制作会社から制作会社じゃない会社に転職が決まりました。制作会社で学んだことを残らず記事にしたいと思います。

パンDKOTORI Blogの公式キャラクター「パンD」です。
コーディングPHP海外からのアクセスを振り分ける[php]

海外からのアクセスを振り分ける[php]

2015年01月21日PHP 
海外からのアクセスを振り分ける[php]記事のアイキャッチ画像

海外からのアクセスを判別して別ページに振り分ける方法を紹介します。phpです。

まえがき

この前とある案件で「海外からアクセスがあったら海外用のページに飛ばしたい。でもその海外用のページから日本語ページにリンクを張って日本語のページも見れるようにしたい」という要望を受けました。

この要望を実現するために、クリアすべき点をザックリ挙げると

  • 海外からのアクセスを判別して振り分け
  • 海外用ページから日本語ページにアクセスされた時を判別

この2点です。2つ目はこの記事のタイトルから見れば若干蛇足ですがついでに解説していこうと思います。

海外からのアクセスを判別して振り分けるいくつかの方法

調べたところ、海外からのアクセスを判別する方法の選択肢は3つ程あるようです。

  • 「php」で判別
  • 「.htaccess」で判別
  • 「javascript」で判別

KoToRiはphpを選択しました。

「php」で判別する方法を選択した理由

「php」で判別する方法というのが、ブラウザの設定言語を取得して海外からのアクセスかどうかを判別するという方法です。
なので「海外からのアクセス」というより「外国人からのアクセス」を判別しているといった感じでしょうか。
例えば日本にいるアメリカ人は恐らくブラウザの設定言語は英語でしょう。そういった人も対象に含むことができます。

あと個人的に「.htaccess」や「javascript」より「php」のほうが好きだからです。

一応、「.htaccess」での判別や「javascript」での判別がダメな理由を書いたのですが完全に蛇足なので要らない人は読み飛ばしてください。

蛇足を読み飛ばす

「.htaccess」で判別するのがダメな理由

ダメって分けじゃないんだけどWordPressでサイトを構築していると「.htaccess」に既にWordPressのリダイレクトの記述が書かれてますよね。
そこに変に違うリダイレクトの記述すると元のリダイレクトとコンフリクトしちゃってWordPressで正常にページ閲覧できなくなるという現象に多々遭遇してるのですよ。
なので「.htaccess」以外の選択肢があるならとりあえずそっちを利用したいですね。

また、「.htaccess」で判別する方法自体がKoToRi的には微妙でした。
現在日本国内に割り当てられているIPアドレスを全て(2014年12月18日の時点で202,491,904個位)「.htaccess」に記述してリダイレクトするとか、
カントリーコードで識別して特定の国からのアクセスをリダイレクトする方法もあるけど精度が低そうだったりとか、
なんか現実的じゃないな~と思いました。

この辺は下記に詳しく書いてあります。
http://www.yuzuriha.sakura.ne.jp/~akikan/kaigai/kaigai6.html
http://www.cgis.biz/tools/access/

「javascript」で判別するのがダメな理由

KoToRiはリダイレクト関係を「javascript」や「html」の「meta」タグで行うのは止めたほうが良いと思います。
当たり前なのですが、「javascript」や「html」は一回ブラウザに読み込まれた上で実行されるものなので、一瞬リダイレクト前のページが見えちゃったりするんですよね。
よろしくありません。なので無しです。

海外からのアクセスを「php」で判別して振り分ける方法

phpに用意されている環境変数「HTTP_ACCEPT_LANGUAGE」を利用します。
「HTTP_ACCEPT_LANGUAGE」にはブラウザに設定されている言語が返ってきます。

ここで気をつけてほしいのはブラウザに設定できる言語は1個じゃないということです。

この画像はchromeの言語設定画面です。

languagegif

  • 英語
  • 英語(アメリカ合衆国)
  • 日本語

この3つの言語が設定されているのがわかると思います。
「英語」と「英語(アメリカ合衆国)」の違いはイギリス英語かアメリカ英語かの違いでしょう。

今回紹介するコードでは
優先度がより高く設定されている言語を判別します
「優先度が高い」=「上に表示されている言語」ということです。

例えばChromeは言語をドラッグして並び替えることが可能です。
動作確認の際はブラウザの設定気をつけてください。

では早速、海外からのアクセスを判別する「php」コードを見てみましょう。

<?php
$languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$languages = array_reverse($languages);

$result = '';

foreach ($languages as $language) {
  if (preg_match('/^en/i', $language)) {
    $result = 'English';
    header("Location: /english");
  } elseif (preg_match('/^ja/i', $language)) {
    $result = 'Japanese';
    header("Location: /");
  } 
}
if ($result == '') {
  $result = 'Japanese';
  header("Location: /");
}

2行目の「explode(‘,’, $_SERVER[‘HTTP_ACCEPT_LANGUAGE’])」で取得したブラウザの言語コードを配列に変換してforeachで回すというコードです。
結果、ブラウザの言語コードに”en”が含まれていれば「/english」に飛ばします。
やってることはいたってシンプルですね。

これでブラウザの言語設定によって表示するページを振り分けることができました。

因みにブラウザが送ってくる言語コードの一覧が下記にアップされています。
http://www.futomi.com/lecture/env_var/http_accept_language.html

海外用ページから日本語ページにアクセスした時を判別する

海外用ページから日本語ページにアクセスした時のみ、海外用ページにリダイレクトさせず普通に日本語ページを表示する方法です。
まえがきでも書きましたがこれは蛇足です。

まず「海外用ページから日本語ページにアクセスした時の判別」ですが、これは「php」の「$_GET」を利用すれば良いかと思います。
海外用ページからのリンクは「http://○○○?lang=ja」とでもしてパラメータ渡してやって、上で紹介したコードをちょっと変更して「if文」追加してやれば、
海外用ページからに日本語ページにアクセスした場合は普通に日本語ページを表示する
といったことができます。
今回の要望ではトップページのみ振り分ければ良かったので下記のようなコードで実現できました。

<?php
$languages = explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
$languages = array_reverse($languages);

$result = '';

foreach ($languages as $language) {
  if (preg_match('/^en/i', $language)) {
    $result = 'English';
  } elseif (preg_match('/^ja/i', $language)) {
    $result = 'Japanese';
  } 
}
if ($result == '') {
  $result = 'Japanese';
}

if(is_home()){
$lang = $_GET["lang"];
if(!$lang&&$result=='English'){
    header("Location: /english?lang=en");
}
}

まとめ

今回紹介した海外からのアクセスを「php」で判別する方法は結構主流で、コードの動作確認のためにブラウザの設定を英語にして色々サイトを回ってたんですが言語を選べるサイト等は結構英語サイトに飛ばされました。やはりブラウザの言語を判断基準にしているところが多いと思います。

参考サイト

PHPで表示言語を自動判別 | refirio.org

ありがとうございます。

シェアするみんなシェアしてね

フォローするフォローする

いつもKOTORI Blogをご覧いただきありがとうございます。Facebook、Twitterを通じて、皆様と交流していき色んな情報を共有していければな~と思ってます。お気軽に登録してください!

基本フォロー返します。

RSSを登録する

RSSはこちらから。

follow us in feedly

Feedly使ってる人はこちらから。

Buy me a Beer

動く!パンDのLINEスタンプ
好きな人にアプローチスタンプ
パンDのLINEスタンプ

関連する記事関連する記事も読んでみてね

コメント

  • よしむら

    いつも記事参考にさせていただいております。
    ありがとうございます。

    一つお聞きしたいのですが、こちらのブログでサイドバーに使われている「役に立っている記事」と「新着記事」の切り替え表示ウィジェットはWPのプラグインでしょうか。
    デザインも良くて切り替え表示が便利なので使いたいと思っています。

    よろしくお願いします。

    • kotoriblog

      よしむらさん
      こんにちは!コメントありがとうございます。

      >一つお聞きしたいのですが、こちらのブログでサイドバーに使われている「役に立っている記事」と「新着記事」の切り替え表示ウィジェットはWPのプラグインでしょうか。

      これは自作というかこういうプラグインがあるのではなく
      「WordPress Popular Posts」というプラグインで役に立っている記事を表示させつつ
      jsとCSSでタブにしているだけです。

      使ってるjsはこれ
      /wordpress/wp-content/themes/kotori_2015/js/tab.js

      プラグインのページはこれ
      https://wordpress.org/plugins/wordpress-popular-posts/

      CSSとソースコードはブラウザのデベロッパーツールかなにかで参照していただければと思います☆

      • よしむら

        kotori様

        ご返信ありがとうございます!
        WordPress Popular Postsを使って組み合わせしておられるんですね。

        なるほど、jsとCSSなんですね!全くわかりませんでした(´;Д;`)

        お時間ある時に記事にしていただけますと非常に喜びます。
        いつもありがとうございます。

  • Pingback: PHPでブラウザの使用言語を解析してページを振り分ける方法 | 個人的プログラムの備忘録()

  • わわわ

    こんにちは。
    wordpressマルチサイト下の階層に英語版と日本語版を作成いたしました。
    トップ階層にアクセスすると各ページへ、、と行きたいのですがトップ階層にあるindex.phpに仕込んだのですがリダイレクトループがかかってしまいました、、、そうですよね。。
    不勉強なのですが、どこへ設置すればよいのでしょうか。

    ご教示いただけるとありがたいです。。
    よろしくお願いいたします。

    • kotoriblog

      わわわさん

      こんにちは。グアムでバカンスしていたため、お返事が遅れてしまいました。ごめんなさい。

      わわわさんの仰っている「トップ階層にあるindex.php」とは、テーマのindex.phpの事ではなくWordPressのコアファイルのindex.phpということですか?

      基本的にテーマのindex.phpの一番上に、コードを記述してブラウザ言語を判定してそれぞれのページに振り分けるという使い方になります。

  • yamayama

    はじめまして、こんにちは。
    とてもわかりやすい記事をありがとうございます。こちらを参考に日本語と英語の二言語サイトを作成したのですが(WPは使用していません)、蛇足にもありました「海外用ページから日本語ページにアクセスした時は日本語ページを表示する」が実現できません。。。
    ヒントは書いてくださっているのですが、PHP初心者のため、記述方法がわからず困り果てています。。
    もしよろしければご教授いただけないでしょうか・・。
    よろしくお願い致します。