php5.3.3 centos6.8 composerインストール手順

インストール

curl -sS https://getcomposer.org/installer | php

composer.pharが出来るので移動

mv composer.phar /usr/local/bin/composer

composer.jsonを作成する

cd /usr/local/bin
vi composer.json

内容

{
    "require": {
        "monolog/monolog": ">=1.0.0"
    }
}

jsonに書いたmonologをインストール(5~10分くらいかかる)

php composer install

vendor配下にインストールされる。後composer.lockが作成される。
さらにパッケージを追加してみる。composer.jsonにpayjpを追加。

{
    "require": {
        "monolog/monolog": ">=1.0.0",
        "payjp/payjp-php": "0.0.x"
    }
}

インストール

php composer install

エラーが出た

Warning: The lock file is not up to date with the latest changes in composer.json. You may be getting outdated dependencies. Run update to update them.
Nothing to install or update
Generating autoload files

Composerを使ってみた - 戦場のプログラマー
こちらのサイトによるとどうやらupdateが必要らしい

php composer update payjp/payjp-php

これでインストールできた
composerのrequireコマンドでパッケージを後から追加する - Qiita
こちらのサイトによるとrequireでも良かったぽい。
phpでは以下のようにrequireすれば使えるようになる。

<?php
require 'vendor/autoload.php';

参考サイト
composerとは? - Qiita
composer 導入をまじめに考える - Qiita
Composer ドキュメント日本語訳
composerの使い方:Composer でphp のパッケージを楽にする - それマグで!

資産形成におすすめのFX口座はこちら。
http://s2fx.com/ranking/856.html

cakephp1.2 Shellからモデルとコンポーネントを呼ぶ方法

コントローラーであれば$usesと$componentsを使うけど、Shellの場合は$usesは使えるけど$componentsは使えない、というなんとも中途半端な感じだったのでメモ。以下のようにする。

<?php
App::import('Component', 'Sample');
                           
class TestShell extends Shell {
    var $uses  = array('Hoge');

    function initialize() {
        parent::initialize();
        $this->Sample = new SampleComponent($this); 
    }
}

資産形成におすすめのFX口座はこちら。
http://s2fx.com/ranking/856.html

mysql group_concatにorder byを指定する時の注意事項

group_concatにorder byを指定しても意図したソートにならないケースがある。
まず以下のように、group_concatに指定したcategory_idをそのカラム順でソートするケースの場合は問題ない。

group_concat(category_id order by category_id)

問題となるのは以下のようなgroup_concatの対象(category_name)とソートの基準となるカラム(category_id)が異なるケース。この場合、category_nameがcategory_id順に並ばない場合がある。

group_concat(category_name order by category_id)

これを防ぐには【group by-group_concatする前に、データをorder byでソートしておく】ことが必要。なので一つのSQLではできない(はず)ため、サブクエリ等を使う必要がある。

select group_concat(category_name order by category_id) from
(
select item_id,category_id,category_name
from item i
inner join item_category ic on i.id = ic.item_id
inner join category c on i.id = ic.category_id
order by category_id
) as tmp_tb
group by item_id

資産形成におすすめのFX口座はこちら。
http://s2fx.com/ranking/856.html

php csrf対策

参考サイト
PHPでクロスサイトリクエストフォージェリ(CSRF)対策するときのメモ - Qiita

php

<?php
//トークンをセッションにセット
function setToken(){
    $token = sha1(uniqid(mt_rand(), true));
    $_SESSION['token'] = $token;
}

//トークンをセッションから取得
function checkToken(){
    //セッションが空か生成したトークンと異なるトークンでPOSTされたときは不正アクセス
    if(empty($_SESSIOIN['token']) || ($_SESSION['token'] != $_POST['token'])){
        echo '不正なPOSTが行われました', PHP_EOL;
        exit;
    }
}
//GETでアクセスされたとき
if($_SERVER['REQUEST_METHOD'] != 'POST'){
    setToken();
}
//POSTでアクセスされたとき
else{
    checkToken();
}

html

<form method="post" action="">
...
<!--hiddenで生成したワンタイムトークンの文字列をPOST送信-->
<input type="hidden" name="token" value="<?php echo h($_SESSION['token']); ?>">
<input type="submit" value="登録">
...
</form>

post時にtokenをポストする必要がある

cakephp1.2 componentの$enabledでNoticeが出る件

本来componentを使うと$enabledがセットされるんだけど、beforeFilter()の中でcomponentをnewしてしまうと、$enabledが定義される前にstarup()とかを呼んでしまい、Noticeが出るのでcomponentをbeforeFilter()の中でnewしないこと。

$enabledはcomponentのstartupやらのcallbackを実行するかどうかのフラグ。falseにするとそれらが実行されない。

追記
アホだった。controllerであれば「var $components」でcomponent設定するからcomponentをnewする必要ないの忘れてた。バッチと完全にごっちゃになっていた。注意すること。

mysql テーブル設計 カンマ区切りのカラムについて考察

例えば商品の属性とかレコードに紐づくデータが沢山あってレコード毎にデータ作ると色々面倒なケース。

DB設計の基本について 例えば一つのレコードが複数のカテゴリに… - 人力検索はてな
MySQLでカンマ区切りの値を登録してみる | シスデイズ技術ブログ
まさにこういうケース。基本はやはり忠実に正規化するのがベターらしいが、場合によってはカンマ区切りにするのもあり。ただカンマ区切りにしてしまうとjoinが面倒になるぽい。柔軟なのはやはり正しく正規化する方なんだと思う。

正規化した場合の問題について
まず正規化した場合、上の例でいうとAカテゴリとBカテゴリに属するレコードを取得する(AのみBのみは除く)となった場合、一番シンプルなのがgroup_concatでカンマ区切りにした結果に対してfind_in_setで絞り込む方法では無いかと思う。

しかし他のテーブルと結合したいと(group_concatでgroup byしてさらにの他のテーブルのカラムでgroup byしたい場合等)なった場合、いったんgroup_concatして、その結果を副問合せとかで結合、という手順を踏まないといけなくなるため、最初からカンマ区切りのデータであればその辺がシンプルになるはず。

データが膨大な場合は、「いったんgroup_concatして」すら出来なくなると思うので、最初からカンマ区切りならそのまま別テーブルと結合して、別テーブルの条件で絞り込んだデータに対してfind_in_setをすれば良い訳だから、データ量によってはパフォーマンスが圧倒的に変わると思う。

とはいえjoinが出来ない(面倒な)のも痛いしな~、両方用意して使い分けるのもありかもしれんけどな。片方更新したらもう片方も更新しないといけないから、その辺は覚悟せなあかんくなる。

全ての要件を満たす方法が無いとなると、後は何を優先させるかだな。パフォーマンスなのか開発工数なのか保守性なのか。ただ絶対に守らないといけないことが1つあって、それは「シンプルである」ということ。これだけは絶対に外してはいけない。

よく考えた結果、テーブル結合が発生する場合は副問合せはどうしても必要になるけど、サブクエリにするタイミングをずらすことで正規化でもパフォーマンス落とさずにできるかも。もうちょっと検証してみる。

結論
自分のSQLがダメだっただけで、やっぱり正規化でパフォーマンス落とさずに対応することができた。なので正規化のデメリットはデータ数が増えることくらいではないかな。でもそれはシステム化すれば大した問題ではない。なのでカンマ区切りにはやっぱりしないこと。

資産形成におすすめのFX口座はこちら。
http://s2fx.com/ranking/856.html

cakephp1.2 database.phpのdefaultに設定されているDBのテーブルはModelファイルの作成が必須ではない

ClassRegistry::init('ModelName');

こんな感じでmodelsフォルダに存在しないModelを読み込んでいた場合に、何故かエラーになる場合とならない場合があって1時間くらいはまってしまったのでメモ。

どうやらdatabase.phpで$defaultに設定されたDBのテーブルだとModelファイルが無くてもエラーにならないっぽい。(もちろん実際のテーブルが存在しなかったらエラーになるが。)

defaultのDBであればModelファイルが無くともfindとかも普通に使える。

今までModelファイルが必須だと思い込んでいたのでもう二度と忘れないこと。