PHPの匿名関数のメモ(多次元配列のソート)

10月 31st, 2008 admin

最近存在を知ってからよく使うのだけど、何度も忘れて検索するのでメモ
2次元配列とかでソートしたいときに便利

PHP:
  1. $langs = array(
  2.          array("name" => "php","age" => "13"),
  3.          array("name" => "ruby","age" => "15")
  4.        );

↑これのageでソートしたいって時が結構ある
まず普通はusortとユーザ定義関数でやる

PHP:
  1. function sortByAge($a,$b){
  2.   return $a["age"]> $b["age"];
  3. }
  4. usort($langs,"sortByAge");

これでOK。だけどなんだか関数の定義が面倒くさい。
んで、そんなときにusortとphpの匿名関数であるcreate_functionを使うとすっきりかける

PHP:
  1. usort($langs, create_function('$a,$b','return $a["age"]> $b["age"];'));

これだけで$langsがageでソートされるので便利。

まとめ

・PHPよりRubyが年上なのが少し驚いた
・匿名関数と無名関数。どちらの言い方が正しいのか知りたい。

CakePHP1.1のページングでGETパラメータを正しく引き継ぐ

9月 27th, 2008 admin

以前にCakePHP1.1用のPaginationコンポーネントを紹介したんですが、getパラメータに配列を使うと正しくリンクを作ってくれなかったのでそれの補足。

要するにhttp://example.com/?data[Search][name]=1とかって感じの配列がGETパラメータにある場合に、このパラメータを引き継いでくれない(data=Arrayとかってなる)バグを修正した。

/views/helpers/pagination.phpの_generateUrlってメソッドを修正する。
http_build_queryっていう関数を使ったんですが、これは配列もしくはオブジェクトからURL エンコードされたクエリ文字列を生成する関数で、なんと多次元配列にも対応している。さすがPHP!(オブジェクトに対応してるほうが変か)

PHP:
  1. function _generateUrl ($page=NULL,$pageDetails=NULL)
  2.     {
  3.         $pageDetails = $pageDetails?$pageDetails:$this->_pageDetails;
  4.         $getParams = $this->getParams; // Import any other pre-existing get parameters
  5.         if ($this->_pageDetails['paramStyle']=="pretty")
  6.         {
  7.             $pageParams=$pageDetails['importParams'];
  8.         }
  9.         $pageParams['show'] = $pageDetails['show'];
  10.         $pageParams['sortBy'] = $pageDetails['sortBy'];
  11.         $pageParams['direction'] = $pageDetails['direction'];
  12.         $pageParams['page'] = $page?$page:$pageDetails['page'];
  13.         if (isset($pageDetails['sortByClass']))
  14.         {
  15.             $pageParams['sortByClass'] = $pageDetails['sortByClass'];
  16.         }
  17.         $getString = Array();
  18.         $prettyString = Array();
  19.         if ($pageDetails['paramStyle']=="get")
  20.         {
  21.             $getParams = am($getParams,$pageParams);
  22.         }
  23.         else
  24.         {
  25.             foreach($pageParams as $key => $value)
  26.             {
  27.                 if (isset($pageDetails['Defaults'][$key]))
  28.                 {
  29.                     if (up($pageDetails['Defaults'][$key])<>up($value))
  30.                     {
  31.                         $prettyString[] = "$key{$pageDetails['paramSeperator']}$value";
  32.                     }
  33.                 }
  34.                 else
  35.                 {
  36.                     $prettyString[] = "$key{$pageDetails['paramSeperator']}$value";
  37.                 }
  38.             }
  39.         }
  40.  
  41.         $url = $this->url;
  42.         if ($prettyString)
  43.         {
  44.             $prettyString = implode ("/", $prettyString);
  45.             $url .= $prettyString;
  46.         }
  47.         if ($getParams)
  48.         {
  49.             $url .= "?". http_build_query($getParams);
  50.         }
  51.         return $url;
  52.     }

CakePHP1.1でキャリアごとの絵文字を表示

9月 5th, 2008 admin

すでにいろいろな方法があるようです。
CakePHPで3キャリア携帯の絵文字を表示する :: Webプログラマー+WebデザイナーなZARU日記(DB使用)
ひでぶろぐ CAKEPHP絵文字入力・出力ヘルパー(DB使用)
EmojiHelper - キャリアを意識せずに絵文字を出力できるCakePHPのHelperクラス - 芋ではない日記(JSON使用)

僕はDBを使うのが嫌だったのとJSONは使ったことがなかったのでMobilePictogramConverterという絵文字ライブラリがあるのでそれを使いました。

特徴
* DoCoMo, au, SoftBankの絵文字を相互変換可能
* 端末からサーバーへ送信された絵文字の変換が可能(掲示板など)
* SJIS/UTF-8に対応
* PCでの絵文字表示が可能(画像)
* 絵文字画像は全て透過GIFでアニメーションに対応
* DoCoMo隠し絵文字一部対応
* バイナリコード, Web入力コード, imgタグからの変換が可能
* 絵文字の削除が可能
* 文字列に含まれる絵文字の数を検出
* UserAgentからキャリアを判別し、キャリアに合った絵文字に自動変換が可能

すごいです。作った人。

手順

(1)MobilePictogramConverterを取得して解凍
(2)MobilePictogramConverterを/app/vendorsにいれる
(3)MobilePictogramConverterのimgをWEBROOT_DIR/img/m/にいれる
(4)/app/app_controller.phpを編集

PHP:
  1. <?php
  2. vendor('MobilePictogramConverter/MobilePictogramConverter');
  3.  
  4. class AppController extends Controller {
  5.  
  6.         //app_controllerのいろいろは省略
  7.  
  8.         function beforeFilter() {
  9.             ob_start();
  10.             parent::beforeFilter();
  11.         }
  12.  
  13.         function afterFilter() {
  14.             parent::afterFilter();
  15.  
  16.             // バッファを取得して、出力バッファをクリア
  17.             $out = ob_get_clean();
  18.  
  19.             if ((isset($this->params["webservices"]) && $this->params["webservices"] == "Mobile")) {
  20.                 $out = mb_convert_kana($out,"k","UTF-8");
  21.                 $mpc =& MobilePictogramConverter::factory($out, MPC_FROM_EZWEB, MPC_FROM_CHARSET_UTF8, MPC_FROM_OPTION_WEB);
  22.                 $mpc->setImagePath(WEBROOT_DIR . 'img/m/');
  23.                 $out = $mpc->autoConvert();
  24.             }
  25.  
  26.             echo $out;
  27.         }
  28. }
  29. ?>

バッファをためて一括で変換しています。絵文字と一緒に全角カナも半角カナに直してしまいます。
$this->params["webservices"]で判別しているのはShin x blogさんの「CakePHP 携帯用ビューを表示する」を使用して携帯のビューを切り替えているからです。

これで携帯のビュー内で>img localsrc="180"/<とかってやると絵文字が表示されます。

akismetでスパム対策が簡単かつ強力

8月 28th, 2008 admin

当ブログはwordpressを利用しており、スパム対策にakismetというのを使用しています。
これがなかなか強力で今までで1000以上のスパムを間違いなしで弾いてくれています。

今回べつのサイトの掲示板にて、botによる荒らしがひどかったためスパム対策をしようとしたところ
akismetがwordpress以外にも簡単に利用できることがわかったため導入してみました。

準備

http://akismet.com/
ダウンロードしたらユーザ登録をしてAPIキーを入手

APIキーを入手するにはwordpress.comのアカウントを作成する必要があります。

サインアップページ
http://wordpress.com/signup/

アカウントを作るとブログがもらえますが今回は必要ないので「Just a username, please.」にチェックを入れるようにします。
アクティベーション用のメールがきますので、本文に記述されているURLをクリックして登録を完了させます。
すると再度メールがきてAPIキーが手に入ります。

次にPHP用のクラスライブラリを手に入れます。
http://akismet.com/development/
ここにはRoR用やJava用や、各種ブログ用などすぐに使えるライブラリがたくさん用意されています。

今回はPHP5なので「PHP 5 class by Alex」を落とします。
あとは書き込みの直前などで以下のコードを実行

コード

PHP:
  1. include("Akismet.class.php");
  2. $akismet = new Akismet("http://"."サイトURL","自分のAPIキー");
  3. $akismet->setCommentAuthor($data['name']);
  4. $akismet->setCommentAuthorEmail($data['email']);
  5. $akismet->setCommentAuthorURL($data['url']);
  6. $akismet->setCommentContent($data['body']);
  7. if($akismet->isCommentSpam()){
  8.     exit("大変申し訳ありませんが、システムの都合で書き込みができませんでした。");
  9. }

これで完了。
Author,AuthorEmail,AuthorURLは空文字でもいいみたいです。

まとめ

CAPTCHAなどの導入も考えましたがユーザの負担がないのが一番ですからね。
あとは誤認識があっても大丈夫なようにエラーメッセージをキャッチする仕組みを用意すれば万全です。
ブログでの実績からすれば全然大丈夫だと思いますが、これでしばらく様子を見てみます。

デザイナーのためのCakePHP1.1メモ

5月 18th, 2008 admin

デザイナーのためのCakePHP入門」というエントリを書いていたのですが、さしあたって1.1の説明が必要になったのでデザイナーさん向けのメモ。主にビューでのHTMLヘルパーの説明になります。

どこを編集すればいいのか?

/app/views

テンプレートファイルがあります

/app/webroot

Stylesheet、Javascript、画像、そのほかのファイルなどはこちらにおきます。css,js,imgというディレクトリがあらかじめ用意されています。大変申し訳ないのですがディレクトリ名はこのまま使ってください。(変えたい場合はプログラマに相談してください)

テンプレートの構造

ここからは/app/views以下の話になります。
まずレイアウトが/layout以下にあり、layoutファイルの中の

<?php echo $content_for_layout ?>

という記述のところに中身が差し込まれます。

<?php echo $this->renderElement('なんとか'); ?>

という記述を見つけたら、それは「/views/element/なんとか」ってファイルを取り込んでいますので、そちらを見てください(layoutファイル以外でも使われます)

各種タグなど

各種外部ファイルの読み込み

PHP:
  1. <?php echo $html->css('import'); ?> //スタイルシートを読み込む
  2. <?php echo $javascript->link('prototype');?> //Javascriptを読み込む

拡張子は省略できます。それぞれ/app/webroot/css,/app/webroot/jsに入れておいてください。

画像を表示

PHP:
  1. <?php echo $html->image("logo.gif") ?>

これで/app/webroot/imgにあるlogo.gifを表示します。

PHP:
  1. $html->image('logo.gif',array("id"=>"logo","alt"=>"会社ロゴ"));

第2引数にハッシュを渡してやることでimgタグにid="logo",alt="会社ロゴ"が追加されます。

リンク

PHP:
  1. <?php echo $html->link("トップ" , "/top"); ?>

とやると、/topへのトップというリンクを表示します。

PHP:
  1. <?php echo $html->link("トップ" , "/top",array("target"=>"_blank")); ?>

このタグもハッシュで属性を追加できます。この場合はtarget="_blank"が追加されます。

画像でのリンク

PHP:
  1. <?php echo $html->link($html->image("/logo.gif",array("id"=>"logo")),"/top",false,false,false)?>

画像でのリンクは画像とリンクのタグを組み合わせるとできます。後半にfalseが3つも並んでいて無駄に見えますがこれは必要なので書くようにしてください。

まとめ

この他にもフォームを書くときなども専用のコードを書く必要があります。面倒くさいですね・・・