1

Say I have a list of IDs like so:

http://www.youtube.com/watch?v=KMU0tzLwhbE
http://youtu.be/KMU0tzLwhbE
http://www.youtube.com/watch?v=KMU0tzLwhbE&featured=embedded

I need a function just to grab the ID: KMU0tzLwhbE

I'm working with something like this at the moment:

$url = "http://www.youtube.com/watch?v=KMU0tzLwhbE";
parse_str(parse_url($url, PHP_URL_QUERY ), $youtubeURL);
echo $youtubeURL['v'];

But I need it to also work for the youtube.be link. Any suggestions on how to proceed would be greatly appreciated.

M.Babcock
  • 18,075
  • 5
  • 50
  • 83
Latox
  • 4,442
  • 15
  • 44
  • 73
  • possible duplicate of [Get Youtube Video ID from html code with PHP](http://stackoverflow.com/questions/1773822/get-youtube-video-id-from-html-code-with-php) – mario Dec 31 '11 at 06:40
  • The search box is your friend! See also: [php regex - find all youtube video ids in string](http://stackoverflow.com/q/5830387/433790) Note that there are _lots_ of YouTube URL formats out in the wild. – ridgerunner Dec 31 '11 at 07:55

5 Answers5

2

Try something like:

$pattern = '/(?:(?:\?|&)v=|\/)([A-Za-z0-9]{11})/';
$url     = 'http://www.youtube.com/watch?v=KMU0tzLwhbE';

preg_match($pattern, $url, $matches);

echo $matches[1];
Ayman Safadi
  • 11,348
  • 1
  • 25
  • 41
1

Do not use regexes for this. URIs have a particular grammar and PHP gives you the tools required to parse each URL properly. See parse_url() and parse_str().

<?php
function getYoutubeVideoId($url) {
    $urlParts = parse_url($url);

    if($urlParts === false || !isset($urlParts['host']))
        return false;

    if(strtolower($urlParts['host']) === 'youtu.be')
        return ltrim($urlParts['path'], '/');

    if(preg_match('/^(?:www\.)?youtube\.com$/i', $urlParts['host']) && isset($urlParts['query'])) {
        parse_str($urlParts['query'], $queryParts);

        if(isset($queryParts['v']))
            return $queryParts['v'];
    }

    return false;
}
Andrew Moore
  • 87,539
  • 30
  • 158
  • 173
  • 3
    "Do not use regexes for this" --- it depends on the task. In most cases the one-liner (regex) is enough, rather than your 10-lines solution. Don't overcomplicate and overengineer – zerkms Dec 31 '11 at 05:30
  • It does depend on the task. The general rule of thumb is: if it has grammar and a lexer can do the job, do not use a regular expression. – Andrew Moore Dec 31 '11 at 05:32
  • 1
    uhm, just curious, where this rule came from? The rule is - solve the task with the appropriate tool. And if the tool is appropriate or not depends on the task's nature. If regex (and its possible drawbacks) satisfy you - then use short solution. KISS – zerkms Dec 31 '11 at 05:33
  • @zerkms At the end of the day, if your 10 liner solution is **easier to maintain and read** than your regex (which is most certainly the case here if you want to handle both short and long YouTube URIs with a good degree of confidence), it should be the adopted solution. – Andrew Moore Dec 31 '11 at 05:35
  • Btw, you started this: `http://not-youtube.com/?v=gotyou` --- and your 10 lines grammar-lexer-magic fails – zerkms Dec 31 '11 at 05:35
  • @zerkms: Yes, indeed it does. However, it doesn't fail with `http://www.youtube.com/watch?v=KMU0tzLwhbE&featured=embedded`. The proper regex for all this mess would be `(?:(?:youtu.be/|(?:\?|&)v=)([A-Za-z0-9]+))`. Hardly maintainable. Adding domain checks to that, forget it. Adding domain checks to my solution, relatively easy. – Andrew Moore Dec 31 '11 at 05:43
  • @Andrew Moore: so `http://youtube.com/?hahahav=gotyou and your regex is broken.` --- the other solutions are broken so you downvoted them but when yours fails it is ok? Am I right? Could you add domain checks to your solution otherwise it just doesn't fair (as long as we speak about maintainability). – zerkms Dec 31 '11 at 05:45
  • `$urlParts['hosts']` --- there is no such item there – zerkms Dec 31 '11 at 05:48
  • @zerkms: Domain checks added. Also, there are other LEGITIMATE YouTube parameters that ends with v that exists (`pv` springs to mind). Also, Robert's solution fails when dealing with `http://www.youtube.com/watch?v=KMU0tzLwhbE&featured=embedded`, a perfectly valid and common URL format. – Andrew Moore Dec 31 '11 at 05:50
  • @Andrew Moore: actually I don't advocate their solutions, but for now I see worked solution and it took 25 minutes to get it. Still don't see how your 10 lines are better readable than regex 1 line – zerkms Dec 31 '11 at 05:51
  • @zerkms: Are they easier to maintain? I think we both know the answer to that question. – Andrew Moore Dec 31 '11 at 05:51
  • `http://youtu.be/KMU0tzLwhb/or-really?` --- your will return wrong result. One more edge case to handle – zerkms Dec 31 '11 at 05:52
  • @zerkms: Yup, it does. [And it also breaks YouTube](http://youtu.be/KMU0tzLwhb/or-really?). Ain't my problem at that point. There is no 100% solution. – Andrew Moore Dec 31 '11 at 05:54
  • 1
    So you *did* end up using RegEx after all... interesting. – Ayman Safadi Dec 31 '11 at 05:56
  • @AymanSafadi: For host checking, sure. At that point you are not parsing anything, you are just checking if the string matches a specific set of conditions. Query strings, URIs should not be **parsed** using Regex. You can however **match** host names. You will also notice that I am not using a regular expression to extract (read **parse**) the host name from the absolute URI, but I am simply matching against what has already been extracted by PHP's lexer. – Andrew Moore Dec 31 '11 at 05:57
  • `http://youtube.com/?hahahav=gotyou` --- it also points to nowhere, but you used it as a proof of bad solution. So did I – zerkms Dec 31 '11 at 05:57
1

Try this:

$video_url = "http://www.youtube.com/watch?v=KMU0tzLwhbE"; // http://youtu.be/KMU0tzLwhbE
$url_parts = parse_url($video_url);

if (isset($url_parts["query"]) && (strpos($url_parts["query"], "v") !== false)) {
  parse_str($url_parts["query"], $vars);

  // Handle full URLs with query string like 'http://www.youtube.com/watch?v=KMU0tzLwhbE'
  if (isset($vars["v"]) && $vars["v"]) {
    $video_code = $vars["v"];

  // Handle the new short URLs like 'http://youtu.be/KMU0tzLwhbE'
  } else if ($url_parts['path']) {
    $video_code = trim($url_parts['path'], '/');
  }
}
Siva
  • 1,093
  • 2
  • 14
  • 25
0

Simply im using this, because url is same for all youtube videos

$ytid = str_replace('http://www.youtube.com/watch?v=', '','http://www.youtube.com/watch?v=bZP4nUFVC6s' );

you can check for the other url variations as well

Lasith
  • 567
  • 1
  • 5
  • 17
0

The first group of a preg_match using (?:(?:\?|&)v=|youtu\.be\/)(.+?)(?:$|&) as the pattern.