<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title>Suinasia(PHP)</title>
<link>http://suin.asia/tag/PHP</link>
<description>「PHP」なエントリー</description>
<language>ja</language>
<lastBuildDate>Sat, 04 Feb 2012 22:22:41 +0900</lastBuildDate>
<docs>http://backend.userland.com/rss/</docs>
<category>PHP</category>
<item>
<title>[PHP] array_diff()は文字列比較だから注意してね</title>
<link>http://suin.asia/2011/08/19/array_diff</link>
<description><![CDATA[<script src="https://gist.github.com/1155934.js?file=gistfile1.aw"></script>

<p><a href="http://www.php.net/manual/ja/function.array-diff.php">PHP: array_diff - Manual</a>をよく読むと、こんな注意書きが。</p>

<blockquote class="note"><p><b class="note">注意</b>: 
   </p><p class="para">
    二つの要素は、<i>(string) $elem1 === (string) $elem2</i>
    の場合のみ等しいと見直されます。言い換えると、文字列表現が同じ場合となります。
    
   </p>
  <p></p></blockquote>

<p>要素が配列だと、string(5) "Array"同士の比較になっちゃうのね(´・ω・｀) </p>]]></description>
<pubDate>Fri, 19 Aug 2011 12:06:22 +0900</pubDate>
<guid>http://suin.asia/2011/08/19/array_diff</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>[PHP] 配列を文字列に変換して取っておく4つの方法</title>
<link>http://suin.asia/2011/08/09/4_tips_to_preserve_array_as_string</link>
<description><![CDATA[<p>配列をデータベースやテキストファイルに保存したいときってありますよね。リレーショナルデータベース的には、ちゃんと最適化すべきだけど、並び替えや検索する必要がない場合は、とりあえず配列を文字列として保存したりします。<code>serialize()</code>関数を使う方法はよく知られています。この関数以外にも、PHPでは配列を文字列に変換できるものがあります。このエントリーでは、<code>serialize()</code>、<code>var_export()</code>、<code>json_encode()</code>、<code>http_build_query()</code>の4つの使い方について書きます。</p>


<h3>今回文字列化を試す変数</h3>

<p>今回文字列化を試す変数は、bool型・int型・float型・string型・添字配列・連想配列を含んだ連想配列です。</p>

<pre name="code" class="php">
$data = array(
	'bool'   => true,
	'int'    => 1,
	'float'  => 1.23,
	'string' => 'foobar',
	'array'  => array('apple', 'orange', 'strawberry'),
	'key-value' => array(
		'jp' => 'Japan', 
		'us' => 'USA', 
		'cn' => 'China',
	),
);
</pre>


<h3>1. serialize()</h3>

<p>この関数は変数を文字列化できることでよく知られています。変換された文字列は型・大きさ・値を保持するようになっています。</p>

<pre name="code" class="php">
$serial = serialize($data);
var_dump($serial);
// string(285) "a:6:{s:4:"bool";b:1;s:3:"int";i:1;s:5:"float";d:1.229999999999999982236431605997495353221893310546875;s:6:"string";s:6:"foobar";s:5:"array";a:3:{i:0;s:5:"apple";i:1;s:6:"orange";i:2;s:10:"strawberry";}s:9:"key-value";a:3:{s:2:"jp";s:5:"Japan";s:2:"us";s:3:"USA";s:2:"cn";s:5:"China";}}"
</pre>

<p>シリアライズされた文字列を、再び配列に戻すには<code>unserialize()</code>関数を使います。元のデータをしっかり復元してくれます。</p>

<pre name="code" class="php">
$serialImported = unserialize($serial);
var_dump($serialImported);
/*
array(6) {
  ["bool"]=>
  bool(true)
  ["int"]=>
  int(1)
  ["float"]=>
  float(1.23)
  ["string"]=>
  string(6) "foobar"
  ["array"]=>
  array(3) {
    [0]=>
    string(5) "apple"
    [1]=>
    string(6) "orange"
    [2]=>
    string(10) "strawberry"
  }
  ["key-value"]=>
  array(3) {
    ["jp"]=>
    string(5) "Japan"
    ["us"]=>
    string(3) "USA"
    ["cn"]=>
    string(5) "China"
  }
}
*/
var_dump($data === $serialImported); // true

</pre>

<h3>2. var_export()</h3>

<p><code>var_export()</code>関数はPHPとして解釈可能な文字列に変換します。第二引数に何も指定しないと、文字列に変換した結果が出力されます。変数に代入するときは第二引数にtrueを指定します。</p>

<pre name="code" class="php">
$php = var_export($data, true);
var_dump($php);
/*
string(267) "array (
  'bool' => true,
  'int' => 1,
  'float' => 1.23,
  'string' => 'foobar',
  'array' => 
  array (
    0 => 'apple',
    1 => 'orange',
    2 => 'strawberry',
  ),
  'key-value' => 
  array (
    'jp' => 'Japan',
    'us' => 'USA',
    'cn' => 'China',
  ),
)"
*/
</pre>

<p><code>var_export()</code>関数には、<code>unserialize()</code>関数のようにインポートする直接的に対応する関数はありません。そのかわりに、<code>eval()</code>関数で文字列を評価します。</p>

<pre name="code" class="php">
eval('$phpImported = '.$php.';');

var_dump($phpImported);

/*
array(6) {
  ["bool"]=>
  bool(true)
  ["int"]=>
  int(1)
  ["float"]=>
  float(1.23)
  ["string"]=>
  string(6) "foobar"
  ["array"]=>
  array(3) {
    [0]=>
    string(5) "apple"
    [1]=>
    string(6) "orange"
    [2]=>
    string(10) "strawberry"
  }
  ["key-value"]=>
  array(3) {
    ["jp"]=>
    string(5) "Japan"
    ["us"]=>
    string(3) "USA"
    ["cn"]=>
    string(5) "China"
  }
}
*/

var_dump($data === $phpImported); // true
</pre>

<h3>3. json_encode()</h3>

<p><code>json_encode()</code>関数は、JSON形式の文字列に変換します。この関数はPHP5.2で導入されました。</p>

<pre name="code" class="php">
$json = json_encode($data);
var_dump($json);
// string(143) "{"bool":true,"int":1,"float":1.23,"string":"foobar","array":["apple","orange","strawberry"],"key-value":{"jp":"Japan","us":"USA","cn":"China"}}"
</pre>

<p>再び配列に戻すときは<code>json_decode()</code>関数を使います。第二引数を指定しないと、戻り値がオブジェクト型になります。戻り値を配列型として受け取るには、第二引数にtrueを指定する必要があります。</p>

<pre name="code" class="php">
$jsonImported = json_decode($json, true);

var_dump($jsonImported);
/*
array(6) {
  ["bool"]=>
  bool(true)
  ["int"]=>
  int(1)
  ["float"]=>
  float(1.23)
  ["string"]=>
  string(6) "foobar"
  ["array"]=>
  array(3) {
    [0]=>
    string(5) "apple"
    [1]=>
    string(6) "orange"
    [2]=>
    string(10) "strawberry"
  }
  ["key-value"]=>
  array(3) {
    ["jp"]=>
    string(5) "Japan"
    ["us"]=>
    string(3) "USA"
    ["cn"]=>
    string(5) "China"
  }
}
*/

</pre>

<h3>4. http_build_query()</h3>

<p><code>http_build_query()</code>関数は、配列をクエリーストリング形式に変換します。この関数はPHP5から利用できます。</p>

<pre name="code" class="php">
$query = http_build_query($data);
var_dump($query);
// string(170) "bool=1&int=1&float=1.23&string=foobar&array%5B0%5D=apple&array%5B1%5D=orange&array%5B2%5D=strawberry&key-value%5Bjp%5D=Japan&key-value%5Bus%5D=USA&key-value%5Bcn%5D=China"
</pre>

<p>デコードには、<code>parse_str()</code>関数を使います。第二引数を指定しないと<code>extract()</code>関数のように、配列のキーで変数を定義します。第二引数を変数すると、デコードした結果がその変数に代入されます。<code>parse_str()</code>関数はすべて文字列型に解釈するので注意が必要です。</p>

<pre name="code" class="php">
parse_str($query, $queryImported);

var_dump($queryImported);
/*
array(6) {
  ["bool"]=>
  string(1) "1"
  ["int"]=>
  string(1) "1"
  ["float"]=>
  string(4) "1.23"
  ["string"]=>
  string(6) "foobar"
  ["array"]=>
  array(3) {
    [0]=>
    string(5) "apple"
    [1]=>
    string(6) "orange"
    [2]=>
    string(10) "strawberry"
  }
  ["key-value"]=>
  array(3) {
    ["jp"]=>
    string(5) "Japan"
    ["us"]=>
    string(3) "USA"
    ["cn"]=>
    string(5) "China"
  }
}
*/

var_dump($data === $queryImported); // false
</pre>]]></description>
<pubDate>Tue, 09 Aug 2011 15:30:30 +0900</pubDate>
<guid>http://suin.asia/2011/08/09/4_tips_to_preserve_array_as_string</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>[PHP]interfaceの命名規約いろいろ</title>
<link>http://suin.asia/2011/08/06/interface_naming</link>
<description><![CDATA[<p>PHPのinterfaceの命名規約ってどういうのがいいんだろう？Javaや他の言語の命名規則をあつめてみた。うちは、こんな命名規則でやってます、というのがあったら教えてください。</p>

<h3>1. Iを接頭辞にする</h2>

<pre class="php" name="code">
interface IUser {}
</pre>

<ul>
<li>○ 慣れればインターフェイスだと比較的分かりやすいかも。</li>
<li>○ ファイル名でソートしたときに、インターフェイスが集まる。</li>
<li>× Iが見えにくい。細い。</li>
<li>感想: ハンガリアン記法っぽくて嫌い。</li>
</ul>

<h3>2. Interfaceを接尾辞にする</h3>

<pre class="php" name="code">
interface UserInterface {}
</pre>

<ul>
<li>○ インターフェイスって分かりやすい。</li>
<li>○ もうクラスがあって、それをインターフェイスに抽象化するときは、クラス名に接尾辞つけるだけ。</li>
<li>× インターフェイス定義だけ見ると冗長。</li>
<li>× 長い。</li>
<li>感想: 悪くないと思う。</li>
</ul>


<h3>3. -ableを接尾辞にする</h3>

<pre class="php" name="code">
interface Countable {}
</pre>

<ul>
<li>インターフェイスは能力を表すという世界観。</li>
<li>○ 慣れればインターフェイスって分かりやすい。</li>
<li>→ クラスに-ableを使うことを禁止しないとごっちゃになる。</li>
<li>× 英語力がないとインターフェイス名考えるのが辛い。</li>
<li>感想: なんとなくいいかも。</li>
</ul>


<h3>4. 完全に自由</h3>

<pre class="php" name="code">
interface FooBar {}
</pre>

<ul>
<li>× クラス名とかぶるとめんどくさい。</li>
<li>× type-hintingとかuseとかinstanceofでインターフェイスって分かりにくい。</li>
<li>→ 分からなくても困らないかも？</li>
<li>○ 臨機応変に名前をつけられる。</li>
</ul>]]></description>
<pubDate>Sat, 06 Aug 2011 13:13:00 +0900</pubDate>
<guid>http://suin.asia/2011/08/06/interface_naming</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>[PHP] abstractとinterfaceの使い分けを整理してみる</title>
<link>http://suin.asia/2011/07/18/php_abstract_vs_interface</link>
<description><![CDATA[<h3>abstractとinterfaceの違いを自信持って使い分けてる?</h3>

<p>abstractとinterfaceの言語仕様はよく似てる。とても混同しやすい。PHPで自身をもって使い分けている人はどれくらいいるかな？少なくとも自分は全部abstractでもいいと思っている（いた）。でも、interfaceはオブジェクト指向できっと重要な概念だろうから、しっかり区別したいな。Twitterでオブジェクト指向に詳しそうな人に聞きいたり、ググったりして調べて自分なりに理解した内容をまとめてみるよ。</p>

<h3>似てる点</h3>

<ul>
<li>そのままでは呼び出せない。abstractはextends、interfaceはimplementsしてはじめて使える。</li>
<li>抽象メソッドを定義できる(see code.1)。ちなみにそれらは子クラスで必ず実装しないといけない。</li>
</ul>

<pre class="php" name="code">
// code.1
abstract class AbstractFoo
{
	abstract public function bar();
}

interface InterfaceFoo
{
	public function bar();
}
</pre>

<h3>異なる点</h3>

<ul>
<li>classはabstractを1つだけextendsできるが、classはinterfaceを複数implementsできる(see code.2)。</li>
<li>abstractは具体的な実装があるメソッドを持てる。interfaceは単に抽象メソッドを列挙するだけ(see code.3)。</li>
</ul>

<pre class="php" name="code">
// code.2
class Hoge extends AbstractFoo
{
}

class Hoge implements InterfaceFoo, InterfaceFoo2, InterfaceFoo3
{
}
</pre>


<pre class="php" name="code">
// code.3
abstract class AbstractFoo
{
	abstract public function bar();

	public function baz()
	{
		echo 'baz!';
	}
}

interface InterfaceFoo
{
	public function bar();
	public function baz();
}
</pre>

<h3>この言語仕様を踏まえてどう使い分けるか?</h3>

<p>「interfaceを使うくらいなら、abstract一辺倒でよくない？いざとなったらabstractに具体的な実装もできるしね」と思っている人はきっと自分だけじゃないと思う。ここではabstractじゃなくてinterfaceを使ったほうがいい、って例を説明していくよ。だから、interfaceのほうにフォーカスした内容になってる。読者はabstractの使い方をよく知っているし、よく使っているという前提ね。</p>

<h4>仕様書はinterfaceにできるかも</h4>

<p>interfaceは具体的な実装を持てない。これは設計書として利用できるかも知れない。今までドキュメントに書いていたクラスの仕様はinterfaceにすることができるってこと。例えば、こんな仕様書があったとする。</p>

<blockquote>
<p>仕様書</p>
<ul>
<li>データベースクライアントクラスは次の4つのメソッドを提供しなければなりません。</li>
<li>書き込みメソッド。メソッド名: create()。引数は保存するデータ(連想配列)。</li>
<li>読み込みメソッド。メソッド名: load()。引数は読み込む行のID(整数)。</li>
<li>上書きメソッド。メソッド名: update()。引数は上書きする行のID(整数)と保存するデータ(連想配列)。</li>
<li>削除メソッド。メソッド名: delete()。引数は削除する行のID(整数)。</li>
</ul>
</blockquote>

<p>文書の仕様書を否定するつもりはないけど、人の言葉で書かれた仕様書は曖昧だったりする。上の仕様書でも、戻り値がよくわかんないし、update()の引数の順番は曖昧だし、引数は必須なのか任意なのか分かんない。</p>

<p>紙の仕様書は、メンテナンスされないこともあるよね。仕様書がなくともプログラムは正常に動作するから。もし、仕様書がプログラムに組み込まれたらどうだろう？仕様書がメンテナンスされなければプログラムが動かないので、仕様書をメンテするようになるよね、きっと。</p>

<p>上の仕様書は、interfaceに翻訳することができるんだ(code.4)。下の例のほうが文書の仕様書より曖昧性が低いよね。それに、仕様変更があったときもエラーとして気が付きやすい。例えば、複数行を取得したくなって、メソッド<code>find(array $condition)</code>を追加したとする。find()を実装していないサブクラスはエラーになるんだ。</p>

<pre class="php" name="code">
// code.4
interface DatabaseClient
{
	/**
	 * テーブルに行を追加する
	 * @returns bool 保存に成功したらtrue、失敗したらfalse
	 */
	public function create(array $data);

	/**
	 * テーブルの行のデータを取得する
	 * @returns mixed 読み込みに成功したら配列、失敗したらfalse
	 */
	public function load($id);

	/**
	 * テーブルの行を更新する
	 * @returns bool 保存に成功したらtrue、失敗したらfalse
	 */
	public function update($id, array $data);

	/**
	 * テーブルの行を削除する
	 * @returns bool 削除に成功したらtrue、失敗したらfalse
	 */
	public function delete($id);
}
</pre>

<p>これはabstractでも同じような書き方ができるね。でも、具体的な実装を持たないならinterfaceにしたほうがいいかもしれないよ。interfaceは実装を持てない。これって、シンプルという長所でもあるよね。仕様を提供する側のコストがミニマムになる。それに、プログラマは最低限のリードタイムで「ここだけ実装しておけばいいのね」ということが分かるようになる。abstractだったら、そのクラスの内部実装にまで目を配らないといけないよね。つまり、interfaceのほうが設計者とプログラマの両者にとってストレスが少ないってことになるね。（ひとりで開発する場合は別かもしれないけど）</p>

<h4>呼び出し方は同じだけど、内部の処理は全然ちがう場合はinterface</h4>

<p>最近のウェブアプリはログインするものが多いよね。内部的なこと言ったら認証処理だね。認証処理ってのは、アプリ側が「あなたはだれ？」が特定できればよくて、それ以外の関心はない処理なんだけど、一方で、認証処理は様々なものがある。アプリ独自の認証方式、OpenID、LDAP、Basic認証、Twitter認証、Facebook認証、社内独自認証などなど。</p>

<p>このケースだと、interfaceを活用できる。ウェブアプリは、認証方法の詳細について口出ししない。その代わり、「interfaceに実装してほしいauthorize()っていうメソッドを定義しておいたよ。」っていう約束だけ決めて(code.5)、「うちはそれだけを呼び出すから、あとはうまいことやってね」と具体的な認証方法は各認証オブジェクトにまるなげする。</p>

<pre class="php" name="code">
// code.5
interface Auth
{
	/**
	 * 認証処理を行う
	 * @returns bool 成功したらtrue、失敗したらfalseを返す
	 */
	public function authorize();
}
</pre>

<p>それで、各認証方式を受け持つオブジェクトは、authorize()を独自に実装する(code.6)。</p>

<pre class="php" name="code">
// code.6
class OpenID implements Auth
{
	public function authorize()
	{
		if ( $this->_openIdAuth() )
		{
			return true;
		}

		return false;
	}

	protected function _openIdAuth()
	{
		// オープンIDで認証する処理
	}
}
</pre>

<p>この例では、abstractはほとんど役に立たないよね。だって、ウェブアプリは認証方式の詳細に口出し（具体的な実装を提供）することができないから。各認証処理は全く異なった実装になるだろうね。具体的な実装の共通化は容易じゃない。無理して共通化に心を砕くくらいなら、interfaceにしたほうがいさぎよい、と思う。</p>

<h3>まとめ</h3>

<p>今回、調べていて気づいた点をまとめると、interfaceの出番は次のようになる。もっと、勉強してinterfaceを上手く使えるようになりたいな。</p>

<ul>
<li>仕様書はinterfaceにできるかも</li>
<li>呼び出し方は同じだけど、内部の処理は全然ちがう場合はinterface</li>
</ul>

<h3>参考になるページ</h3>

<ul>
<li><a href="http://havelog.ayumusato.com/develop/php/e166-php-interface-abstract.html">PHPのinterfaceとabstractを正しく理解して使い分けたいぞー ::ハブろぐ</a></li>
<li><a href="http://d.hatena.ne.jp/anatoo/20080517/1211029059">PHPにはインターフェイスというものがありますよ、という話 - id:anatooのブログ</a></li>
<li><a href="http://www39.atwiki.jp/fujiyan/pages/28.html">ふじやん雑記帳 - とりあえずインターフェース入門</a></li>
<li><a href="http://members.jcom.home.ne.jp/maripiyo.k/UC/uc_lec100/cosc121/java_ch5.htm">５章　インターフェース --Interface--</a></li>
</ul>]]></description>
<pubDate>Mon, 18 Jul 2011 15:08:30 +0900</pubDate>
<guid>http://suin.asia/2011/07/18/php_abstract_vs_interface</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>XOOPSモジュール開発を始める人のための4冊</title>
<link>http://suin.asia/2011/06/02/4books_for_new_xoops_module_developers</link>
<description><![CDATA[<p>これからXOOPS Cubeのモジュールを開発しようとしている方に、suinの主観で選んだ推薦図書を紹介します。</p>


<h3>『XOOPS Cube Legacy デベロッパーズ・バイブル』</h3>

<p>
<a style="float:left; margin: 5px;" href="http://www.amazon.co.jp/gp/product/4797340487/ref=as_li_qf_sp_asin_il?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=4797340487"><img border="0" src="http://ws.assoc-amazon.jp/widgets/q?_encoding=UTF8&Format=_SL160_&ASIN=4797340487&MarketPlace=JP&ID=AsinImage&WS=1&tag=suinyeze-22&ServiceVersion=20070822" ></a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=4797340487" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
XOOPSで有名な<a href="http://marijuana.ddo.jp/">Marijuana</a>さん、<a href="http://petitoops.com/">しゃの</a>さんの著書です。XOOPS Cubeで実装された新機能、プリロード、デリゲートの利用方法、XOOPS Cube Legacyらしいモジュール開発手法、複製モジュールの開発方法などついて詳しく書いてあります。
</p>

<p style="clear:both;"></p>


<h3>『パーフェクトPHP』</h3>

<p><a style="float:left; margin: 5px;" href="http://www.amazon.co.jp/gp/product/4774144371/ref=as_li_qf_sp_asin_il?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=4774144371"><img border="0" src="http://ws.assoc-amazon.jp/widgets/q?_encoding=UTF8&Format=_SL160_&ASIN=4774144371&MarketPlace=JP&ID=AsinImage&WS=1&tag=suinyeze-22&ServiceVersion=20070822" ></a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=4774144371" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
PHPを体系的に学びたい方にオススメです。PHPの概要にはじまり、初心者がつまずきやすいクラスやオブジェクトなど基礎的な部分はもちろん、フレームワークを使った最近の実践的な開発手法、そして忘れてはいけないセキュリティにいたるまで、網羅的に学ぶことができます。最近出たばかりの本なので、最新情報にも詳しいです。著者もPHP業界で非常に活発な方たちである、<a href="http://twitter.com/sotarok">sotarok</a>さん、<a href="http://twitter.com/fivestr">fivestr</a>さん、そしてXOOPS業界でも有名な<a href="http://twitter.com/gusagi">gusagi</a>さんによって書かれています。
</p>

<p style="clear:both;"></p>

<h3>『PHP ポケットリファレンス』</h3>

<p>
<a style="float:left; margin: 5px;" href="http://www.amazon.co.jp/gp/product/4774125024/ref=as_li_qf_sp_asin_il?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=4774125024"><img border="0" src="http://ws.assoc-amazon.jp/widgets/q?_encoding=UTF8&Format=_SL160_&ASIN=4774125024&MarketPlace=JP&ID=AsinImage&WS=1&tag=suinyeze-22&ServiceVersion=20070822" ></a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=4774125024" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
やりたいことからPHPの関数を探すのに便利です。たとえば、「ファイル全体を安全に読み込みたい」というやりたいことから、関数を調べることができます。PHPのオンラインのマニュアルだとどうも分かりにくいという方にも、この本は簡潔にエッセンスだけを提示しているのでおすすめです。私も、この本はボロボロになるまで使いました。
</p>

<p style="clear:both;"></p>

<h3>『PHPサイバーテロの技法―攻撃と防御の実際』</h3>

<p>
<a style="float:left; margin: 5px;" href="http://www.amazon.co.jp/gp/product/4883374718/ref=as_li_qf_sp_asin_il?ie=UTF8&tag=suinyeze-22&linkCode=as2&camp=247&creative=1211&creativeASIN=4883374718"><img border="0" src="http://ws.assoc-amazon.jp/widgets/q?_encoding=UTF8&Format=_SL160_&ASIN=4883374718&MarketPlace=JP&ID=AsinImage&WS=1&tag=suinyeze-22&ServiceVersion=20070822" ></a><img src="http://www.assoc-amazon.jp/e/ir?t=suinyeze-22&l=as2&o=9&a=4883374718" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
XOOPSのモジュールは公開されてしまえば、常に攻撃の脅威にさらされることになります。モジュール開発者はそうした攻撃に強く脆弱性のないPHPの書き方についてよく知っておく必要があります。この本は、クラッカーがどのような攻撃をしてくるか説明した上で、その防御策を説明しているので理解しやすい内容になっています。著者はこれまたXOOPS業界で有名な<a href="http://xoops.peak.ne.jp/">GIJOE</a>さんです。XOOPSってほんとにPHP業界でも著名な人が多いですね。
</p>

<p style="clear:both;"></p>]]></description>
<pubDate>Thu, 02 Jun 2011 20:46:34 +0900</pubDate>
<guid>http://suin.asia/2011/06/02/4books_for_new_xoops_module_developers</guid>
<category domain="http://suin.asia/tag/XOOPS">XOOPS</category>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>MAMP1.9.6にPHPUnitをインストールする方法</title>
<link>http://suin.asia/2011/05/09/how_to_install_phpunit_to_mamp</link>
<description><![CDATA[<h3>PHP5.3にPHPUnitをインストールする</h3>

<pre>
cd /Applications/MAMP/bin
ln -s php5.3 php5 # シンボリックリンクを貼らないとMAMPのバグでPEARがおかしくなるっぽい
php5/bin/pear channel-discover pear.phpunit.de
php5/bin/pear channel-discover components.ez.no
php5/bin/pear channel-discover pear.symfony-project.com
php5/bin/pear channel-update pear.php.net
php5/bin/pear upgrade pear
php5/bin/pear install phpunit/PHPUnit
cd php5.3/bin/
open -a Coda phpunit # 自分のエディタで開く(Coda, Textmate, vimなど)
</pre>

一行目の

<pre>
#!/Applications/MAMP/bin/php5/bin/php
</pre>

を
<pre>
#!/Applications/MAMP/bin/php5.3/bin/php
</pre>

にする

<pre>
sudo ln -s /Applications/MAMP/bin/php5.3/bin/phpunit /usr/bin/phpunit5.3
phpunit5.3 --version
</pre>

おわり

<h3>PHP5.2にPHPUnitをインストールする</h3>

<pre>
cd /Applications/MAMP/bin
rm -f php5 # 上のPHP5.3の手順をやった場合
ln -s php5.2 php5
php5/bin/pear channel-discover pear.phpunit.de
php5/bin/pear channel-discover components.ez.no
php5/bin/pear channel-discover pear.symfony-project.com
php5/bin/pear channel-update pear.php.net
php5/bin/pear upgrade pear
php5/bin/pear install phpunit/PHPUnit
cd php5.2/bin/
open -a Coda phpunit # 自分のエディタで開く(Coda, Textmate, vimなど)
</pre>


一行目の

<pre>
#!/Applications/MAMP/bin/php5/bin/php
</pre>

を
<pre>
#!/Applications/MAMP/bin/php5.2/bin/php
</pre>

にする


<pre>
sudo ln -s /Applications/MAMP/bin/php5.2/bin/phpunit /usr/bin/phpunit5.2
phpunit5.2 --version
</pre>


<h3>参考</h3>
<ul>
<li><a href="http://forum.mamp.info/viewtopic.php?f=6&t=11102">MAMP Forum &bull; View topic - phpunit on MAMP 1.9.5 broken and work around</a></li>
</ul>]]></description>
<pubDate>Mon, 09 May 2011 12:38:02 +0900</pubDate>
<guid>http://suin.asia/2011/05/09/how_to_install_phpunit_to_mamp</guid>
<category domain="http://suin.asia/tag/MAMP">MAMP</category>
<category domain="http://suin.asia/tag/PHP">PHP</category>
<category domain="http://suin.asia/tag/PHPUnit">PHPUnit</category>
</item>
<item>
<title>PHPの出力バッファが有効なときはメモリの枯渇に注意を</title>
<link>http://suin.asia/2011/04/27/clear_output_buffer_for_huge_data_output</link>
<description><![CDATA[<p>CSV出力などで、大量のデータをブラウザに送る際、出力バッファを解除しておいたほうがいい。出力バッファが有効になったままだと、echoしたものは一旦メモリに蓄えられるため、結果的にメモリオーバになる危険性がある。</p>

<pre class="php" name="code">
error_reporting(-1);
ini_set('display_errors', 1);

ob_start(); // 出力バッファ開始

while ( true )
{
	phpinfo();
}

</pre>

<pre>
Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 33300481 bytes) in /Applications/MAMP/htdocs/php/ob_filter/memory.php on line 10
</pre>

<p>出力バッファを解除するには、echoなどの直前で次のような関数を1回だけ実行するだけである。</p>

<pre class="php" name="code">
function clearOutputBuffer()
{
	while ( ob_get_level() > 0 )
	{
		ob_end_clean();
	}
}
</pre>]]></description>
<pubDate>Wed, 27 Apr 2011 10:56:18 +0900</pubDate>
<guid>http://suin.asia/2011/04/27/clear_output_buffer_for_huge_data_output</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>PHPで標準入力を取得する方法</title>
<link>http://suin.asia/2011/04/04/how_to_pass_stdin_to_php</link>
<description><![CDATA[<p>昨日、<a href="http://suin.asia/2011/04/03/command_line_php_11_tips">コマンドラインでPHPを使うときの11のTips</a>というエントリーを書いた。最近、コマンドラインネタが多いけど、懲りずに今日もコマンドラインネタをひとつ書こうと思う。</p>

<h3>標準入力のよくある渡し方</h3>

<ul>
<li>実行結果をパイプ | で繋いで渡す
<pre>
commandA | commandB
# commandAの実行結果がcommandBに渡る
</pre>
</li>
<li>小なり &lt; で後ろから渡す
<pre>
command &lt; data.txt
# data.txtの内容がcommandに渡る 
</pre>
</li>
</ul>

<h3>PHPで標準入力を取得する方法</h3>

<p>php://stdinをファイル操作系の関数で読み込むだけ。たったそれだけ。</p>

<pre class="php" name="code">
&lt;?php
$stdin = file_get_contents('php://stdin');
var_dump($stdin);
</pre>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/SWScY92OQ__CC3gztSohhg?feat=embedwebsite"><img src="https://lh4.googleusercontent.com/_dG0BBWAhWis/TZkJqKWyDYI/AAAAAAAABbc/TuoAz0JqzGA/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-04-04%208.57.01%EF%BC%89.png" height="303" width="400" /></a></p>

<p>CSVを渡してデータを操作したり、いろいろ使えそう。</p>]]></description>
<pubDate>Mon, 04 Apr 2011 08:59:24 +0900</pubDate>
<guid>http://suin.asia/2011/04/04/how_to_pass_stdin_to_php</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>コマンドラインでPHPを使うときの11のTips</title>
<link>http://suin.asia/2011/04/03/command_line_php_11_tips</link>
<description><![CDATA[<h3>1. ファイル単位の構文チェックはphpコマンドで行おう</h3>

<p>phpコマンドにlオプションを指定することで、特定のファイルの構文チェックができる。エラーの詳細は、php.iniで指定したエラーログに出力されるので、そちらを確認する。</p>

<pre class="shell" name="code">php -l /path/to/file.php</pre>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/ZaFyqfEdOHbU8BDspL2hIw?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/_dG0BBWAhWis/TZgJHroDDmI/AAAAAAAABa8/DLu29YCzI_M/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-04-03%2013.14.55%EF%BC%89.png" height="241" width="400" /></a></p>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/JGOTYReU6nzTlWBwO6GiSA?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/_dG0BBWAhWis/TZgJHj6r8SI/AAAAAAAABa4/giqaoJLlm10/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-04-03%2013.15.32%EF%BC%89.png" height="241" width="400" /></a></p>

<h3>2. 成功・失敗はexit()の引数で切り分けよう</h3>

<p>exit()の引数に整数を指定すると、端末側に処理が成功したか失敗したかを伝えることが可能。成功で終わったことを伝える場合は、exit(0);というふうにし、失敗で終わったという場合は、exit(1);か1以上の整数を与える。</p>

<pre class="php" name="code">
&lt;?php
echo &quot;&#25104;&#21151;&#12375;&#12414;&#12375;&#12383;&quot;.PHP_EOL;
exit(0);
</pre>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/wUgWK-9CW8j7aPIIF1pA1w?feat=embedwebsite"><img src="https://lh5.googleusercontent.com/_dG0BBWAhWis/TZgJH_nxSBI/AAAAAAAABbA/BqYWV2EbOHQ/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-04-03%2013.22.19%EF%BC%89.png" height="241" width="400" /></a></p>

<pre class="php" name="code">
&lt;?php
echo &quot;&#22833;&#25943;&#12375;&#12414;&#12375;&#12383;&quot;.PHP_EOL;
exit(1);
</pre>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/RLGSiqjcD9cbKXdnUqcKjQ?feat=embedwebsite"><img src="https://lh4.googleusercontent.com/_dG0BBWAhWis/TZgJIanisLI/AAAAAAAABbE/d7OLiQyo09k/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-04-03%2013.23.02%EF%BC%89.png" height="241" width="400" /></a></p>

<p>(ちなみに、私のプロンプトは前回のコマンドが失敗したときは、顔文字が赤くなるように細工してあるので、exit()の引数が働いているのがよくわかります。)</p>

<h3>3. メッセージ出力用の関数をつくろう</h3>

<p>メッセージの出力は、単純にecho 'message';とやってもいいのだが、これだと改行されないので、見づらくなってしまう。改行を有効ににするには、echo "message\n";のように最後に改行コードを付ける。ただ、毎回改行コードを文字列に埋め込むのは非効率的なので、下のようなメッセージ出力用の関数を作って、その関数で運用したほうが100倍楽だ。</p>

<pre class="php" name="code">
function print($message)
{
	echo $message.PHP_EOL;
}
</pre>

<h3>4. エラーメッセージの出力用の関数をつくろう</h3>

<p>「メッセージ出力用の関数」と同様にエラーメッセージの出力も関数にしておくのがおすすめ。「え？エラーメッセージって普通にechoするだけでいいんじゃないの？」と思われそうだが、echoは標準出力になるので、実行端末側が普通のメッセージなのかエラーメッセージなのか区別できなくなる。実行端末と上手く連携するためには、エラーメッセージは「標準エラー出力」に吐き出すことが得策だ。標準エラー出力先はphp://stderrになる。エラーメッセージの出力用の関数の最も単純な実装が下の例だ。</p>

<pre class="php" name="code">
function error_message($message)
{
	file_put_contents('php://stderr', $message.PHP_EOL);
}
</pre>

<p>エラーメッセージを標準エラー出力に吐き出すようにしておくと、例えばcronでエラーの時だけメールがほしいといった場合に便利。crontabを次のように、設定しておくだけでエラーに気づけるようになる。</p>

<pre>
0 4 * * * php /path/to/scheduled_job.php > /dev/null
# 標準出力は捨てて、標準エラー出力はメールに送られる。
</pre>

<h3>5. exec()関数はラップして使おう</h3>

<p>外部コマンドを実行するexec()関数ですが、ラップした関数を用意しておこう。自分がよく使うラッパーは次のような実装だ。</p>

<pre class="php" name="code">
function execute($command, $captureStderr = false)
{
	$output = array();
	$return = 0;

	if ( $captureStderr === true )
	{
		$command .= ' 2>&1';
	}

	exec($command, $output, $return);

	$output = implode("\n", $output);

	return array('output' => $output, 'return' => $return);
}
</pre>

<p>exec()関数の第二引数はデフォルトではエラー出力を受け取らないので、エラー出力をキャプチャする必要がある場合には、コマンドに 2>&1 を埋め込む必要がある。上のラッパーでは、第二引数でエラー出力を受け取るか指定できるようにしている。</p>

<h3>6. プロセスは小分けにしよう</h3>

<p>Webインターフェイスだと、プロセスの寿命は長くてもせいぜい3秒程度だが、バッチ処理などを実装すると、どうしてもプロセスの寿命が長くなってしまう。プロセスの実行時間が長くなれば、メモリの使用量も大きくなりがりなので、メモリオーバに陥る危険性も必然的に高くなる。メモリ管理に自身のあるプログラマならメモリの残りを見ながらプロセスをコントローラすべきだ。が、もしメモリ管理に不安を覚えるようであれば、プロセスの寿命を短くすることに注力しよう。プロセス実行時間が短くなれば自ずとメモリオーバの危険性も低くなる。</p>

<p>実行時間を短くするTipsとして、最も単純なのがプロセスを小分けにする方法だ。exec()関数で、サブプロセスのPHPを実行するだけである。</p>

<pre class="php" name="code">
exec("php subprocess.php", $output, $return);
</pre>

<h3>7. 変数のスコープは狭くしよう</h3>

<p>メモリオーバの対策として、できるだけグローバル変数を使わないという方法もある。グローバル変数はプロセスが終了しないかぎり、メモリから解放されないが、関数内の変数はスコープが切れると直ちにメモリから解放される。なので、できるだけメソッドや関数に小分けにして実装するのがおすすめだ。</p>

<pre class="php" name="code">
&lt;?php

function hoge()
{
	$bar = range(0, 1000);
}

$foo = range(0, 1000);
hoge();
// $barはここで開放される

// 長い処理…

// $foo は最後の最後まで開放されない
</pre>

<h3>8. 実行権限に注意しよう</h3>

<p>特にLinux系のサーバで実行するときは、実行権限に注意する必要がある。root権限で実行されるのか、apache権限で実行されるのか、それとも別のユーザ権限で実行されるのか。ファイル操作や、コマンドの実行で、権限によってエラーになったり実行できなかったりする。今、このPHPが誰によって実行されているか確認するには、passthru('whoami');を実行するといいだろう。</p>

<h3>9. apache権限でsudoするときはコマンドごとにNOPASSWDを設定しよう</h3>

<p>どうしてもapcahe権限でsudoする必要があるときがある。そんなときは、visudoでapacheをsudorに追加しておこう。その際、apacheに無条件でsudoできるようにするのは危険なので、コマンドを絞ろう。そして、そのコマンドに関してはパスワードなしで実行できるようにしよう。パスワードなしで実行できるようにするのは、PHPでインタラクティブにパスワードを入力するのは実装が面倒だからだ。</p>

<pre>
apache  localhost=(ALL) NOPASSWD: /path/to/command.sh, /path/to/command2.sh, /path/to/command3.sh
</pre>

<p>/path/to/command.shの中身は例えば、次のような例だ。たとえ、lsやmkdirのような単純なコマンドでも引数も含めてshファイルに固定しておき、lsやmkdirの実行権限自体は与えないようにする。そうすることで目的のコマンドを安全に実行できるようになる。</p>
<pre class="sh" name="code">
#!/bin/sh
ls /root
mkdir /root/newdir
</pre>

<p>PHP側の実装は、exec()関数を次のように叩くだけだ。</p>

<pre class="php" name="code">
exec('sudo /path/to/command.sh');
</pre>

<p>余談だが、sudoするときの別の裏技として、apacheにパスワードを設定しておき、sudo -Sを利用する方法がある。ex.「echo "apache passowrd here" | sudo -S ls /root'」</p>

<h3>10. プロセスはロックが必要か検討しよう</h3>

<p>cronなどで処理の実行をスケジュール化しているとき、スケジュールの間隔が数分単位など短くなっていると、前のプロセスが完了する前に次のプロセスが走ってしまう場合がある。</p>

<pre>
process 1 -------------------------------------------------------->
process 2                    ------------------------------------------------------>
                             [この部分で二重に処理される危険性がある]
</pre>

<p>このような場合、ステータスファイルを検討してみるといいだろう。process1が走り始めた段階で、「現在プロセスが走ってます」という状態を表すファイルをどこかに作っておき、そのファイルがある限り、process2が走らないようにしておくといったものだ。下のような実装にすれば、同じプロセスが二重に走る心配がなくなる。</p>

<pre class="php" name="code">
&lt;?php

if ( file_exists('/path/to/process.lock') )
{
	echo "このプロセスはロックされています。".PHP_EOL;
	die(1);
}

echo "プロセスを開始します".PHP_EOL;

touch('/path/to/process.lock');

// 時間のかかる処理

unlink('/path/to/process.lock');

echo "プロセスを終了します".PHP_EOL;
die(0);
</pre>

<h3>11. 今PHPのプロセスが走っているかは ps ax | grep php で調べよう</h3>

<p>開発中はデバッグ中に、現在PHPのバッチ処理が動いているか知りたい時がある。Linuxであれば、そうしたときは次のコマンドを実行して調べてみよう。コマンドにphpが含まれているプロセスが表示され、一目瞭然だ。</p>

<pre class="sh" name="code">ps ax | grep php</pre>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/mMXr-0HYN5shNlyRip1HUw?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/_dG0BBWAhWis/TZgJJRjkVSI/AAAAAAAABbM/WJ60VUAb-80/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-04-03%2014.37.40%EF%BC%89.png" height="236" width="400" /></a></p>

<p>この応用として、私がよく使う確認コマンドは次のようなものだ。どういうものかというと、1秒ごとに上のコマンドを実行して、実行状況の進捗を確認するものだ。</p>

<pre class="sh" name="code">while true; do ps ax | grep php; sleep 1; done;</pre>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/O_VxVQAMHo3TbINWu9rTBw?feat=embedwebsite"><img src="https://lh6.googleusercontent.com/_dG0BBWAhWis/TZgJJZYAs3I/AAAAAAAABbI/zsej_Ej8KLw/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-04-03%2014.40.15%EF%BC%89.png" height="400" width="378" /></a></p>

<h3>まとめ</h3>

<p>以上が、コマンドラインPHPを利用する上でのTipsでした。もっとこうしたほうがいいとか、こんな便利なTipsもあるよ、という意見・ご感想などもお待ちしてます^-^ 本気で、バッチ処理などを書くときはPHPを使わないなんて意見もありそうですが、それは自粛し...(ry</p>]]></description>
<pubDate>Sun, 03 Apr 2011 14:47:12 +0900</pubDate>
<guid>http://suin.asia/2011/04/03/command_line_php_11_tips</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
<item>
<title>svn commitする前にvar_dump, console.logが含まれてないかチェックするスクリプトをPHPで書いてみた</title>
<link>http://suin.asia/2011/03/30/check_debug_code_before_svn_commit</link>
<description><![CDATA[<p>開発中にデバッグするために変数を出力する関数をプログラムに直接書きこむことがある。PHPであればvar_dump()、JavaScriptであれば、console.log()などがその関数になる。これらのプログラムに記述したデバッグ用のコードは、デバッグコードと呼ばれる。</p>

<p>プロジェクトを複数人で共有している場合、デバッグコードを書いたとしても、メンバーと共有する場合は消しておくことが必要だ。仕事でのプロジェクトであれば、デバッグコードによる余計な出力やプロセスの終了は不具合として扱われることになる。</p>

<p>自分も仕事でデバッグコードを書いて、それをそのままSubversionのリポジトリに上げてしまっていたので、svn commitする手前でvar_dump, console.logが含まれてないかチェックするスクリプトを作ってみた。</p>


<h3>できたもの: svn-commit</h3>

<a href="http://dl.dropbox.com/u/949822/Downloads/svn-commit" class="download">ダウンロード</a>

<ul>
<li>開発環境がMacOSXなので、Macで動く。</li>
<li>ターミナルから使うので、コマンドラインインターフェイス。</li>
<li>どうせなのでPHPで書いてみた。</li>
<li>svn commitコマンドの感覚で使える。</li>
<li>ついでに、コミットコメントもいれやすい感じにしてみる。svn ci -m ""とかエディタの設定とかめんどくさいって人なので。</li>
</ul>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/o3eMIMb3-y_CfvBI-NdZuw?feat=embedwebsite"><img src="https://lh4.googleusercontent.com/_dG0BBWAhWis/TZHs0rSgh3I/AAAAAAAABak/7631ugGqw_c/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-03-29%2022.20.20%EF%BC%89.png" height="206" width="400" /></a></p>

<p class="photo"><a href="https://picasaweb.google.com/lh/photo/aqmnM0BsoFEU3YqX4ffrNA?feat=embedwebsite"><img src="https://lh4.googleusercontent.com/_dG0BBWAhWis/TZHs0vCcfqI/AAAAAAAABao/MANsn3FlInY/s400/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%EF%BC%882011-03-29%2022.20.55%EF%BC%89.png" height="331" width="400" /></a>
</p>

<small>写真はsciにsvn-commitのエイリアスを張っている</small>

<h3>使い方</h3>

<ul>
<li>svn-commitをダウンロード</li>
<li>PATHの通っているところにsvn-commitをおく。</li>
<li>svn-commitに実行権限を与えておく。</li>
<li>あとは、svn ciをするかわりにsvn-commitを実行するだけ。</li>
</ul>]]></description>
<pubDate>Wed, 30 Mar 2011 00:00:00 +0900</pubDate>
<guid>http://suin.asia/2011/03/30/check_debug_code_before_svn_commit</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
<category domain="http://suin.asia/tag/subversion">subversion</category>
</item>
<item>
<title>cronでPHPを動かす2つの方法</title>
<link>http://suin.asia/2011/03/20/2_ways_to_trigger_php_with_cron</link>
<description><![CDATA[<h3>1. コマンドラインインターフェイスで動かす</h3>

<p>PHPをコマンドラインインターフェイスで動かす方法です。</p>

<pre>
# 4時半に実行
30 4 * * * php /private/path/to/batch.php
</pre>

<h4>メリット</h4>

<ul>
<li>サーバ外部から実行されないので、セキュリティ的に安心。</li>
<li>タイムアウトの心配がない。</li>
<li>phpコマンドだけあればいい。</li>
<li>余計なトラフィックがない。</li>
</ul>

<h4>デメリット</h4>

<ul>
<li>$_SERVER['SERVER_NAME']などのApache由来の環境変数が取れない。</li>
<li>ウェブインターフェース用に作ったプログラムがそのまま再利用できない場合がある。</li>
<li>処理をトリガするサーバと、処理を行うサーバが同じである必要がある。(* SSHなどでリモートコントロールする場合をのぞく)</li>
</ul>

<h3>2. ウェブ経由で動かす</h3>

<p>PHPをウェブ経由で動かす方法です。</p>

<pre>
# 4時半に実行
30 4 * * * wget --spider http://localhost/batch.php
</pre>

<h4>メリット</h4>

<ul>
<li>$_SERVER['SERVER_NAME']などのApache由来の環境変数が取れる。</li>
<li>ウェブインターフェース用に作ったプログラムがそのまま再利用できる。</li>
<li>処理をトリガするサーバと、処理を行うサーバが別でもいい。</li>
</ul>

<h4>デメリット</h4>

<ul>
<li>サーバ外部から実行されうるので、セキュリティ的に心配。あるいは認証処理を実装する必要がある。</li>
<li>タイムアウトの心配がある。</li>
<li>wgetコマンドが必要。(別にwgetじゃなくてもいいんだけど。)</li>
<li>余計なトラフィックがある。</li>
</ul>

<h3>ケースによって柔軟に使い分けよう</h3>

<p>長い処理、セキュリティが担保される必要のある処理は、コマンドラインで。</p>
<p>誰が実行してもよくて、ウェブインターフェース用のプログラムを再利用したい場合は、ウェブ経由で。</p>

<p>まあ、でも、全部、CLIでやってもいいんだけどね。</p>]]></description>
<pubDate>Sun, 20 Mar 2011 14:52:33 +0900</pubDate>
<guid>http://suin.asia/2011/03/20/2_ways_to_trigger_php_with_cron</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
<category domain="http://suin.asia/tag/cron">cron</category>
</item>
<item>
<title>もっとより良いPHPerになるためのTips</title>
<link>http://suin.asia/2011/03/20/20_tips_you_need_to_learn_to_become_a_better_php_programmer</link>
<description><![CDATA[<p>PHPに限らず、プログラムには書き手やプロジェクトによって流儀は様々なのは最初に述べておくとして、<a href="http://1-byte.jp/2011/03/20/20_tips_you_need_to_learn_to_become_a_better_php_programmer/">より良いPHPerになるための20Tips</a>(英語原典<a href="http://www.webgeekly.com/tutorials/php/20-tips-you-need-to-learn-to-become-a-better-php-programmer/">20 Tips you need to learn to become a better PHP Programmer | webgeekly.com</a>)に自分なりの補足をしたいと思う。</p>

<h3>5. 変数名に意味を持たせよ</h3>

<blockquote>
<p>変数に意味を持たせることは、いつもあなたのためになる。<br /> 
データの型まで分かると、更に良い。<br /> 
例えば、integer型の変数には、変数名のプレフィックスとしてiをつける。<br /> 
変数に型宣言しないPHPにおいて、これは特に重要だ。</p> 
<p>変数名の頭文字を大文字にするかどうかは、あなた次第だ。<br /> 
しかし、読み易さから言っても、単語の先頭は大文字にすることをお勧めする。</p> 
<p>こんな感じだ。</p> 
<pre class="brush: php;"> 
&lt;?php
$iNumber = 10; // For Integers
 
$sName = &quot;Marc&quot;; // For Strings
 
$fPi = 3.14159265; // For Floats
 
$aNames = array(); // For Arrays
 
$oUser = new User(); // For Objects
 
$bIsMember = false; // For Booleans
</pre> 
</blockquote>

<p>これは自分は真反対。というより、変数名に意味を持たせることは非常に同意するけど、<a href="http://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%B3%E3%82%AC%E3%83%AA%E3%82%A2%E3%83%B3%E8%A8%98%E6%B3%95">ハンガリアン記法</a>について反対ということ。「PHPは型がゆるい言語だからハンガリアン記法で型を宣言しよう」っていう主張は前からあるけど、型がゆるい言語だからこそハンガリアン記法は避けるべきだと思う。これが1つ目の理由です。</p>

<pre name="code" class="php">
$sTags = 'php,perl,ruby,python';
$sTags = explode(',', $sTags);
</pre>

<p>例えば、カンマで区切られた文字列をexplodeで配列に分解したら、あっというまに型が変わってしまう。ここでもうハンガリアン記法は意味のないものになってしまう。それなら、配列用に別の変数名をつければいいじゃないかという反論があるかもしれない。しかし、それは一方で無駄な一時変数を増やすことでもある。</p>

<p>もうひとつの理由は、ハンガリアン記法は必ずしもプログラマ同士で共通化されていないという点。ハンガリアン記法自体、いくつかの流儀があって流儀が異なる者同士が同じコードを触った際に混乱につながる。混乱させるような記法なら最初から避けるべきだと思う。</p>

<p>私が思うに、「変数名に意味を持たせよ」で重要なことは、つきつめれば次の1点だと思う。</p>

<ul>
<li>変数名を略しすぎず、できるだけ発音できるものにする。</li>
</ul>

<p>具体的に言えば、$categoryを$ctgと略したりしないということです。</p>

<h3>10. 三項演算子を使え</h3> 

<blockquote>
<p>もし、シンプルなif文を書きたいなら、三項演算子を使って、ワンラインで通常のif文を書くのと同じことが書ける。</p> 
<pre class="brush: php;"> 
&lt;?php
if ($a == 1) $b = 2;
else $b = 3;
</pre> 
<p>上記のコードは、以下の三項演算子を使ったのと同じことだ。</p> 
<pre class="brush: php;"> 
&lt;?php
$b = ($a == 1) ? 2 : 3;
</pre>
</blockquote>

<p>「三項演算子を使え」は言い過ぎだと思う。せいぜい、「読みやすいコードになる場合に限ってのみ三項演算子を使ったほうがいい」だと考える。現に三項演算子は重ねて書かれると読みにくいし、ブレースがないぶん制御構造としての認識が低くなる。さらに言えば、単体テストのときにテストケースへの意識も低くなりかねないという危険性がある。上の例のようなコードでは、三項演算子が歓迎されると思う。しかし、三項演算子の乱用は控えるべきだとも思う。</p>


<h3>12. ++と&#8211;の演算子を使え</h3> 

<blockquote>
<p>整数を減少あるいは増加させる場合、インクリメントあるいはデクリメントの演算子が使える。<br /> 
もし、あなたがこんなコードを書いているなら、</p> 
<pre class="brush: php;"> 
&lt;?php
$iNumber = $iNumber  + 1;
$iNumber2 = $iNumber2 - 1;
</pre> 
<p>こう変換すべきだ。</p> 
<pre class="brush: php;"> 
&lt;?php
$iNumber++;
$iNumber2--;
</pre> 
</blockquote>

<p>もっとより良いPHPerならこうすると思う。++より、+= 1を使う。</p>

<pre class="php" name="code">
$iNumber  += 1;
$iNumber2 -= 1;
</pre>

<p>なぜなら、万が一 $iNumber に 'a' が代入されていたら、どうなるだろうか？その際の動作は、期待したものだろうか？</p>

<pre class="php" name="code">
$iNumber = 'a';
$iNumber ++;
var_dump($iNumber); // string(1) "b"
</pre>

<p>もちろん$iNumberは、整数型にキャストする、ないしはバリデーションしておくべきだ。それでも、ちょっと工夫するだけで防衛プログラミングができるならそれに越したことはないと思う。</p>]]></description>
<pubDate>Sun, 20 Mar 2011 13:00:59 +0900</pubDate>
<guid>http://suin.asia/2011/03/20/20_tips_you_need_to_learn_to_become_a_better_php_programmer</guid>
<category domain="http://suin.asia/tag/PHP">PHP</category>
</item>
</channel>
</rss>
