ブログ

  • 【書評】たったコレだけでPHPプログラミングが理解できる本

    ■ 書評対象 たったコレだけでPHPプログラミングが理解できる本  大家正登(著)

    ■ 良い点

    ・ 説明が易しい
    ・ 図がわかりやすい
    ・ 基礎からDB(SQL)およびセッションまで扱っている
    ・ PDOを扱っている
    ・ 要点が絞られている

    ■ 悪い点

    ・ 若干、癖のあるコードがある
    ・ 誤字脱字が少々

    ■ 総評

    PHP初心者の総復習に向いた一冊です。基本からデータベース(SQL)そして、セッションまで扱っています。

    堅苦しい文法書ではなく、軽い読み物風のため、比較的、楽に読み進められます。SQLにも詳しい内容になっているので、SQLに不安のある人には特にオススメです。

    内容的には、それぞれの章のテーマに沿った、アプリケーションを作成するつくりになっています。

    ホテルの予約システムや、口コミサイト、ショッピングカートなどの作成の概要を通して、PHPの重要ポイントを学ぶことができます。

    ただ、書籍内のサンプルコードは、一部省略されている箇所もあるので、きっちり学びたい人は、 コードをダウンロードしてじっくり学習するのが良いと思います。

  • 【PHP】__FILE__や$_SERVER[‘SCRIPT_NAME’]等の違い

    PHPでスクリプトを書いていると、絶対パスやら相対パスを取得することが多々あります。

    PHPの定数やグローバル変数には、それらのパスを返すものがあるのですが、若干、ややこしいです。そこで、少しまとめてみました。

    なお、以下の例は、CORESERVERでの結果を表示しています。

    ■ まず、定数から。

    __FILE__

    これは、「__FILE__」が記述されたファイルそのものの絶対パスを返します。インクルードされるファイルならそのファイルです。
    例:/virtual/account/public_html/examle.com/foo/bar.php

    次に、

    dirname(__FILE__) 又は __DIR__

    これは、「dirname(__FILE__)」が記述されたファイルのディレクトリまでの絶対パスを返します。最後はスラッシュは付かないです。
    例:/virtual/account/public_html/examle.com/foo

    ■ ここからは、$_SERVER変数です。

    $_SERVER['SCRIPT_FILENAME']

    現在実行しているスクリプトの絶対パス。__FILE__とは異なり、全体としての実行ファイルの絶対パスを指しします。
    例:/virtual/account/public_html/examle.com/foo/filename.php

    __FILE__は、それが記述されたファイル名であり、インクルードされるファイルであるならそのインクルードされるファイルを指します。

    これに対し、$_SERVER[‘SCRIPT_FILENAME’]は、URL(と同等とも言うべき)の絶対パスを返します。つまり、インクルードする側のファイル名です。

    なお、mod_rewriteでURLの読み替えを行っていても、読み替え前の素のファイル名を返すので注意が必要です。

    $_SERVER['SCRIPT_NAME']

    これは、現在のスクリプトのパス。ドメイン下のディレクトリからファイル名までのパスとなります。?以後のパラメーターがつく場合には、その部分は無視します。
    なお、mod_rewriteの場合は、読み替え前のファイルです。
    例:/foo/filename.php

    $_SERVER['PHP_SELF']

    これは、現在実行しているスクリプトのファイル名です。$_SERVER[‘SCRIPT_NAME’]とほぼ同じです。ただし、?以後にパラメーターが付く場合、そのパラメーターも表示してしまいXSSの脆弱性につながるとのこと。
    例:/foo/filename.php

    つまり、パラメーター部分にJavaScriptを仕込まれると、ブラウザ上で実行してしまう危険性があるというわけです。使う場合には、htmlspecialchars等でサニタイズすることが必要とのこと。

    ■ require_once()について

    require_once()

    最後に、ファイルを読み込む処理の方である、require_once()についてですが、これは、require_once()が実行されるファイル全体を起点として、ファイルの読込を行います。

    そのため、ディレクトリ階層が違う複数のファイルからインクルードされる特定のファイルにおいて、require_once()をする場合には注意が必要です。

    その場合には、一度、__FILE__を利用して絶対パスに修正してから使います。

    $path = dirname(__FILE__).'/../../../data/init.php';
    require_once($path);

    なお、../の付いた相対パスだと見づらい場合には、realpath()関数で正規の絶対パスに変更することも可能です。

    $path = realpath(dirname(__FILE__).'/../../../data/init.php');

    以上です。

  • 【JavaScript】JSONのデータを読み込む方法【Ajax】

    AjaxとPHPを連携させていて、複数のデータをPHPからAjax側に送りたい場合、どのようにデータを送ればスマートなのか考えてみた。

    というか、ある本を読んで気づいたのだが、PHP側からJSONのデータ形式でAjaxに送れば良いんじゃないかと。

    今までは単なるテキスト形式で1つのテキストを送っていた。複数のデータを送りたいときは、特定の記号をいれて、その前後でsplitして区切って複数化していた。

    しかし、JSONを使えば、複数のデータをオブジェクト形式でおくれるのではないか。

    ネットで調べてみると、実際、そういう使い方が多くなされているみたい。というかそれが普通なんですね。

    となると、Ajax側では、受けたそのデータをどう扱うのか?

    調べてみると、ibmの記事に次のようにあった。
    http://www.ibm.com/developerworks/jp/web/library/wa-ajaxintro10/

    var people =
      { "programmers": [
        { "firstName": "Brett", "lastName":"McLaughlin" },
        { "firstName": "Jason", "lastName":"Hunter" },
        { "firstName": "Elliotte", "lastName":"Harold" }
       ],
      "authors": [
        { "firstName": "Isaac", "lastName": "Asimov" },
        { "firstName": "Tad", "lastName": "Williams" },
        { "firstName": "Frank", "lastName": "Peretti" }
       ],
      "musicians": [
        { "firstName": "Eric", "lastName": "Clapton" },
        { "firstName": "Sergei", "lastName": "Rachmaninoff" }
       ]
      }

    何も複雑なことはありません。people に、これまで説明してきた JSON フォーマットのデータが含まれるようになっただけです。だたしデータは明らかに便利なフォーマットにはまだなっていないので、この変更に大きな意味はありません。

    データにアクセスする

    一目ではわからないかもしれませんが、上記の長々としたストリングは単なる配列なので、この配列をJavaScript 変数に組み込めば簡単にアクセスできるようになります。配列を区切るには、ピリオド区切り文字を使うだけで済みます。以上のことから、programmersリストの最初のエントリーに含まれる姓にアクセスするには、JavaScript で以下のようなコードを使います。

    people.programmers[0].lastName;

    ここまで引用。

    受け取ったデータを変数に入れ(オブジェクト化)、そうしたら、ピリオド区切りで配列のようにアクセスできるようです。

    これは便利です。ただ、本当にこれで出来るのかな?

    ちなみに、JSONの受け取り方について、レガシーな方法だと、evalを使っていたりする。

    the_object = eval( "(" + http_request.responseText + ")" );

    また、最近では、JSON.parse()メソッドを使う方法もあるみたいです。

    var json = JSON.parse(xhr.responseText);

    ■ 追記

    書いていて気づきましたが、AjaxでPHPから受けるときは、上記ibmの方法だけではダメなようですね。やはり、evalかJSON.parseを使う等するのが定石らしいです。

    なお、PHP側では、json_encodeを使うと、便利なようです。
    http://www.php.net/manual/ja/function.json-encode.php

    //jsonを出力
    header('Content-type: application/json');
    echo json_encode($val); //$valは(連想)配列

    以上です。

  • 【PHP】stdClassとは?

    プロになるためのPHPプログラミング入門を読んでいると、オブジェクトの作成場面で知らない語法がでてきた。

    $obj = new stdClass();

    このstdClassとは何ぞや?ということで早速、調べてみました。

    解答は、PHPマニュアルに。
    http://php.net/manual/ja/language.oop5.basic.php

    上記マニュアルのノート部分に次のような記述があります。英語なので意訳してます。

    『stdClassは、PHPのデフォルトのオブジェクト(クラス)なんだ。
    stdClassは、どんなプロパティもメソッドも持たず、親クラスも無いんだよ。そして、マジックメソッドをサポートしてないし、インターフェースも無いんだ。
    スカラー値や配列をオブジェクトして扱いたいとき、stdClassをインスタンス化することができるよ。一般的なオブジェクトをインスタンス化したい時、stdClassを使うことができるんだ。』

    つまり、次のように、クラスが無くとも、とりあえずオブジェクトを作りたいときに便利に使える代物のようです。

    $obj = new stdClass();
    $obj->val1 = 123;
    $obj->val2 = 'abc';

    でも、あまり見かけないですよね。古い使い方なのでしょうか?それともオブジェクト指向のコードだと頻繁に使うものなのかな。

  • 【PHP】セッションファイルの保存先を変更する方法【CORESERVER】

    PHPのセッションファイルの保存場所変更についての覚書です。

    セッションファイルの保存場所を変更するには、「session_save_path」関数を用いることができます。
    http://www.php.net/manual/ja/function.session-save-path.php

    たとえば、CORESERVERを利用していて、セッションファイルを自分のホームディレクトリである非公開領域(ルート直下にsessionディレクトリを任意に作成した場合)に置きたい場合には次のようにスクリプト内で設定します。

    session_save_path('/virtual/your_account/session');

    この関数実行を含むファイルを共通化して、セッションを要するファイルすべてにインクルードする訳です。(php.iniや.htaccess等でも同様の設定はできるみたいですが、それはおいときます。)

    なお、session_start()関数を呼ぶ前に、session_save_path関数を実行することが必要です。

    このように、通常のセッションの置き場(CORESERVERやXREAだと、’/tmp’)と違う場所にセッションファイルを置く様にした場合は、ガベージコレクションについても、設定しておきます。

    ガベージコレクションを設定しておくと、セッションファイルの有効期間を任意に決められるので便利です。通常だと、1440秒(24分)アクセスがないとセッションは切れてしまいますが、それを、1時間とか2時間に延長することができます。

    セッションの保存先変更とあわせて設定すると次のようなスクリプトになります。

    //セッションファイル保存先 
    session_save_path('/virtual/account/session');
    
    //ガベージコレクション設定 
    ini_set('session.gc_probability', 1); 
    ini_set('session.gc_divisor', 100); 
    ini_set('session.gc_maxlifetime', 2 * 60 * 60);

    一番下の、’session.gc_maxlifetime’がセッションの有効期間を定めたものです。ここでは、2時間に設定しています。

    上の二つは、これで一組です。この設定の場合、1/100の確率でセッションファイルを削除することを意味します。

    1/100とは、session_start関数が100回呼ばれた場合、1回の確率でセッションファイルを削除する動作(ガベージ・コレクション)をするというものです。

    こまめに削除したいなら、1/10にするのも良いかもしれませんし、セッションをなるべく長時間生かしたいなら1/1000とかにするのも良いでしょう。ちなみに初期設定は、1/100らしいです。

    最後に蛇足ですが、セッションに関するセキュリティについても設定しておきます。

    セッションをクッキーのみで処理する方がセキュリティが高まります。つまり、URLパラメーターにセッションIDを付けるのを止める方法です。これは次のように設定します。

    //クッキーのみセッション可能設定
    ini_set('session.use_cookies', 1);
    ini_set('session.use_only_cookies', 1);

    これで、URLパラメーターにセッションIDがついていても無視することになり、セッション固定化攻撃等を防ぐことができるというわけです。

    ただし、クッキーが使えない携帯サイトでセッションを使う場合にはとりづらい方法かもしれません。

    上記で、セッション関連の設定を解説しましたが、どれもsession_startよりも前に実行することを忘れずに。

    なお、php.ini等で設定できる場合には、スクリプト内で設定するより楽なのでそちらの方がよいかもしれません。

    もっとも、CORESERVERでは、php.iniをそれぞれのディレクトリに置く必要があるかもしれないので、共通ファイル化したスクリプト内に、ini_set関数で設定してしまうのもありかもです。

    ■ セッションファイルの保存先を変更する理由

    最後の最後になりますが、どうしてセッションファイルの保存先を変更するのか?

    セッションファイルは、通常は、ルート直下の’/tmp‘に作成されます。

    これは、レンタルサーバーが共用サーバーである場合でも、同様です。

    共用サーバーである場合、他のユーザーのセッションファイルもルート直下の’/tmp’に作成されます。

    すると、自分のサイトに関連するセッションファイルと、他人のサイトのセッションファイルが同じtmpディレクトリに存在することになります。

    セッションファイルの名前は、セッションIDと同じです。その結果、’/tmp’を覗かれた場合には、他人のセッションファイルのセッションIDを知ることができてしまいます。

    これは、自分のセッションファイルのセッションIDが知られてしまうことも意味します。

    セッションIDが漏洩するとなりすまされる危険があります。

    そこで、自分だけのホームディレクトリかつ非公開領域にセッション用のディレクトリを作成しそこにセッションファイルを保存するようにするわけです。