Youtube動画をホームページに埋め込むことは今ではよくあります。
Youtubeから「共有」メニューを選択すると、コピーペーストだけで貼り付けができます。
↓このような感じにの貼り付けです。
ただ、ここで疑問に思いました。
PHPを使ってYoutubeのURLだけで、動画の貼り付けができないものだろうか?
埋め込みコードを使えば事足りることですが、URL投稿だけで自動処理してくれれば、利便性が向上します。
そこで、YoutubeのURLから埋め込みコードを自動生成する方法について考えてみました。
原理は動画のIDコードを抽出できればOK
YoutubeのURLは以下のようになります。
https://www.youtube.com/watch?v=XcMS77O6XIw
これに対し、Youtubeの埋め込みコードは以下のようになります。
<iframe width="560" height="315" src="https://www.youtube.com/embed/XcMS77O6XIw" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
この2つを見比べていたら、共通点があることがわかりました。
どちらにも動画IDを指定している点です。
URLの場合
www.youtube.com/watch?v=XcMS77O6XIw
埋め込みコードの場合
www.youtube.com/embed/XcMS77O6XIw
どちらにも動画IDが埋め込みされております。
URLからこのIDを取り出し、埋め込みコードに動画IDを設置すれば、自動で動画埋め込みができます。
まずは試作してみました。
そこでURLから動画IDを取り出し、埋め込みコードにあてがう処理を試作してみました。
サンプルを見ていただくと、youtubeのURLを再生可能な埋め込みコードに変換しています。
ソースはこちら
<?php
$youtube = $data = null;
if (isset($_REQUEST["text"]) == true)
{
/** 入力内容を取得 */
$data = $youtube_url = $_REQUEST["text"];
/** HTMLコードをエンティ */
$data = htmlspecialchars($data, ENT_QUOTES);
/** コード変換 */
$youtube_url = substr($youtube_url, (strpos($youtube_url, "=")+1));
$youtube = "<iframe width=\"100%\" height=\"400\" src=\"https://www.youtube.com/embed/${youtube_url}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>";
}
?>
<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>テスト</title>
<style type="text/css">
article
{
width: 600px;
margin-top: 100px;
margin-right: auto;
margin-left: auto;
border: 1px solid #CCC;
text-align: center;
padding: 30px;
border-radius: 6px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
}
div
{
text-align: center;
padding-top: 40px;
}
</style>
</head>
<body>
<article>
<form action="" method="post">
<p>Youtube URLを入力してください。</p>
<input name="text" type="text" value="<?php echo $data; ?>" style="width:90%;">
<input name="" type="submit">
</form>
<div><?php echo $youtube; ?></div>
</article>
</body>
</html>
動画IDの取り出し方
動画IDを取り出しているのは以下の部分です。
$youtube_url = substr($youtube_url, (strpos($youtube_url, "=")+1));
PHPの文字抽出処理を使って取り出しています。
substr()関数
substrは文字列から一部の文字列を抽出する関数です。
引数は以下の通りです。
substr(①文字列, ②取得開始位置, ③抽出文字数)
①文字列は今回の場合は、「https://www.youtube.com/watch?v=XcMS77O6XIw」です。
②取得開始位置は、文字取得を始める位置になります。
例だと動画IDの位置は、32文字目になります。
ただし、https:// をつける場合、つけない場合があります。
https://をつけない場合は24文字目になります。
③抽出文字数は、指定した文字数を抽出します。省略すると②の位置から後ろ全部取得します。今回の場合は後ろ全部取得するため、省略します。
今回の場合、②の取得開始位置が32文字目、24文字目と変動するため、固定値では設定できません。
そこで、特定文字を検出してその文字から取得するようにします。
その文字とは「=」です。
Youtubeの動画URLには必ず「=」がつきます。
そして「=」の次が動画IDコードになります。
「=」の次の文字から抽出とすればよいのです。
strpos()関数
strposは、特定文字が指定文字列の何文字目かを調べる関数です。
引数は以下の通りになります。
strpos(①検索文字列, ②検索したい文字, ③任意検索開始位置)
①文字列は今回の場合は、「https://www.youtube.com/watch?v=XcMS77O6XIw」です。
②の検索したい文字は、今回の場合「=」になります。
③は検索文字と重複が発生する場合などに、抽出開始位置をずらすために使用します。今回は重複文字がないため省略します。
+1をしている理由
$youtube_url = substr($youtube_url, (strpos($youtube_url, “=”)+1));
strpos()で、「=」文字のある位置を取得し、そこから動画IDを抽出しています。
ただ、このままだと「=」を含んで抽出してしまうため、+1をして動画IDの先頭から抽出しています。
完成完成!と思っていたら、落とし穴がありました・・・
思ったより簡単にできたー。
と思っていたら、例外がありました。
それがこちらです。
Youtube URLには短縮URLパターンもありました。
ブラウザのURL欄に表示されるURLのほかに、Youtubeには短縮URLがあることがわかりました。
この短縮URLを先ほどのサンプルにあてがってみると、当然正しく動作しません。
それもそのはずです。
このURLには「=」がありません。
そのため誤動作していました。
そこで、短縮URLでも動作するバージョンを作ってみました。
それがこちらです。
従来のURLでも、短縮URLでもどちらでも動作します。
ソースはこちらです
<?php
$youtube = $data = null;
if (isset($_REQUEST["text"]) == true)
{
/** 入力内容を取得 */
$data = $youtube_url = $_REQUEST["text"];
/** HTMLコードをエンティ */
$data = htmlspecialchars($data, ENT_QUOTES);
if (strpos($youtube_url, "watch") != false) /* ページURL ? */
{
/** コード変換 */
$youtube_url = substr($youtube_url, (strpos($youtube_url, "=")+1));
}
else
{
/** 短縮URL用に変換 */
$youtube_url = substr($youtube_url, (strpos($youtube_url, "youtu.be/")+9));
}
$youtube = "<iframe width=\"100%\" height=\"400\" src=\"https://www.youtube.com/embed/${youtube_url}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>";
}
?>
<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>テスト</title>
<style type="text/css">
article
{
width: 600px;
margin-top: 100px;
margin-right: auto;
margin-left: auto;
border: 1px solid #CCC;
text-align: center;
padding: 30px;
border-radius: 6px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
}
div
{
text-align: center;
}
</style>
</head>
<body>
<article>
<form action="" method="post">
<p>Youtube URLを入力してください。(共有URLにも対応)</p>
<input name="text" type="text" value="<?php echo $data; ?>" style="width:90%;">
<input name="" type="submit">
</form>
<div><?php echo $youtube; ?></div>
</article>
</body>
</html>
URLの違いで処理を判別しています。
従来のURLには「watch」パラメータが付属しています。
そこで、「watch」があったら従来の処理、なかったら短縮URLの処理と判断しています。
if (strpos($youtube_url, "watch") != false) /* ページURL ? */
短縮URLの場合は、別の文字列で動画ID位置を判定
短縮URLにも動画IDが付属しています。
ただ記述が違うため、strposで、別の文字列で位置を判定します。
$youtube_url = substr($youtube_url, (strpos($youtube_url, "youtu.be/")+9));
動画IDは、短縮ドメインの後に来るため短縮ドメインを検索キーとしました。
「youtu.be/」
「/」でもよいような感じもしますが、「https://」と重複するため、ドメインを交えた形にしました。
+9としているのは「youtu.be/」文字列が9文字あるためです。
+9することで、動画ID位置から取得できます。
今度こそ大丈夫と思ったら、まだ例外がありました。
今度こそ大丈夫と思ったのですが、まだ例外がありました。
それは、埋め込みコード(iframeタグ付きのコード)を設置した場合です。
この場合は、何も処理する必要がなくそのまま表示すればよいのですが、サンプル②のパターンだとエラーになります。
そこで、iframeタグ付きのコードを投稿した場合は「何もしない」ように修正しました。
ソースはこちらです
<?php
$youtube = $data = null;
if (isset($_REQUEST["text"]) == true)
{
/** 入力内容を取得 */
$data = $youtube_url = $youtube = $_REQUEST["text"];
/** HTMLコードをエンティ */
$data = htmlspecialchars($data, ENT_QUOTES);
if (strpos($youtube_url, "iframe") != true) /* フレームでない ? */
{
if (strpos($youtube_url, "watch") != false) /* ページURL ? */
{
/** コード変換 */
$youtube_url = substr($youtube_url, (strpos($youtube_url, "=")+1));
}
else
{
/** 短縮URL用に変換 */
$youtube_url = substr($youtube_url, (strpos($youtube_url, "youtu.be/")+9));
}
/** youtube 表示状態に変換 */
$youtube = "<iframe width=\"100%\" height=\"400\" src=\"https://www.youtube.com/embed/${youtube_url}\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>";
}
}
?>
<!doctype html>
<html>
<head>
<meta charset="shift_jis">
<title>テスト</title>
<style type="text/css">
article
{
width: 600px;
margin-top: 100px;
margin-right: auto;
margin-left: auto;
border: 1px solid #CCC;
text-align: center;
padding: 30px;
border-radius: 6px;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
}
div
{
text-align: center;
padding-top: 40px;
}
</style>
</head>
<body>
<article>
<form action="" method="post">
<p>Youtube URLを入力してください。(共有URL、iframeにも対応)</p>
<input name="text" type="text" value="<?php echo $data; ?>" style="width:90%;">
<input name="" type="submit">
</form>
<div><?php echo $youtube; ?></div>
</article>
</body>
</html>
処理をする前にiframeがあったら何もしないようにしています
if (strpos($youtube_url, "iframe") != true)
今回の場合は、埋め込みコードそのままなので、iframeタグがあった場合は何もせずそのまま表示するようにしています。
細かな例外処理はまだ必要ですが、大筋YoutubeのURL加工に対応できました。
テストして例外を見つけたら対応処理を追加。それがプログラム開発の重要な部分です。
プログラム開発は、文字通り机上で設計します。
ただ、チェック時に動作させてみると「例外」を見つける場合があります。そのような場合、例外に対応する処理を追加します。
以下に「例外」を見つけるかがプログラム開発で重要な要素です。
なぜならば、例外動作での不具合がなくなるためです。
今回URLから動画IDを抽出するだけのプログラムでしたが、少なくともYoutubeのURLに相当等するものが3種類あることがわかりました。
3種類のURLに対応できる処理が必要ということがチェック段階で見つけることができました。
厳しめの目線でチェックすることもよいプログラムを作成するうえでは大事なのです。