ラベル php の投稿を表示しています。 すべての投稿を表示
ラベル php の投稿を表示しています。 すべての投稿を表示

2016年12月6日火曜日

リリース前に文法チェックを差分実行して確認する


コード(bach)

git fetch origin
for FILE in `git diff --name-status origin/master -- | grep -E '^[AUM].*\.php$'| cut -c3-`; do
  if php -l $FILE; then
    echo "OK"
  else
    exit 1
  fi
done

解説


まずfetchして最新のmasterを取得します
diffを取得してA: 追加、M: 更新、U: 競合しているファイルを抽出
必要な場所だけ取得してループを回します

$FILEを用いてphp -lで文法チェックする

2015年4月14日火曜日

php短縮タグが使えない!

いつもphpのタグを <?  ?> で書いているのですが、
CakePHP3.0を試すために先日新しく環境を建てた際に <?php   ?> でしか動かなかったのでメモ

調べてみたら簡単なのですが、php.iniで設定が必要みたいです

$ php -i | grep php.ini

short_open_tag の値をオンにする
$ sudo vi /etc/php.ini
;short_open_tag = Off
short_open_tag = On
参考:PHPマニュアル
http://php.net/manual/ja/ini.core.php

2014年10月18日土曜日

cakephp 中間テーブルの命名規則

中間テーブルの命名規則で右往左往したのでメモ

cakephpの中間テーブルの命名規則


複数形をアンダースコアでつなぐ
順番はabc順

「ユーザー」と「趣味」を多対多の関係で表現する場合

interests_usersとなる

modelの命名規則

複数形 + アンダースコア + 単数でつなぐ
順番はabc順

modelは単数なのでモデル名の末尾は単数にする
中間テーブルの一つ目の名称は複数のままにする
interests_user.php

インスタンスの命名規則

アッパーキャメルで複数 + 単数
InterestsUser




2014年10月14日火曜日

cakephp saveAllの仕様

オプションでvalidate onlyとした時、IDの補完はしない

save Allの便利な機能の中に、リレーションを張るとidを保管してくれる機能があります。
しかし、確認画面を挟むなどの理由でバリデーションだけをしたい時に、validatesをonlyとしてしまうと、idの補完は行われません。

なので、そのIDに依存するバリデーション条件が設定されている場合は、必ずエラーに成ってしまうので気をつけないといけません。

User hasone UserInfo

$data = array(
    'User' = array(
        'name' => 'waldo',
        'tel'     => 0123456789,
    ),
    'UserInfo' = array(
        'prefecture' => 'hokkaido',
        'city'           => 'sapporo',
    ),
);
       
$this->User->saveAll($data, $options);

この場合、UserInfo.user_idにinsertしたデータのUser.idが補完されてsaveされます。

$options = array('validates' => 'only');
$this->User->saveAll($data, $options);
とした場合は、上記の補完が適用されないため、user_idの存在の確認や、市外局番と住所の不一致などのバリデーションをuser_id経由で行えなくなります。(user_idが無いというエラーが出ます)

同様のことは
$options = array('validates' => 'first');
とした時にも一度onlyでバリデーションチェックをするので発生しますので注意してください。

解決方法

saveAllを使わない

idを補完したいということならsave後に$this->User->idでinsertしたIDを取得できるので、自前でsaveAll的なメソッドを作ってしまう。
逐一、unsetなどができて自由度が高い。

atomic => false で外部トランザクションをかけて毎回ロールバックする

楽ちんだが、オートインクリメントされていくので、IDが飛び飛びになってしまう

UserInfoバリデーション時にUserのPOST値を見に行く作りにする

UserInfoだけ追加でinsertしたい、updateしたいなどの時に、別途バリデーションを作らないといけない。冗長な作りになってくる



2014年1月19日日曜日

iCLUSTAはphp-5.3.17 配列構造の短縮構文は使えない

久しぶりの更新です。
現在は家計簿アプリのcakephp化を実施しています。

ホームページのサーバーとしてiCLUSTA+を使っていますが、バージョンを意識することがあったので、メモとして記しておきます。

「phpのバージョンはphp-5.3.17」

なぜ調べたかって言うとcakeに書き換えている時に配列構造を

array(
    配列を記述
)


ではなく

[
     配列を記述
]


の短縮構文で書いていて、エラーが出たから。ちなみに配列構造の短縮構文はphp-5.4から使えます。array()に慣れてるわけじゃないから自分としては見やすいので、こっちで書きたいんだけどな。 次回以降、cake関連でいろいろ更新再開します。 あとvim使い出したのでその設定とか

2013年12月3日火曜日

[MySQL]、[php] 分類のindex管理(4)

引き続き分類を文字列からindex管理に変更する過程です。
【関連する記事】
[MySQL]、[php] 分類のindex管理(1)
[MySQL]、[php] 分類のindex管理(2)
[MySQL]、[php] 分類のindex管理(3)

前回まではデータベースに登録されてある分類項目を選択項目としてhtmlで表示するところまで紹介しました。

今回は全ユーザー共通の分類項目とユーザー独自の分類項目を分けて管理する部分を紹介します。


実は、[MySQL]、[php] 分類のindex管理(2)で作ったテーブルにuser_idを入れておきました。このuser_idを使います。
まずはマスターのIDとしてuserテーブルのID=0にmasterとでも登録しておきます。
これが全ユーザーが使う分類項目となります。同時にuser_id=0が、この後ユーザーとして登録されないように埋めておくことにもなります。

ユーザー独自分類登録

では、ユーザーが分類を登録するページを作ります。前提としてユーザーIDが$_SESSION['user_id']によって受け取れる状態としてます。

[specification_choice.php]

<h2>ユーザー独自の分類を登録</h2>
<form action=“insert_action.php” method="post" >  
 <label>名称</label>
 <input type="text" name="specification_name" />
 <input type="submit" value="追加"/>
</form>

[insert_action.php]

$sql = sprintf('INSERT INTO pay_specifications SET name="%s", user_id=%d, created=NOW()',
  mysql_real_escape_string($_POST["specification_name"]),
  mysql_real_escape_string($_SESSION['user_id'])
  );
mysql_query($sql, $link) or die(mysql_error());

ユーザー独自分類取り出し

それでは、SQL文を書き換えます。phpのコードは前回のページを参照してください。

【やりたいこと】

pay_specificationsを読み出す時にuser_id=0(マスターのID)と使用するユーザー自身のidだけを読み込む

【コード before】

$sql = sprintf('SELECT * FROM pay_specifications
 ORDER BY ID ASC',
 mysql_real_escape_string($_SESSION['user_id']

【コード after】

$sql = sprintf('SELECT * FROM pay_specifications
 WHERE user_id=0 OR user_id=%d
 ORDER BY ID ASC',
 mysql_real_escape_string($_SESSION['user_id']


2行目にWHERE句を追加しました。
これで、他のユーザーが独自に使用する分類項目は表示されないはずです。

ユーザー独自分類の非表示

最後に、ユーザー独自の分類項目を入力ではもう使わないが、一覧表示にはそのまま残したい。そんな時のためにユーザー独自の分類項目は削除ではなく使用フラグでかんりするようにしました。これもテーブルには用意してあって、usesカラムを使って

  1. 使用
  2. 不使用

と定義して、

[insert_action.php内書き込みのSQL]

$sql = sprintf('INSERT INTO pay_specifications SET name="%s", user_id=%d, created=NOW(), uses=1',
  mysql_real_escape_string($_POST["specification_name"]),
  mysql_real_escape_string($_SESSION['user_id'])
  );
mysql_query($sql, $link) or die(mysql_error());

[読み込みのSQL]

SELECT * FROM pay_specifications
 $sql = sprintf('WHERE user_id=0 OR user_id=%d AND uses=1
 ORDER BY ID ASC',
 mysql_real_escape_string($_SESSION['user_id']

[新たに、削除用のページを作り以下のSQLを発行]

UPDATE pay_specifications SET uses=2 
 $sql = sprintf('WHERE id=%d AND user_id=%d',
 mysql_real_escape_string($_POST['not_use_id']),
 mysql_real_escape_string($_SESSION['user_id'])

deleteするのではなくuses=2とすることで選択肢として表示されず、一覧表示にはそのまま表示される仕組みになっています。

2013年12月2日月曜日

[MySQL]、[php] 分類のindex管理(3)

引き続き分類を文字列からindex管理に変更する過程です。
【関連する記事】
[MySQL]、[php] 分類のindex管理(1)
[MySQL]、[php] 分類のindex管理(2)

前回は、DBの追加と変更について書きました。

今回は実際にデータを取得してhtmlに表示する部分です

データベースの素晴らしい機能であるリレーションを使います。

初めて使った時は感動でした。form部分にセレクトタグを使って表示します。

<?php 
$sql=sprintf('SELECT * FROM pay_specifications
 ORDER BY ID ASC',
 mysql_real_escape_string($_SESSION['user_id'])
);
$result = mysql_query($sql) or die(mysql_error());

$record=NULL;
while ($row = mysql_fetch_assoc($result)) {
 $record[] = $row;
}
?>

<select  name="pay_specification_id">

<?php 
for ($i=0,$count_record=count($record); $i<$count_record; $i++){
 print('<option value="'.h($record[$i]['id']).'">'.h($record[$i]['name']).'</option>');
}
?>

</select>


書いてあるコードの内容

2~11行目

支払分類テーブルからデータを取り出して$recordに格納する。
     SQL文生成ークエリ発行ーフェッチして各行を格納

18~19行目

selectタグで挟まれた部分のoptionに先ほどデータを格納した$recordを使って値を入れる。
postする値にpay_specifications.idを、htmlで表示される値にpay_specifications.nameを指定

<option value=1>食費</option>');
<option value=2>交際費</option>');
<option value=3>その他</option>');
のようにデータベースに登録されている値が出力されます。

次回

共通して表示される分類項目とユーザー独自で設定する分類項目をどうやって管理し、表示するようにしたかを紹介していきます。


2013年12月1日日曜日

[MySQL]、[php] 分類のindex管理(2)

前回の記事の続きです。
【関連する記事】
[MySQL]、[php] 分類のindex管理(1)

前回は改造前の状態とやることをザクっと把握したところまで書きました。

今回はデータベースの変更点

を主に紹介します。支払情報を例にとって見てみます

まずは支払情報のデータベースに分類IDという項目を追加します。


ALTER TABLE `pay` ADD `specification_id` INT NOT NULL AFTER `count`

次に分類テーブルを作ります。

カラムにはID、名称、ユーザーID、使用フラグ、作成日、更新日を作っておきます。

CREATE TABLE `pay_specifications` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL,
  `user_id` int(11) NOT NULL,
  `uses` int(11) NOT NULL,
  `created` datetime NOT NULL,
  `modefied` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8  AUTO_INCREMENT=1 ;

これで支払DBのspecification_idを使って支払分類DBの情報を持ってくる準備ができるようになりました。

次回

実際にデータを取得してhtml上に選択画面として表示させるところまで書きたいと思います。







2013年11月29日金曜日

[MySQL]、[php] 分類のindex管理(1)

[MySQL]、[php] 支払と収入の分類項目をデータベースで管理する


2013/11/25の更新によって追加した機能についてどのように実装していったか書き残しておこうと思います。

今回の変更点

・収入と支払の分類項目をindex管理する。(php、DB設計)
・全ユーザー共通の分類項目を用意。(DB設計)
・ユーザーが独自に設定した項目は他のユーザーには表示されない(DB設計)
・ユーザーが独自に設定した項目を設定するページ作成。(php)
・ユーザー独自の分類項目を「使わない」設定にした後も支出・支払一覧には表示させる。(DB設計)

項目としてはDB設計の変更がメインですね。新しい設定ページが必要だったので時間がかかったのは結局phpのコーディングですが。

改造の動機・問題点

これまでのページでは分類を下のように書いていました。

<select  name="type" id="type" >
<?php 
$bunrui_array = array("交通費","食費","消耗品","交際費","サークル","研究室","その他");
for ($i=0; $i<count($bunrui_array); $i++){
 print('<option value="'.$bunrui_array[$i].'">'.$bunrui_array[$i].'</option>');
}
?>
</select>

この問題点は、2つ

  1.  文字列で格納しているので拡張させづらい
  2.  全ユーザーが作成者の指定した分類項目でしか分類できない 

index管理は口座の設定をできるようにした部分で一度実装しているので、それを応用して行います。んで作る途中で気づいたことは、

  • ユーザーが独自の分類項目を削除したときどんな挙動をさせたら良いのか? 
  • データベースから削除してしまっては今までのデータを見るときに表示されないので困る。 

となるとデータベース上には保存しておく必要があるなと、フラグで管理するのが適切ということになりました。 そんなこんなで最初に書いたリストにあるように開発していくのですが、内容は次の記事に

次の記事

[MySQL]、[php] 分類のindex管理(2)



2013年11月19日火曜日

【注意点】[php] sprintf関数でSQL文を生成する時

今回の学習

sprintf関数を使ってLIKEやDATEFORMATなど%を使うSQL文を生成する時、%は%%としましょう。

参考にしたサイト
http://d.hatena.ne.jp/niconico_licoco+wu/20130117/1358398457

受け取った変数をエスケープするためにsprintf関数を用いてSQL文を作ってクエリに投げるといったやり方をしばしば行います。(私は基本的にこの方法で統一してます)

例えばこんな感じで使ってます(ユーザーの口座情報を取得するクエリ)

$sql = sprintf('SELECT a.name, u.id FROM user_accounts u 
                  JOIN accounts a ON u.account_id=a.id 
                  WHERE u.user_id=%d ORDER BY ID ASC',
    (mysql_real_escape_string($user_id))
);
$result = mysql_query($sql) or die(mysql_error());

ここからが困った時の様子

この時に、SQL文で%を使う場合(LIKEとか、DATEFORMATとか)があります。
例えば自分のアプリケーションではユーザーの今月の収入データを取得します

$sql = sprintf("SELECT SUM(income.amount) AS sum_income
   FROM income 
   WHERE user_id=%d
    AND date >= DATE_FORMAT(NOW(), '%Y-%m-01')
    AND date < ADDDATE(DATE_FORMAT(NOW(), '%Y-%m-01'), interval 2 month)
                     GROUP BY income.user_id ", 
   mysql_real_escape_string($user_id)
);
$result = mysql_query($sql, $link) or die(mysql_error());

です。この時、上のようにsprintfを使って実行すると......

"Query was empty"

クエリがありませんと?! いやいや、んなまさか?
試しにエスケープしてた部分に適当に値を入れてデータベースに直接SQL文を実行すると値が返ってくる。

ん?ん?ん? 普段ならこの直接SQLを打って間違ってる箇所洗い出して見つかるのだが、今回は分からない。

SQLをコーテーションで囲うだけにして単なる文字列として生成してみると...
$sql = "SELECT SUM(income.amount) AS sum_income
   FROM income 
   WHERE user_id=0
    AND date >= DATE_FORMAT(NOW(), '%Y-%m-01')
    AND date < ADDDATE(DATE_FORMAT(NOW(), '%Y-%m-01'), interval 2 month)
                     GROUP BY income.user_id ";
$result = mysql_query($sql, $link) or die(mysql_error());

これは動く!

sprintf関数が原因とわかりまして、初めてsprintf+MySQLで検索。
判明しました。sprintfの中で%は%%としなくてはいけないみたいです。%sとか%dで変換指定をするので、そのままじゃダメなのね。納得

ということで

sprintf()内で%を使いたいときは%%とする。

正解は
$sql = sprintf("SELECT SUM(income.amount) AS sum_income
   FROM income 
   WHERE user_id=%d
    AND date >= DATE_FORMAT(NOW(), '%%Y-%%m-01')
    AND date < ADDDATE(DATE_FORMAT(NOW(), '%%Y-%%m-01'), interval 2 month)
                     GROUP BY income.user_id ", 
   mysql_real_escape_string($user_id)
);
$result = mysql_query($sql, $link) or die(mysql_error());

2013年11月18日月曜日

syntax error, unexpected '[', expecting ']'

今日気づいたバグ
ローカル環境でエラーは出ていなかったけどリモートに挙げたらあるページでこんなエラーが

【エラーの内容】


syntax error, unexpected '[', expecting ']'

シンタックスエラーはいわゆるケアレスミスのことが多いです。よくあるのは、;を忘れるミス
http://www.php-labo.net/tutorial/public/error.html


今回は "[" 書いたのに "]" ないぞってやつです。
実際にコード見たら

何故か[]でなく[[]]になってた〜なんででしょうね。とりあえず
unset($_SESSION['income']);

としたら難なく解決。