1

I have a text input field for a user to input a video url, for example: https://www.youtube.com/watch?v=d4bv2NaO9fQ (this is just a video I selected at random to test)

I then want to extract the id from the url to use to embed the video. I've been following KAD's example using regex here: How to embed YouTube videos in PHP?

In the code below I am taking $videourl from a customizer field in WordPress and trying to apply the regex to it, but it just returns an empty array. If I swap out $videourl for the hardcoded $url1 that you can see in the code below, then it works perfectly.

As you can see I am echoing both the urls and what that returns looks identical:

<div>
            https://www.youtube.com/watch?v=d4bv2NaO9fQ     </div>
            
                    <div>
            https://www.youtube.com/watch?v=d4bv2NaO9fQ         </div>
<?php 
$customizer_video_repeater = get_theme_mod('video-repeater', json_encode( array()) );
      $customizer_video_repeater_decoded = json_decode($customizer_video_repeater);
      foreach($customizer_video_repeater_decoded as $repeater_item){

$videourl = $repeater_item->text;
?>

    <div class="videocontainer">
    <div class="videoresponse">
    <?php 
        if ($videourl) {
            ?>
            <div>
            <?php echo $videourl ?>
            </div>
            
            <?php 
        $url1 = "https://www.youtube.com/watch?v=d4bv2NaO9fQ";?>
        <div>
            <?php echo $url1 ?>
            </div>
            <?php 
            
    preg_match("/^(?:http(?:s)?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:.*&)?v(?:i)?=|(?:embed|v|vi|user|shorts)\/))([^\?&\"'>]+)/u", $videourl , $matches);
        
            print_r ($matches);
        
        ?>
        
        <iframe width="356" height="200" src="https://www.youtube.com/embed/<?php echo $matches[1] ?>" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
        <?php } ?>
        </div>
        </div>
      <?php } ?>

I don't know if it coming from an input field means it is encoded incorrectly for regex in some way? I've looked at the answer to a similar question here: Input from form doesn't match regex, but hard-coded string does

and added the /u to the end of my preg_match but it doesn't seem to have made any difference.

Any ideas would be a great help, thanks!

Lv1983
  • 67
  • 1
  • 9
  • why would you not parse it in javascript as its added into the input? – Lawrence Cherone Jan 07 '22 at 15:39
  • 1
    Have you tried using `trim()` on the input before passing it to your regex? It's also better do do `var_dump($videourl);` when debugging so you can see if there are any leading white spaces etc (there could still be some non-printable characters that causes issues though, so trim is still good to do) – M. Eriksson Jan 07 '22 at 16:00
  • Thanks LawrenceCherone is that a better way to do it? Can you point me in the direction of how I might do that? @M.Eriksson Thanks for the advice, var_dump is much better! I can see that my input string is 58 characters as opposed to 43 on the manual one so there is definitely something extra in there. I have tried applying the trim() function though and it isn't making any difference. Not sure why not... – Lv1983 Jan 07 '22 at 16:35
  • If you get more data than you should from your input, I would start by checking how you're actually sending the data. If you post all relevant HTML and JS, it would help. It's always better to fix the cause than the symptom. – M. Eriksson Jan 07 '22 at 20:30
  • @M.Eriksson so I have got this working now by using url_encode on my string to see the characters that were in it (%26, %23 and %3B which represent & # and ; respectively), I was then able to use str_replace to remove them after which it worked. As you say though that doesn't solve the root of the problem, I am wondering if the json_encode/decode could be affecting it? – Lv1983 Jan 09 '22 at 09:51

1 Answers1

0

You can omit the anchor ^ at the start of the pattern, and update the pattern a bit as there are unnecessary groups, escapes and too broad matches.

preg_match(
    "/(?:https?:\/\/)?(?:www\.)?(?:m\.)?(?:youtu\.be\/|youtube\.com\/(?:(?:watch)?\?(?:\S*&)?vi?=|(?:embed|v|vi|user|shorts)\/))([^?&\"'>\s]+)/",
    $url,
    $matches
);

The value for the param v is in capture group 1.

Regex demo

Sam Holguin
  • 553
  • 2
  • 9
  • 24
The fourth bird
  • 154,723
  • 16
  • 55
  • 70