Home > PHP

PHP Archive

前の日曜日は何日?

  • 2006-11-18 (土)
  • PHP
この記事の所要時間: 057

strtotime()で様々な日付をunixタイムスタンプで取得できます。

Keep it simple and just do strtotime(‘-1 Sunday’,$currentDay);

Calculating start and end dates of a week. – Derick Rethans (2006-11-18)

コメント欄からの引用です。

エントリにある週の始め、終わりの日にちを取得するには以下で取得できます。

< ?php
$now = time();
// 週の始め(月曜日)
echo date('Y/m/d', strtotime('-1 Monday', $now)) . "\n";
// 週の終わり(日曜日)
echo date('Y/m/d', strtotime('+1 Sunday', $now)) . "\n";
?>

PHPマニュアルに他の記述も載っていますのでご参考にどうぞ。

■参考サイト
PHPマニュアル-strtotime

ユニットテストでデータ検証

この記事の所要時間: 35

ユニットテストでプログラムで生成したデータを検証する方法です。

CSVファイルを検証するテストをPHPUnitで書いてみました。

< ?php
require_once "PHPUnit.php";

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

  function testData() {
    // データ読み込み
    $fp = fopen('data.csv', 'r');
    if (!$fp) {
      die('data not found.');
    }

    // テストループ
    $line = 0;
    while(!feof($fp)) {
      $line++;
      $row = fgetcsv($fp, 4096);
      if (empty($row)) {
        continue;
      }

      if (count($row) != 3) {
        $this->fail('Line: ' . $line);
        continue;
      }

   // id は数値のみ
      $id = $row[0];
      $this->assertRegExp('/^[0-9]+$/', $id, $line);

   // code は英数字のみ
      $code = $row[1];
      $this->assertRegExp('/^[A-Za-z0-9]+$/', $code, $line);

   // name は値があれば良い
      $name = $row[2];
      $this->assertTrue(strlen($code) > 0, $line);
    }

    fclose($fp);
  }
}


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

ポイントは「assert失敗時のメッセージにデータを特定する項目を含めておく」くらいでしょうか。(このソースでは行数を入れていますが、DBのRecordsetを検証する時はpkeyの値を入れています。)あとはdata.csvが何万行あろうが何回テストしようがphpunitがきっちりテストしてくれます。やっている事は単純なのですが効果は高いです。

他にも複雑なSQLで生成されるデータをPHPで取得して検証したり、DBに問い合わせてデータが正しいかを検証するという方法もあります。もちろん正となるデータを用意しておいてそれと比較するというのもありです。

あと、ここではPHPUnitを使いましたが、データを相手にテストを行うので別にSimpleTestでも良いですし、PerlでもRubyでも何でもOKです。Javaで開発したシステムのデータをPHPで検証する、なんてこともできますね。(LL言語の利用範囲がこんなところにも;-))

ロジックの自動テストも大事ですが、生成物の自動テスト(チェック)もあると心強いものです。

Nesting level too deep – recursive dependency?

  • 2006-11-17 (金)
  • PHP
この記事の所要時間: 22

Big Room » Blog Archive » PHP 5.2 – Nesting level too deep – recursive dependency?でオブジェクト同士の比較で発生するエラーについて書かれています。

class MyObj
{
    public $p;
}
class OtherObj
{
    public $q;
}

$a = new MyObj();
$b = new OtherObj();
$a->p = $b;
$b->q = $a; // the circular reference: $a->p->q === $a

$c = new MyObj();
$d = new OtherObj();
$c->p = $d;
$d->q = $c;// another circular reference: $c->p->q === $c

echo ( $a == $c ); // Fatal error:
?>
Big Room » Blog Archive » PHP 5.2 - Nesting level too deep - recursive dependency? (2006-11-16)

ポイントは循環参照と[==]での比較です。

PHPでは[==]と[===]とで処理結果が異なるのは良く言われていることですが、これはオブジェクト同士でも同様です。オブジェクトの比較にあるように[==]ならオブジェクトの持つ変数同士が比較され、[===]ならオブジェクトの参照が比較されます。(Javaの==とStrings#equals()に似ていますね。)

つまり循環参照しているオブジェクト同士を[==]で比較すると延々オブジェクトの変数が比較され続けてエラーが発生するというわけです。

ちなみにPHP4では[==]も[===]もPHP5の[==]と同じ動作をするようです。(PHP4におけるオブジェクトの比較

呼び出し元のメソッドを使用したい場合にうっかり循環参照になっていたりするので注意が必要です。

 

# エントリではPHP5.1.6では[==]で動作していたようですが、手元の環境では5.1.6でも同じエラーが発生しました。5.2.0特有の現象というわけでは無さそうです。

CakePHP1.1.10.3825-bake.php修正パッチ

この記事の所要時間: 246

cakephp.jpにあるように、1.1.10.3825のbake.phpをWindows上で使用すると上手く動作しない場合があります。

この現象はcake\とは異なるディレクトリにプロジェクトを生成しようとした場合に発生するようです。

New App Directoryが作成するプロジェクトのディレクトリなのですが、妙なパスが表示されています。[D:\tmp\d:\tmp\app]

> php -q D:\tmp\cake\scripts\bake.php -project d:\tmp\app
...
New App Directory: D:\tmp\d:\tmp\app
---------------------------------------------------------------

原因はディレクトリ区切り文字を[/]に決めうちしているためです。この問題の修正パッチを作りましたのでよろしければどうぞ。

--- cake_1.1.10.3825.org/cake/scripts/bake.php       2006-11-10 14:37:00.531250000 +0900
+++cake_1.1.10.3825/cake/scripts/bake.php       2006-11-13 18:08:16.187500000 +0900
@@ -82,12 +82,12 @@
        }
 
        $shortPath = str_replace($root, '', $app);
-       $shortPath = str_replace('../', '', $shortPath);
-       $shortPath = str_replace('//', '/', $shortPath);
+       $shortPath = str_replace('..' . DS, '', $shortPath);
+       $shortPath = str_replace('//', DS, $shortPath);
 
-       $pathArray = explode('/', $shortPath);
+       $pathArray = explode(DS, $shortPath);
        $appDir = array_pop($pathArray);
-       $rootDir = implode('/', $pathArray);
+       $rootDir = implode(DS, $pathArray);
        $rootDir = str_replace('//', '', $rootDir);
 
        if(!$rootDir) {

 

2006/11/21追記:
修正パッチを取り込んで貰えました。https://trac.cakephp.org/changeset/3872
他にも修正されていますし、いずれ1.1.11が出そうですね。

日付時間はDateTimeクラスで

  • 2006-11-10 (金)
  • PHP
この記事の所要時間: 357

5.2.0の新機能にDateTimeクラスがあります。既存のdate関係の関数をクラスにまとめたもののようです。

以前から思っていたのですが、日付時間データを文字列や数値で持っているのに違和感がありました。特にDBからデータを取得した際、DBで日付時間型(PostgreSQLならtimestamp型)のものはPHPでもそのまま扱えないかな、と思っていました。

そこで自分が構築しているアプリケーションではDBのレコードをModelに格納する際に自作のDateクラスに変換しています。こうしておけばそのModelを使う場合は日付時間をDateクラスのメソッドで操作できます。イメージとしては以下のような感じです。

< ?php
class MyModel {
  /** 登録時間 */
  var $regiterTime = null;
}

// DB からモデル生成
// ....

// 年だけを取得
$model->registerTime->getYear();
// YYYY/MM/DD文字列で取得
$model->registerTime->getFormatString('Y/m/d');
?>

日付時間は色々なフォーマットに変換して表現する(YYYY/MM/DDにしたりYYYYだけ取ったり)のでクラス化した方が後は扱いやすいと思うのですが、あまりこういった話は聞かないですね。DBの日付時間型関数が充実しているだけにPHPでも、と考えてしまいます。

そこで冒頭のDateTimeクラスです。

いずれはPDOを使ったDBアクセスではDBの日付時間型をこのクラスに変換してくれるようになって、日付時間はDateTimeクラスで扱うというのが標準になってくれれば良いなあ、と淡い期待を抱いています。

常にDateTimeクラスにされると困る人もいるでしょうから、イメージとしてはこんな感じでしょうか。

< ?php
  // createdの内容をDateTimeオブジェクトにする
  $stmt->bindColumn('created', $created, PDO::PARAM_DATE);
?>

ひそかに注目のクラスです。

 

2006/11/10追記:PDOとの連携を考えてみました。

かなりadhocな方法ですが、いちおうDBの日付時間型をDateTimeクラスで表現できます。

< ?php
class MyModel {
  private function __set($name, $value) {
    if ($name == 'created') {
      $this->{$name} = new DateTime($value);
    } else {
      $this->{$name} = $value;
    }
  }
}

dl('php_pdo_pgsql.dll');
try {
  $dbh = new PDO('pgsql:host=localhost;dbname=xxx', 'xxx', 'pass');
  $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  $stmt = $dbh->prepare('SELECT id,created from users where id=?');

  $stmt->execute(array('1'));

  while ($ret = $stmt->fetchObject('MyModel')) {
    printf("id:%d %04d年%02d月%02d日", $ret->id
                                    , $ret->created->format('Y')
                                    , $ret->created->format('m')
                                    , $ret->created->format('d'));
  }

  $dbh = null;
} catch (PDOException $e) {
   print "error!: " . $e->getMessage() . "<br />";
   die();
}
?>

CakePHP cakeError()は値を返さない

この記事の所要時間: 150

cakeError()は値を返さない、という話です。

Well, this solution would work fine as long as it is only used internally (even though it is not very elegant). But the framework allows you to write a custom error handler, and so if you want to handle a “missing helper file” error yourself, you get PHP errors when you don’t use an exit.

cakebaker » Don’t rely on side effects in your code

はじめてこの箇所のコードを追っかけた時にちょっと頭が「?」になりました。エントリでも言及されていますが、自分でエラーハンドラを作る際はこれを意識しておかないとまずい事になりますね。

どうせErrorHandlerでexitするなら、単純にcakeError()は値を返さず、メソッド内でexitすれば良いような気もします。コードで書くとこんな感じですね。

エラー呼び出し元

< ?php
...
//return $this->cakeError(...);
$this->cakeError(...); // returnしない
...
?>

Object#cakeError()

function cakeError($method, $messages) {
...
  if (class_exists('AppError')) {
    $error = new AppError($method, $messages);
  } else {
    $error = new ErrorHandler($method, $messages);
  }

  exit;
}

CakePHP1.1.10.3825リリース

この記事の所要時間: 059

CakePHP1.1.10.3825がリリースされました。(1.1.9がリリースされたのですがバグがあったようで、すぐに1.1.10がリリースされています。)

バグフィックスが主なですが、ACLに大きな変更がなされたようです。(ACL使ってます?)

1.1.8とのdiffを見てみると以前あった「Controllerのメソッドが外部から呼べる」(CakePHP Controller小話)の対策がなされていました。Controllerクラスにあるメソッドは直接外部からは呼べなくなっていますね。(Missing Methodが表示されます。)あとはAppControllerや各コントローラでアクション以外のメソッドを書かないようにすれば、ひとまず外から任意のメソッドを呼ばれる心配は無くなりました。

あとbakeにも色々と改良が加えられています。近頃はフレームワーク自体の出来もそうですが開発をサポートするツールの存在が大きいのでこれは嬉しいですね。

 

移行の方法ですが、ACLを使っていなければ1.1.10のcake/を既存のcake/にコピーすればokです。

PHP5.2.0リリース

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

PHP5.2.0がリリースされましたね。

The PHP development team is proud to announce the immediate release of PHP 5.2.0. This release is a major improvement in the 5.X series, which includes a large number of new features, bug fixes and security enhancements.

PHP: PHP 5.2.0 Release Announcement

バージョンNoからも分かるとおり大きな修正が行われています。このリリースでPHP5.1系はもうリリースされなくなるようです。リリースノートの和訳はPHPの次期バージョン、PHP 5.2.0 リリース – PHPプロ!ニュースにあります。

PHP5もどんどんバージョンが上がっていますが、私の周りではまだまだPHP4がバリバリ動いてたりします。;-)

既に問題が見つかっているようなのでご注意を。

WIMP?WISP?WAPP?

  • 2006-11-01 (水)
  • PHP
この記事の所要時間: 124

ZendとMicrosoftが手を組んだようです。

Zendの共同創設者兼技術担当バイスプレジデントであるAndi Gutmans氏は、31日に開催のZend/PHPカンファレンスにおいて、PHPソフトウェアの信頼性を向上させ、Windowsサーバ上での速度を 2~3倍加速させる改良内容を発表すると述べていた。同氏によると、PHPの稼動プラットフォームとしてより一般的な「Linuxとほぼ同レベルの性能を達成することができた」という。

MSとゼンド、オープンソースPHPソフトのWindowsサーバ対応で提携 – CNET Japan (2006-11-01)

LAMP(LAPP)構成がデファクトとなりつつあるのになぜWindows?MicrosoftにはASP.NETがあるのになぜPHP?と双方ともに疑問はありますが、お互いの領域を広げていきたい(言語・プラットフォーム)のが狙いなのでしょう。

通常のインターネットに出るサーバはLA(M|P)Pで構築するのがほとんどですが、イントラネットでWAPP(Windows/Apache/PostgreSQL/PHP)で構築したことがあります。短時間に集中して負荷がかかるシステムなのですが、安定して稼働しているようです。

さらにこのプロジェクトではWAPPサーバとLAPPサーバのデータ連携もあったりしてプラットフォームを選ばず同じ言語で開発できたのは有り難かったですね。

ちなみにWIMPは[Windows/IIS/MySQL/PHP]、WISPは[WINDOWS/IIS/SQLServer/PHP]らしいです。呪文ですね。:-)

PHP開発手法いろいろ

  • 2006-10-31 (火)
  • PHP
この記事の所要時間: 231

PHP開発に有用な開発手法がPHPDeveloper.org: ZendCon 2006 Notes: Best Practices for PHP Developmentで紹介されています。

ZendCon 2006のセッションで発表された内容で、セッションの資料はMikeNaberezny.com » Best Practices of PHP Developmentに置かれています。

Source Documentation

PHPDeveloper.org: ZendCon 2006 Notes: Best Practices for PHP Development (2006-10-31)

PHPDocでコメントを書きましょう、という内容です。見知らぬコードを読む際はこれがあるとホントに有り難いです。JavaDocを書いたことがあるのでこれは実践しています。ただ自己流も混じっていてクラスの変数は普通に[//]コメントで書いてたりしてます。。。

Unit Testing

PHPDeveloper.org: ZendCon 2006 Notes: Best Practices for PHP Development (2006-10-31)

本当は全てのコードをUnitテストした方が良いのでしょうけど、複雑なモジュールについてのみ行っています。ただ効果は体感しているのでテストするコードの範囲は以前より広がっています。業務ではPHP4を使用しているのでPEAR::PHPUnitを使用しています。

また最近はフォーム入力が絡む画面ではSelenium IDEを使ってテストしています。UIのテストツールとして有用なのはもちろんですし、ただ単にフォーム入力ロボットとして使っても便利です。

Source Control

PHPDeveloper.org: ZendCon 2006 Notes: Best Practices for PHP Development (2006-10-31)

ソース管理にはSubversionを使ってます。複数のマシンでのソース同期はもちろんのこと、細かいリリースを行うWebシステムではコミット履歴が役立ちます。ある意味コミット時のコメントとソース履歴はドキュメントと言えると思います。

Deployment

PHPDeveloper.org: ZendCon 2006 Notes: Best Practices for PHP Development (2006-10-31)

これが目下の悩みどころです。自社サイトでは稼働サーバからSubversionリポジトリを見てチェックアウト(アップデート)するので問題無いのですが、お客様のサーバだとそうもいかないのが現状です。ですので現在はローカルコピーをscp等でアップロードしています。まれにアップロードする漏れが発生するのでここを上手くまとめたいですね。

ホーム > PHP

検索
フィード
メタ情報

Return to page top