質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

4775閲覧

ホスト名からドメインだけを取り出したい

flat

総合スコア617

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

2グッド

1クリップ

投稿2016/03/29 13:22

編集2016/03/30 10:45

ホスト名からドメインの部分だけを取り出したいと思い、まだ途中ですが次のようなコードを書きました。
しかし、ドメインがTLDだけなら話は簡単なのですが、SLDも想定しなければいけないため頭を悩ませています。
とりあえず余計な部分を削ぎ落とすところまでは考えたのですが、ここからSLDが無い場合でもドメインのみの状態にするにはどのような処理が必要でしょうか?

追記
この処理で私が今回行おうとしている事は、サーバーにアクセスしてきたホストのドメインを取得する(だけ)というものです。(正引きで確認済み)
つまりプロバイダなどの通信事業者を経由したアクセスを想定しているので、よく考えると地域型ドメインは考慮しなくても良いです。(多分……)

PHP

1$hostname1 = 'www.example.com'; // example.com 2$hostname2 = 'www.example.co.jp'; // example.co.jp 3$hostname3 = 'xxx.yyy.www.example.tokyo.jp'; // example.tokyo.jp 4$hostname4 = 'www.example.shibuya.tokyo.jp'; // example.shibuya.tokyo.jp 5 6$arr = array_reverse(explode('.', $hostname4), TRUE); 7 8// 地域型ドメインだと4レベルドメインになる事を考慮 9if (count($arr) > 4) {// 3 だったのを 4に変更 10 array_splice($arr, 4);// 3 だったのを 4に変更 11} 12 13// さてここからどうしよう……という状態です。

追記2
ngyukiさんの回答にあるコードを参考に試行錯誤していたのですが、色々と妥協していった結果、今回は省コストであることを優先することにしました。
コードは最終的に次のようになりました。

PHP

1$hostname1 = 'teratail.com'; // teratail.com 2$hostname2 = 'www.example.com'; // example.com 3$hostname3 = 'www.example.jp'; // example.jp 4$hostname4 = 'www.example.co.jp'; // example.co.jp 5$hostname5 = 'xxx.yyy.www.example.ne.jp'; // example.ne.jp 6$hostname6 = 'xxx.yyy.www.example.tokyo.jp'; // tokyo.jp 7$hostname7 = 'tokyo.jp'; // tokyo.jp 8$hostname8 = 'oreore.areare'; // oreore.areare 9 10/** 11 * @param string $hostname ホスト名 12 * @return string 一般的なドメインであればドメイン名を、そうでない場合はunknownを返す 13 */ 14function narrow_down_domain($hostname) { 15 if ($hostname === 'unknown') { 16 return $hostname; 17 } 18 19 $arr = array_reverse(explode('.', $hostname)); 20 21 if (strlen($arr[1]) > 2) { 22 $domain = implode('.', array_reverse(array_slice($arr, 0, 2))); 23 } elseif (strlen($arr[1]) < 3) { 24 $domain = implode('.', array_reverse(array_slice($arr, 0, 3))); 25 } else { 26 $domain = 'unknown'; 27 } 28 29 return $domain; 30} 31 32/** 33 * 都道府県型JPドメインおよび地域型ドメイン(またはそれに類するドメイン)は諦める 34 * つまり、正確に取得することは諦める 35 * $hostname8 のようなケースは、ホスト名を取得する段階の処理で、信頼できないホスト名だった場合は'unknown'を返すようにする事で対処する 36 */
mpyw, KiyoshiMotoki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

この問題、一意な解法はありません。
都道府県ドメインと地域ドメインのリストを全部自分で持つくらいしか(日本の都道府県・地域ドメインを自分で持ったとして、各国の似たような制度はどうしたものですかね)。

ホスト名のうちどこまでがドメイン名かわからないという問題はCookieの安全性問題にもなっていて、Cookie Monsterと呼ばれています。
http://blog.tokumaru.org/2011/09/jpcookie.html

投稿2016/03/29 13:33

編集2016/03/29 13:46
yuba

総合スコア5568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

flat

2016/03/29 14:08

回答して下さりありがとうございます。 リンク先を拝見しましたが、地域型ドメインだと4レベルのドメインになるんですね……。 頭が痛いです。 また、仰るように地域型ドメインと都道府県型ドメインを網羅出来たとしても、外国まで考えるとなると相当骨が折れそうですし、増える度に対応しなければいけないので大変ですね。 国外のものは諦めて例外処理にでも回すのが無難そうかなと思いました……。 完全な解決は諦めて、自分なりに試行錯誤してみます。
guest

0

このコードは半分ネタみたいなもので、正確かどうかもわかりませんが・・・

public_suffix_list というものがあるので、これを利用して、

<?php $cache = '/tmp/public_suffix_list.dat'; if (file_exists($cache) === false) { file_put_contents( $cache, file_get_contents('https://publicsuffix.org/list/public_suffix_list.dat') ); } $list = file($cache); $list = array_map('trim', $list); $list = array_filter($list, 'strlen'); $list = array_filter($list, function ($v) { return substr($v, 0, 2) != '//'; }); $list = array_flip($list); $hosts = [ 'www.example.com', 'www.example.co.jp', 'xxx.yyy.www.example.tokyo.jp', 'www.example.shibuya.tokyo.jp', 'teratail.com', 'tokyo.jp', 'oreore.areare', ]; function detectDoamin($host) { global $list; $arr = explode('.', $host); for ($i=0; $i<count($arr); $i++) { $suffix = implode('.', array_slice($arr, $i)); if (isset($list[$suffix]) === false) { continue; } if ($i > 0) { $domain = implode('.', array_slice($arr, max($i-1, 0))); } else { $domain = $host; } return $domain; } return false; } foreach ($hosts as $host) { $domain = detectDoamin($host); if ($domain === false) { echo "$host => unknown!!!\n"; } else { echo "$host => $domain\n"; } }

次のような結果になります。

www.example.com => example.com www.example.co.jp => example.co.jp xxx.yyy.www.example.tokyo.jp => example.tokyo.jp www.example.shibuya.tokyo.jp => example.shibuya.tokyo.jp teratail.com => teratail.com tokyo.jp => tokyo.jp oreore.areare => unknown!!!

投稿2016/03/29 14:39

編集2016/03/29 14:41
ngyuki

総合スコア4514

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

flat

2016/03/29 15:29 編集

回答して下さりありがとうございます。 public_suffix_list!こんなリストがあるんですね。 私も回答にあるコードを試してみましたが、結果を見る限りではバッチリなように見えます。 まだどの辺りの処理が肝なのかはちょっと分かりませんが、処理を追いながら理解してみようと思います。 そしてやはりというか、リストをそのまま利用するとメモリを結構食いますね……。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問