CakePHP3 今日のデータを取得する

PHP

なんかちょいちょいつまづいちゃったので、書いておきます。

最終的には、下記のように書けば、Offers.delivery_dateが本日のデータを取得できます。

 $query = $this->Offers->find()->contain(['Deliveries'])
 			->where(['Offers.winner_id' => $user_id,
 				'Offers.delivery_date' => new \DateTime('today')])
 			->limit(50);

しかし、最初は下記のようにやってたんですよ。

 $query = $this->Offers->find()->contain(['Deliveries'])
 			->where(['Offers.winner_id' => $user_id,
 				'Offers.delivery_date > ' => DATE_SUB(NOW(), INTERVAL 1 DAY)])
 			->limit(50);

しかし、これだと、下記のようなSQLになってしまい、シングルクォートがついてしまい、本日のデータを取得できません。[sad]

 SELECT 
  Offers.* 
 FROM 
  offers Offers 
 WHERE 
  (
    Offers.winner_id = '99' 
    AND Offers.delivery_date > ' DATE_SUB(NOW(), INTERVAL 1 DAY)'
  )  
 LIMIT 
  50

また、最初の例だと、普通は

 'Offers.delivery_date' => new DateTime('today')

だと思うんですが、それだと下記のエラーが出ます。

 Class 'App\Controller\Component\DateTime' not found

http://stackoverflow.com/questions/29500225/cakephp3-class-datetime-not-found

CakePHP3 REST JSONで出力する

PHP
CakePHP3.2

JSONフォーマットで出力するのがとっても簡単!になりました。

例えば、住所の一覧を、JSONで出力するRESTなAPIを作りたいときに、CakePHPさんが、ササッと変換してくれます。

その設定も超簡単。

config/routes.php
の中に

 Router::scope('/', function ($routes) {
  
   //この行を足す
   $routes->extensions(['json']);
   …以下略

だけです。

それで、ブラウザの

 http://localhost/cake//addresses.json

に接続すると、JSONで出力してくれます。

CakePHP3.2 XAMPPで動作させる

PHP
CakePHP3.2
XAMPP for Windows 5.6.11

いつの間にか、CakePHPも3.2ですね!!

必要なPHPのバージョンも、PHP 5.5.9となり、ぐっと大人っぽくなったCakeちゃん、という感があります。

さて、今回テスト的にXAMPPで動作させたかったのですが、前もってググると、先人たちがかなり苦労されたご様子で(^^; なんか、敷居高いのかなー いやだなーと思っていたら、XAMPPのバージョンも新しかったおかげか、そこまで苦労しなかったので、とりあえず手順を書いておきます。

本家ドキュメントはこちら。

http://book.cakephp.org/3.0/en/installation.html#

上記をかいつまんで、Windowsでちゃちゃっと動かしたい人向けに書きます。
最終的には、CakePHPが配布している、サンプルアプリ、ブックマーク

①まずは、composerをダウンロードして、インストールします。
下記のサイトの中ほどにある、「Download and run Composer-Setup.exe」 とある、Composer-Setup.exeをクリックしてダウンロードです。

https://getcomposer.org/download/

普通にインストールすればOKです。
で、コマンドプロンプトを立ち上げて、composer と入力してみましょう。
COMPOSERというAA的なものが表示されれば、無事動いています!やった!!
ってか、昔Linuxサーバーにcomposer入れたときは、けっこう難しかったんですけどね~。こんなにあっさりできると、癒されますね!!(゜∀゜)

②次は、コマンドプロンプトでブックマークアプリを動かしたいディレクトリにcdで移動します。
XAMPPで動かす、というのが目標なので、XAMPPの中に作りましょう。
C:\xampp2\htdocs\ひみつ\caketest の中に作ることにします。
んで、

 composer create-project --prefer-dist cakephp/app bookmarker

とやります。

cakephp3-1.png

すると、ややっ 途中でエラーで止まっちゃいます(つД`)

 Problem 1
    - cakephp/cakephp 3.2.x-dev requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.1 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.0-RC1 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - cakephp/cakephp 3.2.0 requires ext-intl * -> the requested PHP extension intl is missing from your system.
    - Installation request for cakephp/cakephp ~3.2 -> satisfiable by cakephp/cakephp[3.2.0, 3.2.0-RC1, 3.2.1, 3.2.x-dev].
 
  To enable extensions, verify that they are enabled in those .ini files:
    - C:\xampp2\php\php.ini
  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

げげっ
嫌な感じですね。
エラーメッセージ通り、php.iniにある、

 extension=php_intl.dll

の先頭の#を外しても、動作しません。

調べたところ、下記に解決方法が。
http://stackoverflow.com/questions/26285280/cakephp-3-0-installation-intl-extension-missing-from-system

xamp\phpフォルダの中にある、icで始まるファイルを、全部コピーして、\xampp\apache\binにペーストする、そうです。
んで、Apacheをリスタートです。

ちなみに、私の環境では、コピペするときに置き換えますか?って出てきてたんで、単にエスケープを外した後に、Aparche再起動してなかったのが原因かも…。

Apacheをリスタートして、phpinfo.phpを見ると、intlの行が増えています!
パチパチ。

cakephp3-2.png

で、コマンドプロンプトで、もう一度、さっきの

 composer create-project --prefer-dist cakephp/app bookmarker

をやります。

今度は、正常に終わったようです!

下記のようなフォルダの中に、いろいろと入っているはずです!
C:\xampp2\htdocs\ひみつ\caketest\bookmarker

③ついに、CakePHPを始動させます…
コマンドプロンプトで、

 C:\xampp2\htdocs\ひみつ\caketest\bookmarker

に移動し、

 bin\cake server

とやります。

ふぉっ ついに動いた!
下記にブラウザでアクセスします。

 http://localhost:8765/

CakePHPの画面が出ますね!

cakephp3-3.png

④DBとの接続を作ってみます。
cake_bookmarksというDBを作って、下記のSQLで、テーブルを作っておきます。

 CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    email VARCHAR(255) NOT NULL,
    password VARCHAR(255) NOT NULL,
    created DATETIME,
    modified DATETIME
 );
 
 CREATE TABLE bookmarks (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL,
    title VARCHAR(50),
    description TEXT,
    url TEXT,
    created DATETIME,
    modified DATETIME,
    FOREIGN KEY user_key (user_id) REFERENCES users(id)
 );
 
 CREATE TABLE tags (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255),
    created DATETIME,
    modified DATETIME,
    UNIQUE KEY (title)
 );
 
 CREATE TABLE bookmarks_tags (
    bookmark_id INT NOT NULL,
    tag_id INT NOT NULL,
    PRIMARY KEY (bookmark_id, tag_id),
    FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
    FOREIGN KEY bookmark_key(bookmark_id) REFERENCES bookmarks(id)
 ); 

bookmarkerの中にある、下記のファイルを開いて、

 config/app.php

 return [
    // More configuration above.
    'Datasources' => [
        'default' => [
            'className' => 'Cake\Database\Connection',
 …

とあるあたりを自分のDBに合わせて変更します。

⑤次は、楽しい楽しいBakeの時間ですね!
私は、この機能が大好きです!
コマンドプロンプトで、次のを一個ずつ実行します。

bin\cake bake all users
bin\cake bake all bookmarks
bin\cake bake all tags

プログラムがじゃんじゃんできてきますね!⊂(^-^)⊃

⑥面倒ですが、またサーバーを再起動させます。

 bin\cake server

とやります。

下記に、ブラウザから接続します。

 http://localhost:8765/bookmarks/add

おーっ できてる!!

cakephp3-4.png

本当の開発はここからですね!
以上で終了です。

CakePHP3 同じテーブルに二つアソシエーションを作る

PHP

例えば、ここに2つのテーブルがあります。
UsersとReviewsです。
機能はユーザーがお互いを評価するというものですが、ユーザーは乗客、ドライバーと二つの立場があるとします。

なので、Reviewsは
「レビューと対象者(ドライバー)の紐づけ」
「レビューと書いた人(乗客)の紐づけ」
と2つの方法でUsersと紐づける必要があります。

で、普通に書いた人を紐づけるのは

  //ReviewsTable.php内
    public function initialize(array $config)
    {
        parent::initialize($config);
 
        $this->table('reviews');
        $this->displayField('id');
        $this->primaryKey('id');
 
        
        $this->belongsTo('Users', [
            'foreignKey' => 'user_id',
            'joinType' => 'INNER'
        ]);
    }

でいいんですが、2つ目のbelongsToアソシエーションをどうやって作るのか、は次のようにやります。

 $this->belongsTo('Drivers', [
        'className' => 'Users',
         'foreignKey' => 'driver_id'
        ]);
        

CakePHP3 テーブルに別名をつける

PHP
CakePHP3.2.11

データを取得してくるときに、CakePHPのデフォルトでは普通にテーブル名がオブジェクトになって返ってきますね。

それを変更したいとき、MySQLでよくあるように as で名前を変更できるか(別名をつけられるか)と思いきや、できないんですね~。

こんな時、アソシエーションの定義を利用することができます。

詳しくは、下記のページをご参照ください。
http://book.cakephp.org/3.0/ja/orm/associations.html

例えば、モデルの中で次のようにすると、

 class ArticlesTable extends Table
 {
 
    public function initialize(array $config)
    {
        $this->hasMany('Comments', [
            'className' => 'Comments',
       ]);
 
        $this->hasMany('UnapprovedComments', [
            'className' => 'Comments',
        ]);
    }
 }

オブジェクトの名前を’Comments’でも、’UnapprovedComments’でも使えます。(^_^)

この使い方は便利で、
CakePHP3 同じテーブルに二つアソシエーションを作る
で紹介しているようにも使えます。