PHPで相対パスから絶対URL(URI)を作成する

HTMLページをパースしてURLを取り出す処理を書いていたのですが、ページ内のリンクなどが全部絶対URLで記述されていれば非常に楽なのですが、現実としてそうでもなく、ページによっては相対パスで書かれていたりして、正規表現で偏にリンクからURLを抜き出すだけではうまくできませんでした。

そこで少しググってみたら

PHPで相対パスから絶対URL(URI)を作成する|PHPプログラムメモ|プログラムメモ

という記事を発見!おぉ、これは便利!
と思って使わせてもらおうと思ったのですが、いくつかテストしてみて、相対パス処理で不備があるなーと思ったところがあったのでちょっと改良させてもらいました。

37~38行目は正直いらない気がしたのですが、 PHP 5.3 のCLIでWindows上でテストした際に、なぜか \/ (アルファベットのVではなく、\/ ) で出力されたのが気になったので、無駄かもしれないけどあえて記述。
あと $parse の初期化もここまでする必要ないけど、念のためNotice対策を…w

相対パスから絶対URLする関数


PHP:
  1. <?php
  2. /**
  3. * 相対パスから絶対URLを返します
  4. *
  5. * @param string $base ベースURL(絶対URL)
  6. * @param string $relational_path 相対パス
  7. * @return string 相対パスの絶対URL
  8. * @link http://blog.anoncom.net/2010/01/08/295.html
  9. * @link http://logic.stepserver.jp/data/archives/501.html
  10. */
  11. function createUri( $base = '', $relational_path = '' ) {
  12.    
  13.     $parse = array (
  14.         'scheme' => null,
  15.         'user' => null,
  16.         'pass' => null,
  17.         'host' => null,
  18.         'port' => null,
  19.         'path' => null,
  20.         'query' => null,
  21.         'fragment' => null,
  22.     );
  23.     $parse = parse_url ( $base );
  24.    
  25.     // パス末尾が / で終わるパターン
  26.     if ( strpos( $parse['path'], '/', ( strlen( $parse['path'] ) - 1 ) ) !== FALSE ) {
  27.         $parse['path'] .= '.'// ダミー挿入
  28.     }
  29.     if ( preg_match ( '#^https?\://#', $relational_path ) ) {
  30.         // 相対パスがURLで指定された場合
  31.         return $rel_path;
  32.     } elseif ( preg_match ( '#^/.*$#', $relational_path ) ) {
  33.         // ドキュメントルート指定
  34.         return $parse['scheme'] . '://' . $parse ['host'] . $relational_path;
  35.     } else {
  36.         // 相対パス処理
  37.         $basePath = explode ( '/', dirname ( $parse ['path'] ) );
  38.         $relPath = explode ( '/', $relational_path );
  39.         foreach ( $relPath as $relDirName ) {
  40.             if ($relDirName == '.') {
  41.                 array_shift ( $basePath );
  42.                 array_unshift ( $basePath, '' );
  43.             } elseif ($relDirName == '..') {
  44.                 array_pop ( $basePath );
  45.                 if ( count ( $basePath ) == 0 ) {
  46.                     $basePath = array( '' );
  47.                 }
  48.             } else {
  49.                 array_push ( $basePath, $relDirName );
  50.             }
  51.         }
  52.         $path = implode ( '/', $basePath );
  53.         return $parse ['scheme'] . '://' . $parse ['host'] . $path;
  54.     }
  55. }



テストケース

ベースURL
 http://example.com/path/to/url

相対パス
  • /
  • /index.html
  • /foo/bar/baz/
  • ./foo/bar/baz
  • ../../../foo/bar/baz/index.html
  • foo/bar/baz.html
  • foo/bar/baz/../index.html

テストコード


PHP:
  1. <?php
  2. $base = 'http://example.com/path/to/url';
  3.  
  4. $pathes[] = '/';
  5. $pathes[] = '/index.html';
  6. $pathes[] = '/foo/bar/baz/';
  7. $pathes[] = './foo/bar/baz';
  8. $pathes[] = '../../../foo/bar/baz/index.html';
  9. $pathes[] = 'foo/bar/baz.html';
  10. $pathes[] = 'foo/bar/baz/../index.html';
  11.  
  12. foreach ( $pathes as $path ) {
  13.     echo createUri($base, $path) . "\n";
  14. }



結果

こんな感じ

http://example.com/

http://example.com/index.html


http://example.com/foo/bar/baz/


http://example.com/path/to/foo/bar/baz


http://example.com/foo/bar/baz/index.html


http://example.com/path/to/foo/bar/baz.html


http://example.com/path/to/foo/bar/index.html


No TweetBacks yet. (Be the first to Tweet this post)

No related posts.

関連記事はYARPP関連記事プラグインによって表示されています。

Leave a Reply

Get Adobe Flash playerPlugin by wpburn.com wordpress themes