Home > PHP

PHP Archive

CakePHPを使う理由

この記事の所要時間: 11

International PHP Magazineで「CakePHPを使う理由」というアンケートをやっています。

# Lightweight
# CakePHP does not believe in a components/widget approach
# Compatible with PHP4 and PHP 5
# Enhanced AJAX support
# Suitable for any kind of project
# The Bake command

International PHP Magazine::News::IPM Poll Question: Reasons to use CakePHP are ?

2つめは良く分からないのですが、後はまあ有りそうな選択肢ですね。

ちなみに私がCakePHPに興味を持った理由は「PHP4/5対応」と、選択肢には無いですが「ActiveRecordライクなModel」「設定ファイル不要」でした。(あとはやっぱりこれです。;-))

アンケートに回答すると現在の集計結果を見ることができます。bakerな方は回答してみては?

PHP6はコードキャッシュを搭載?

  • 2006-12-12 (火)
  • PHP
この記事の所要時間: 112

エントリはAPCのインストール方法なのですが気になる内容が。

APC Cache is not included with the latest release of php (although it is planned on being included with version 6).

Jaslabs: High performance php » How to install Alternative PHP Cache

PHP6にはAPCが含まれる可能性があるようです。

私も本稼働のサイトでeAcceleratorを使用しているのですが効果は抜群です。単純なコードならあまり効果は無いかもしれませんが、フレームワークなど多数のコードを読み込むようなアプリケーションだとかなり有効です。

ただ導入した時は若干クセがあり、高負荷時に安定稼働させるには試行錯誤が必要でした。

PHP本体に標準添付となれば使われる事例も増え、ノウハウが共有されていくでしょう。さらにソフト自体の信頼性も上がっていく事も期待できますね。(さらにさらに進んでJITコンパイラなんかが出てくるかもしれません。:-))

PHP6では

$ ./configure --enable-apc or --with-code-cache=apc

なんて感じでしょうか。

複数のレイヤで考える

この記事の所要時間: 147

複数のレイヤで考えるというのは大事ですね。

Webアプリケーションって、H/Wを始め、ネットワークやOS、ApacheやPHP自体などいろいろなレイヤの上に位置するものだし、それらの技術の上に成り立っているものなので、「コーディング」というレイヤの上っ面だけかじって、「Javaできます」とか「PHPできます」ってのはどうかと。コーディングも大事ですが、それより下のレイヤもそれ以上に大事だと思います。それらのレイヤで簡単に解決できるハズの問題を、JavaとかPHPのレイヤで解決しようとしてるのを目にすることが多すぎる気がします

Do You PHP はてな – LANスイッチングセミナー その2

はげしく同意です。

複数レイヤで考える簡単な例としてはWebアプリケーションのアクセス制限があります。

クライアント側のIPを見てアクセス可否を判断したい場合は、FW・ルータ・サーバ(iptables等)・Apache(Webサーバ)・アプリケーションサーバ・アプリケーションと様々な箇所で対策を行う事ができます。(PHPならアプリケーションを「php.ini等の設定」と「コード」にも分けられますね。)

コードでがりがり書いたものが、実は下位レイヤで設定ファイルを少し触るだけで実現してしまったりします。

あとアクセス制限なら下位のレイヤで制限をかけておけば、当然それより上位のレイヤにアクセスする事ができなくなります。その結果、負荷が軽減されたり、セキュリティが確保されたりします。

もちろん要件や環境によってどのレイヤで解決するべきかは変わってきます。レンタルサーバなどでは通常ネットワーク周りは触れないでしょうし、アプリケーションを不特定多数に配布する事が前提ならできれば全て配布物(アプリケーション)で解決したいでしょう。

ただ知っている事により問題解決の引き出しが増えることは間違いないです。

アプリケーション以外のレイヤも是非触ってみましょう。

# 目の前には1月前から箱に入ったままのRTX1100があったりします。。。
# 早くやれよ>自分:-P

PHPテクニカルセミナーに参加してきました。

この記事の所要時間: 116

PHPテクニカルセミナー – PHP言語で快適デバッグに参加してきました。

平日の午前中という時間帯に関わらず多くの人が集まっており満員御礼状態でした。(プレゼンターの田中さんも触れられていましたが正直私もこんなに集まると思っていませんでした。:-p)

セミナーではいくつかのデバッグ手法・ツールが紹介されていました。

  • print_r/var_dumpメソッド
  • PEAR::Var_dump
  • dBug
  • DBG
  • Xdebug
  • Gubed
  • Simple PHP Debugger
  • VS.Php

印象に残った内容です。

  • ブラウザ->DBG->DBGListener->デバッガの流れが分かりやすかった。
    (ポイントだったようで何度も説明されていました。)
  • Gubedは試してみたい。
  • VS.PhpはSubversionクライアントにも使える。
  • VS.Phpはdeployにも使える。
  • VS.Phpは複数バージョンのPHPエンジンを使える。
  • VS.PhpはMicrosoftが作っているわけではない。
  • VS.Phpは試用版がある。

このセミナーはVS.Phpの販促だったと思うのですが、DBG+DBGLisener+デバッガの構築が複雑だっただけに、それと対比してVS.Phpがいかに簡単に導入できるかをアピールすれば良かったのように思いました。

関西ではPHPのセミナーは少ないので次回が開催される事を楽しみにしています。

PHPソースからフローチャートを生成する

この記事の所要時間: 054

Visustin – Flow chart generator sofware

PHPのソースからフローチャートを生成するツールです。

対応している言語はPHPの他にC/C++、Java、VBといった主要な言語はもちろんのこと、さらにPerlやPythonといったLL系の言語も網羅されています。(Rubyはまだのようです)

デモ版でCakePHPのソース[cake/dispatcher.php]からフローチャート生成してみました。

visustin_flowchart

※デモ版ではプリントアウト・エクスポートといった出力ができないので画面をキャプチャしています。

フローチャートの他にUMLのアクティビティー図も生成できます。

visustin_activity

ソースの規模にもよりますが、生成した図は画面で見るには大きいですし、デバッグやコードレビュー時に参考資料として使えそうなので、やはりプリントアウト機能は欲しいです。実用するには有料版を購入する必要があるという事ですね。

# 自分が書いたソースが図になると何だか嬉しいです。:-)

PHP5.2.0でOut of memory

  • 2006-12-07 (木)
  • PHP
この記事の所要時間: 512

PHP5.2.0にメモリリークのバグがあるようです。

どうやらPHP 5.2.0のZendEngine2にメモリリークバグがあるようでBTSにもPHP Bugs: #39438: Memory leak PHP Fatal error: Out of memoryとして報告があがっていました。

PHP 5.2.0におけるメモリリークバグ – Sooey

CVS版では既に修正されていますが、CVS版がすぐに適用できない場合もある(ない?)のでリコンパイルせずにこの問題を回避する方法を考えてみました。

メモリリークする事はもちろんまずいのですが、結局はPHPがメモリを確保する際にmemory_limitの制限に引っかかってしまう事によりFatal errorが発生しています。そこでmemory_limitの制限を外す or 上限値を上げる方法を試してみます。

バグを発生させるコードです。
(via [cvs] View of /ZendEngine2/tests/bug39438.phpt

< ?php
$i=0;
$test2=array(
   'a1_teasermenu' => array(
   		'downloadcounter' => 2777,
        'versions' => array(
        	'0.1.0' => array (
        		'title' => 'A1 Teasermenu',
        	    'description' => 'Displays a teaser for advanced subpages or a selection of advanced pages',
        	    'state' => 'stable',
        	    'reviewstate' => 0,
        	    'category' => 'plugin',
        	    'downloadcounter' => 2787,
        	    'lastuploaddate' => 1088427240,
        	    'dependencies' => array (
        	          'depends' => array(
        	                  'typo3' =>'', 
        	                  'php' =>'', 
        	                  'cms' => ''
        	           ),        	
        	          'conflicts' => array('' =>'')        	
        	    ),        	
        	  	'authorname' => 'Mirko Balluff',
        	  	'authoremail' => 'balluff@amt1.de',
        	  	'ownerusername' => 'amt1',
        	  	't3xfilemd5' => '3a4ec198b6ea8d0bc2d69d9b7400398f',
      		)
  		)
  	)
);
$test=array();
while($i&lt;1200) {	
	$test[]=$test2;
	$i++;
}
$out=serialize($test);
echo "ok\n";
?>

まずはPHP5.1.6(memory_limit=16M)で実行してみてみました。こちらはエラーになりません。

$ php516/bin/php -v
PHP 5.1.6 (cli) (built: Oct 17 2006 20:22:42) 
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
$ php516/bin/php -f memory_leak_520.php -d memory_limit=16M
ok

続いてPHP5.2.0(memory_limit=16M)で実行するとFatal errorが発生しました。

$ php -v
PHP 5.2.0 (cli) (built: Nov  7 2006 14:33:45) 
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies
$ php -f memory_leak_520.php -d memory_limit=16M
PHP Fatal error:  Allowed memory size of 16777216 bytes exhausted (tried to allocate 784851 bytes) in ~/memory_leak_520.php on line 36

memory_limit=24Mにするとエラーは発生しませんでした。

$ php -f memory_leak_520.php -d memory_limit=24M
ok

memory_limitを無制限にした場合もエラーは発生しませんでした。

$ php -f memory_leak_520.php -d memory_limit=-1
ok

本来はバグを修正すべきですが、まあこんな方法もあるという事で。

CakePHP1.1.11.4064リリース

この記事の所要時間: 051

CakePHP1.1.11.4064がリリースされています。

数々のバグフィックスの他、以下のような内容が盛り込まれています。

  • Configureクラスにメソッド追加(version(),read(),write())
  • Modelの遅延読込(the lazy loading of models)によるパフォーマンス向上
  • View#_viewVarsがdeprecatedに
    => これからはView#viewVarsになるようです。

CakePHP cakeError()は値を返さないCakePHP1.1.10.3825-bake.php修正パッチの内容も修正されていました。

ソースをざっと見たところではコードのクリーニングが行われていたり、phpdocが追記されていたりとソース自体の熟成も進んでいる印象を受けました。機能を実装するより地味ですが、クオリティを上げるのに重要な作業だと思います。開発者の方々には感謝感謝ですね。

PHPUnitでMockオブジェクトを使う2

この記事の所要時間: 338

PHPUnitでMockオブジェクトを使うで紹介したMockオブジェクトですが、これは元クラスを継承しているわけではないので当然ながら元クラスの実装は使えません。

ただテストする場面によっては、基本は元クラスの振る舞いをして、一部のメソッドだけMockにしたいという場合があります。

そこで元クラスを継承したMockオブジェクトを作ってみます。

元クラス

< ?php
class Hoge {
  // このメソッドはそのまま
  function execute() {
    if ($this->request()) {
      // OK
      return 1;
    } else {
      // NG
      return -1;
    }
  }

  // このメソッドをMockにしたい
  function request(&$db) {
    $db->query();
    sleep(100);
    return true;
  }
}
?>

テストケース

Mockオブジェクトをテストケースに書いています。単にHogeクラスを継承してrequest()をオーバーライドするだけです。

< ?php
require_once 'PHPUnit.php';
require_once 'Hoge.php';

class MockHoge extends Hoge {
  function request() {
    return true;
  }
}

class HogeTest extends PHPUnit_TestCase {
  function testExecute() {
    $obj = new MockHoge();
    $this->assertTrue($obj->execute());
  }
}

$suite = new PHPUnit_TestSuite('HogeTest');
$result = PHPUnit::run($suite);
echo $result->toString();
?>

テストケース-返り値を設定

こちらではMockHogeに変数を追加して、インスタンス変数に応じてrequest()メソッドの返り値が変わるようにしています。

< ?php
require_once 'PHPUnit.php';
require_once 'Hoge.php';

class MockHoge extends Hoge {
  var $mockRequestValue;

  function request() {
    return $this->mockRequestValue;
  }
}

class HogeTest extends PHPUnit_TestCase {
  function testExecute() {
    $obj = new MockHoge();

    $obj->mockRequestValue = true;
    $this->assertEquals(1, $obj->execute());
    $obj->mockRequestValue = false;
    $this->assertEquals(-1, $obj->execute());
  }
}

$suite = new PHPUnit_TestSuite('HogeTest');
$result = PHPUnit::run($suite);
echo $result->toString();
?>

この方法では(Mockオブジェクト用の)コンポーネントは必要ないので手軽にMockオブジェクトを使う事ができます。また元クラスの実装を生かせるのでこの例のように一部だけを変えたい場合には有用です。

SimpleTestのようなMockオブジェクトとケースバイケースで使い分けるのが良いですね。

PHPUnitでMockオブジェクトを使う

この記事の所要時間: 347

PHPUnit3がリリースされました。このバージョンにはMockがサポートされているのですが、PHPUnit3はPHP5を対象としているので残念ながらPHP4では動作しません。ですのでPHP4対応のPHPUnitでMockクラスを使う方法を探ってみました。

使うのはPHPUnitと並ぶユニットテストツールのSimpleTestです。こちらはPHP4対応でMockクラスがサポートされています。これをPHPUnitと組み合わせて使ってみます。

SimpleTestインストール

PEARパッケージが以前はあったようなのですが、sourceforgeにはそれらしいものが見当たりませんでした。
zuzara : symfonyチュートリアル実践【第14~16日目】を参考に以下のコマンドでインストールしました。

$ pear install http://jaist.dl.sourceforge.net/sourceforge/simpletest/simpletest_1.0.0.tgz

PEARパッケージが見つからない場合でもsourceforgeからソースを取得してinclude_pathで参照できる位置に配置すればOKです。

PHPUnit用Mockクラス

SimpleTestのSimpleMockを継承してPHPUnitで使うMockクラスを記述します。

< ?php
require_once 'simpletest/mock_objects.php';

class PHPUnitMock extends SimpleMock {
  function PHPUnitMock($test, $wildcard) {
    $this->SimpleMock($test, $wildcard);
  }
}
SimpleTestOptions::setMockBaseClass('PHPUnitMock');
?>

テスト対象クラス

テスト対象のクラスはこちらです。selectCount()はテーブル名を引数に取り、テーブルのレコード数を整数で返します。擬似的に処理時間が100秒かかるようにしています。

< ?php
class Database {
  function selectCount($table) {
    sleep(100);
    return null;
  }
}
?>

テストケース

Databaseクラスのテストケースを記述します。Mockクラスを使用することに定義した処理結果[100]がすぐに返ってきます。

< ?php
require_once 'PHPUnit.php';
require_once 'PHPUnitMock.php';
require_once 'Database.php';

Mock::generate('Database');

class DatabaseTest extends PHPUnit_TestCase {
  function DatabaseTest ($name) {
    $this->PHPUnit_TestCase($name);
  }

  function setup() {
  }

  function testQuery() {
    $mock =& new MockDatabase($this);
    $mock->setReturnValue('selectCount', 100, 'users');

    $ret = $mock->selectCount('users');
    $this->assertEquals($ret, 100);
  }
}

$suite = new PHPUnit_TestSuite('DatabaseTest');
$result = PHPUnit::run($suite);
echo $result->toString();
?>

SimpleTestはMockクラスの他にHTTPテストも行えるなど高機能なのですが、すでにPHPUnitを使用していたので今更移行するのも億劫でした。あとはコードカバレッジも使えると良いのですが。;-)

foreachでIndirect modification of overloaded propertyが発生する

  • 2006-11-21 (火)
  • PHP
この記事の所要時間: 222

マジックメソッドの__get()ですが、配列を返すとforeachでNoticeが発生する場合があります。

< ?php
error_reporting(E_ALL);

class A {
  private $array = array(1, 2, 3);

  function __get($name) {
    if ($name == 'hoge') {
      return $this->array;
    }
  }
}

$obj = new A();
foreach ($obj->hoge as $elem) {
  var_dump($elem);
}
?>
PHP Notice:  Indirect modification of overloaded property A::$hoge has
 no effect in __get.php on line 15

The reason for this is that __get() only returns variables in read mode, while foreach() wants a variable in read/write mode as it tries to modify the internal array pointer. As it can’t do this PHP 5.2 will now throw a warning on this.

Overloaded properties (__get) – Derick Rethans

理由はforeachではread/writeモードが要求されるのに__get()ではreadモードの値が返されるためのようです。__get()がreadモードで返すのは当然のような気がしますがちと不便ですね。

対策としては__get()内で(array)でキャストするか

< ?php
  function __get($name) {
    if ($name == 'hoge') {
      return (array)$this->array;
    }
  }
?>

__get()の値を別の変数に代入すれば良いようです。

< ?php
$array = $obj->hoge
foreach ($array as $elem) {
?>

この現象は5.2.0で発生し、5.1.6ではNoticeはでませんでした。__get()は便利で何だか使いたくなる機能ですが、配列を返す場合は注意しましょう。

ホーム > PHP

検索
フィード
メタ情報

Return to page top