Shoelaced
Shoelaced

Reputation: 881

Undefined Offset / PHP error

I'm using a WordPress plugin that contains this function, but the plugin developers are not being particularly quick to respond.

It is supposed to get the video ID from a YouTube URL, but instead I'm getting an "Undefined Offset: 1" error. Is there a coding error that I'm missing?

Here is the function:

function youtube_id_from_url($url) {
    $pattern =
        '%^# Match any youtube URL
        (?:https?://)?  # Optional scheme. Either http or https
        (?:www\.)?      # Optional www subdomain
        (?:             # Group host alternatives
          youtu\.be/    # Either youtu.be,
        | youtube\.com  # or youtube.com
          (?:           # Group path alternatives
            /embed/     # Either /embed/
          | /v/         # or /v/
          | /watch\?v=  # or /watch\?v=
          )             # End path alternatives.
        )               # End host alternatives.
        ([\w-]{10,12})  # Allow 10-12 for 11 char youtube id.
        $%x'
        ;
    $result = preg_match($pattern, $url, $matches);
    if (false !== $result) {
        return $matches[1];
    }
    return false;
}

I tried doing a print_r to see what the array $matches looks like, and it seemed to just be an empty array, so I tried echoing $result and it returned 0, which would mean that preg_match() isn't finding a match, correct? If so, I can figure out what's wrong with $pattern that would make it return 0.

UPDATE: Apparently there's some other function that is taking the URL and making a link out of it and then saving that as the $url variable. If I echo the $url variable it prints as <a href="youtube url">youtube url</a>.

So that explains the error but how can I modify the regex to accommodate the html markup?

Upvotes: 1

Views: 197

Answers (1)

Brian Gottier
Brian Gottier

Reputation: 4582

preg_match will only return FALSE if an error occurs, and in this case you're probably wanting to know if there was either matches or no matches. So you should be able to switch the line:

if (false !== $result) {

to

if ( isset( $matches[1] ) ) {

or

if ( $result && isset( $matches[1] ) ) {

As Phil points out, all you really need is:

if( $result ) {

Full revised function complete with Phil's modification to the regex:

function youtube_id_from_url($url) {
    $pattern =
        '%^# Match any youtube URL
        (?:https?://)?  # Optional scheme. Either http or https
        (?:www\.)?      # Optional www subdomain
        (?:             # Group host alternatives
          youtu\.be/    # Either youtu.be,
        | youtube\.com  # or youtube.com
          (?:           # Group path alternatives
            /embed/     # Either /embed/
          | /v/         # or /v/
          | /watch\?v=  # or /watch\?v=
          )             # End path alternatives.
        )               # End host alternatives.
        ([\w-]{10,12})  # Allow 10-12 for 11 char youtube id.
        &?.*$%x'
        ;
    $result = preg_match($pattern, $url, $matches);
    if ($result) {
        return $matches[1];
    }
    return false;
}

Upvotes: 1

Related Questions