「cakePHP」カテゴリーアーカイブ

【cakePHP3】bakeで自動生成されるリンクは動詞と名詞を別々に__()に翻訳させるといいですよ

最近、cakePHP3を使っています。
しばらくfuelPHPとか、あと名前も忘れましたがいくつかPHPフレームワーク使っていました。
しかしcakePHPの規約たくさん、でも覚えてしまえば分かりやすいぬるめのお湯的な感覚が忘れがたく、PHP5.2を捨ててクラスのauto loadとチェインによるSQL生成さえ対応してくれればいつでも戻ってくるつもりでした。そしたら、いつの間にかcakePHP3になってそれらも実装されているし、いろいろ変わっているではありませんか。

しばらく使ってみた感想は、正統な進化で慣れてくるとやはり使いやすいです。しかし、ドキュメントの劣化がひどいです。かなり公式が分かりづらいです・・・。

さて、今日はbakeで自動生成されるView画面のリンク名を日本語に翻訳していく時の簡単なテクニックです。

↓画像のように日本語化したいと思います。

とコマンドを打てばtexturesテーブルを元にindex,view,edit,addの各画面を勝手に作ってくれる、モックアップに超便利な機能です。
生成した画面の左のメニューなど、ソースでは
といった感じになっていると思いますので、翻訳ファイル(src/Locale/ja/default.po)は
が必要ですね。
List ..以外にもAdd ..、New …などあり、これだと翻訳が必要になる文章が多くなりますので
とViewを書き換えることを提案します。
を用意したら “Textures一覧”と翻訳されます。
Texturesの翻訳も用意したらちゃんと「画像一覧」と全文翻訳されます。この方法だとdefault.poの記述はかなり少なく済みます。
既に生成された全ファイルに対して一気に変えたいという場合は
の正規表現でどうぞ。
あれ、この内容、前にもどこかに書きましたっけ??
あとは生成するテンプレート自体を変えるやり方とか、翻訳のもう少し詳しいやり方とか気が向いたら書きます。

【cakePHP】配列を組み替える便利なHashクラス

cakePHP使っててうれしいのが、Hashクラスが組み込まれていることです。

これはとっても便利なので、他のフレームワークを使う時でももし同等のものがなければコピーして使おうかと思っています。

サンプルコード

いくつか簡単な例をあげます。

このような配列があるとして、

4番目のユーザーの名前を取り出したいとき

Result:

Userの下の配列は数値キーで0から始まっているので4番目を指定するには3になります。説明無用とは思いますが念のため。

idが2のユーザーの名前を取り出したいとき

[配列名=配列値]の書式で条件式を書けます。

Result:

配列名がなければ配列番号でもいけます

Result:

Hashクラスのマッチャで使える記号:

‘=’
‘!=’
‘>’
‘<‘
‘>=’
‘<=’

等号は==でなく=なので注意してください。

配列のキーをidにして必要なデータのみの配列を作りたい時

Result:

このようにすっきりした配列を作成できます。リンクリストなどを作るのに活躍します。

条件式で指定したデータの配列を生成する

combineとマッチャを組み合わせて使用するときに注意しないといけないのが、第2引数と第3引数、両方にマッチャを指定しないといけないことです。キーと値の数が合わないとfalseが返ってきます。

Result:

グループIDでグルーピングしたユーザー配列を生成する

2次元配列を作るにはcombineに引数を追加します。

Result:

group_idでユーザーを分けることが出来ましたね。

複雑な階層の多次元配列を扱う

不特定のキーを表すのに{n}と{s}があり、nが数値キー、sは文字列キーに対応しています。Hashパス構文の中に何個でも出現して構いません。

Result:

キャラクターの持つアイテムリストができました。idをキーとすることで重複は省かれています。

sptinrfの結果を値に入れる

Hash::formatを使えばsprintfの結果を取り出せます。

Result:

これをHash::combineでやるときには第3引数を配列にして、1番目にフォーマット文字列を入れます。

Result:

 

ほかにもいろいろ便利ですが

文字列を生成したり、配列に値を加えたり削除したり、非常にいろんなことができますが、抽出系に絞って書いてみました。

cakePHPの公式ドキュメント「Hash」をみれば全部書いてますが、サンプルが少ないのでちょっと分かりにくいかもと思うところもあります。

これを参考に、配列を自由に扱えるようになるとデータの扱いもぐっと幅がでてくることでしょう。

最後に、進撃の巨人のキャラクター名をサンプルに使ったのは深い意味はないのでその辺のツッコミは無用でお願いします。

【cakePHP】繰り返しrequestActionを呼び出すのをApp::usesにしたらメモリ使用量が抑えられた

cakePHPのシェルコマンドモードから繰り返しrequestActionを呼び出すコードを実行すると、2000回くらい繰り返したところでメモリオーバーで停止していたのを解決しました。

PHPバージョンが5.2なもので、バージョンアップすればガーベッジコレクションが効いてなんとかなるかも(PHP マニュアル >機能 >ガベージコレクション)、とも思ったのですが、お客様のサーバーだし、そもそもメモリーを使い続けるのがおかしいのでなんとかしてみます。

まず、メモリ使用量の計測

結果:

どんどんメモリ使ってますね。requestActionがかなりメモリを消費する関数だって事は分かっているので、ここをもう少し低レベルなものに置き換えます。単純にControllerクラスを呼び出すのがいいでしょうが、cakePHPにはApp::usesを使った便利な呼び出しがあります。

改善された!ちょっとづつ増えていますが、16Mくらいで安定して、増え続けるという事はありませんでした。

最初にApp::uses(“ItemsController”, “Controller”);で使用する事を宣言しておきます。App::importでもいいのですが、cakePHP2ではusesの方が使用する時だけ呼び出すのでいいっぽいです。

使用する時は$ItemsController = new ItemsController;で宣言して、いつも通り$ItemsController->action()でいいのですが、これだとbeforeFilterが実行されません。
$ItemsController->constructClasses();
$ItemsController->startupProcess();
をクラスの宣言直後に行う事で、初期化されるようになりました。

コントローラーの変数は直接操作できるので、$ItemsController->request->params[‘requested’] = 1のようにリクエスト変数をいじってrequest_actionと同じパラメータにすることもできます。

【cakePHP】.htaccessでmod_rewriteを使いつつ特定のURLをBASIC認証なしにする

毎日スパムコメントを捨てています、自宅プログラマです。

さくらのレンタルサーバーってCGI版PHPなんで、CakePHPの認証モジュールを使えないんですよねー。そういうわけで、apacheでBASIC認証かけていました。最初の.htaccessはこうです。

AuthUserFileは自分で作ってくださいね。bakerattaというのはfoobarやhogeと同じようなメタ構文変数ってやつです。

How to make Basic Auth exclude a rewritten URL
をみて

をやるとmedicine以下の時だけ$_SERVER[‘REDIRECT_noauth’]という変数ができてました。$_ENVにも同じものが。なんだ、これ、おもろー。なんでREDIRECT_がつくんだろ。$_SERVER[‘REDIRECT_REDIRECT_noauth’]ってのもできるし。そっか、URLが書き換わるたびにhtaccessを評価するんですね。
って、最初、環境変数がセットされているか確認の仕方が分からず、ここまででかなり苦労しました。呼び出したPHPでphpinfo()を実行すればapacheの一時変数も$_SERVERに入るんで、これで足がかりができました。
phpinfoの結果

んで、それでもうまくいかず、いろいろやっているうちに結局mod_rewriteの環境変数使わなくてもSetEnvIfだけでいけました。

Satisfy にanyを設定することにより、ユーザー認証だけでなくホスト制限もみてくれるようになります。
これで通常はBASIC認証かけつつ、medicineディレクトリ(と、そこから呼び出されているcss/imgディレクトリ)以下がBASIC認証対象外になりました。

ポイントは、Rewrite書き換え前と書き換え後、2つのURL両方を書いておくことです。

SetEnvIfを使ってBASIC認証解除したいURLを加えていけばいいので分かりいいですね。

## 2016/03/16 追記
img/x.gifのようなファイルをリクエストしているにも関わらずファイルがみつからない404の時にもBASIC認証がでていたので
SetEnvIf Request_URI “/webroot/index.php” noauth
を追記しました。
ファイルがない場合、cakePHPはwebroot/index.phpにリダイレクトするのでここも許可対象に入れたということです。一見すべてのアクセスが許可されたように思えますが、URLが書き換えられる前もチェックされるのでこれでいいのだ!
あと、特定のコントローラだけBASIC認証かける時とかはPHPで処理した方が簡単です。
HappyQuality – [CakePHP][PHP]コンポーネントを利用せずにベーシック認証を実装する

【cakePHP】重複を省いたPaginator

重複を省いて正しい件数をだすPaginatorのやり方です。

データを取得するだけなら
CakePHP の find で DISTINCT を使って重複した行を除外してデータを取得する方法[WEBLE]

でいけます。

ページ分けをしてくれる便利プラグイン、Paginatorを使っているとどうでしょう。
fieldsはPaginatorに設定することができますが、カウントしている部分には使ってくれません。
どうしようかと思ったらPaginatorで自分用のカウント方法を設定する方法がありました。

モデルの中にpaginateCount関数を作ればよかったです。

【cakePHP】SSLと非SSLが共存するサイト

ひとつのサイトの中にSSLページと非SSLページを混ぜる場合は注意が必要です。

http://book.cakephp.org/2.0/ja/development/sessions.html
に書かれてあるように、session.cookie_secureをfalseにしないとcookieが継続できません。

SSLページから他のページに飛ぶときに、相対リンクだとやはりSSLのかかったページにとびます。暗号化通信を解除しようと思うとhttp://から始まる絶対リンクで書かないといけません。
これを相対リンクのままにして強制的にhttpかhttpsに振り分けるようにしたやり方も書いときます。

config/route.phpでsslディレクトリ以下へのアクセスはpssl/を省いたコントローラ・アクションにアクセスし、パラメータsslを入れるよう設定。

AppControllerでアクセスのたびに環境変数のHTTPSとパラメータsslを比べてリダイレクトし直しています。

【cakePHP】コントローラからViewファイルを使う

cakePHPのサイトでユーザーにメッセージを送るときに、テンプレートファイルで内容を用意しておきたいな、と思ったもので、コントローラーから好きなViewファイルの内容を変数に入れるのをやってみました。CakeEmail.phpを参考にしました。

コントローラのアクションの中で

フォルダ名は既存のものに階層を掘っても(/スラッシュが使える)新しく作ってもかまいません。ファイル名のtemplate_nameを書き換えることで好きなViewファイルを使えます。

【cakePHP】トグルスイッチをAJAXで反映させる

さして目新しいことでもないですが簡単な小ネタでも。

トグルスイッチを切り替えるたびにDBを書き換えることは簡単にできます。
cakePHP2.0+jQueyMobile1.2でのトグルスイッチのDBへの反映のやり方です。いいやり方か分からないですが何かの助けになればと。

cakePHPのアクションは

こんな感じです。これをコントローラに記述して /{コントローラ名}/toggleValid/{ID} にアクセスするたびにvalidカラムが0と1に交互に変わります。CASE文で判定すればいろいろできて便利なのでcakePHPでSQL組み立てるやり方が分からないときはとりあえずqueryファンクション使っちゃいます。

そしてこの関数はコントローラーでなくモデルに書くべきものなので実際にはモデルに書いてます。またjQueryMobileと組み合わせているので下のようになります。

[共通読み込みJavaScriptファイル]

このファイルはjQueryMobile特有の処理をしています。最初のイベントバインドはDOMキャッシュを有効にしたままJavascriptを実行させるため、data-role=”page”の属性を持つコンテナにidを割り振り、そのページコンテナの初期イベントを監視しています。

[ビューファイル(index.ctp)]

$validと$idはコントローラからセットしておいてください。data-idはjQueryMobileではおなじみのHTML5の独自データ属性です。これでデータIDをjQueryへ渡すのが簡単です。

[AJAX呼び出し先コントローラー]

[モデル]

【cakePHP】検索エンジンに補足されないよう削除リンクはPOSTにしよう

かなり前に作ったサービスなんですが、入れたはずのデータが時間が経つと消えているという怪現象に遭遇しました。

いや、分かってみると怪現象でもなんでもなかったんですが、とある中華検索サイトが削除リンクをクローラ収集中に踏んでいたのでした。

こういうことが起きないよう、クローラにアクセスされるとデータが変わってしまうようなリンクはPOSTかJavaScriptを使ったリンクにしましょう。

元のリンク

cakePHP1.3のajaxヘルパー(2.0では非推奨)を使ってリンク先の画面を画面を遷移せずに取得していました。変換されるHTMLをみると

とJavaScriptが実行できないクローラでも普通のリンクとして辿れるようにできています。
POSTに書き換えました。(div内を書き換えるのでなく特定のdivを削除するようやり方は変わってます)
jQueryを使用しています。

ちなみにcakePHP2.0のFormヘルパーにはpostLINKという関数が追加されていますので、動的に書き換えたりしないならこっちを使ったほうが簡単なのではないでしょうか。

キャッシュ可能なURLはGETで、データ操作のあるURLはPOSTで行うと考えると分かりやすいでしょう。

しかし検索クローラはPOSTをSUBMITしないのでしょうか。googleは2012年のWEBマスター向け公式ブログでPOSTリクエストに対応していると明記しています。
いずれまた対策を施さないといけなくなるかもしれません。その時は、パーミッションの与えられた会員ユーザーかどうかをチェックしたうえで削除することになるでしょう。