Title TBD

中途未経験からエンジニアを目指してエンジニアになりました。学んだことなど中心に書いていきます。最近はもっぱらnoteで書いてます。https://note.com/toshi65811

CakePHP 超入門 Chapter 3のちょっとしたまとめ

 

世間はGWで楽しげな雰囲気に満ち満ちていますが、派遣の私にはGWなんて関係ありません!つらいね!

さて、現在「CakePHP超入門」を使ってCakePHPの学習をしています。

CakePHP 超入門

CakePHP 超入門

 

 前回、Chapter 1,2の簡単なまとめを書いたので、今回はその続きとしてChapter 3のまとめを書きました。まとめというかほぼテキストそのまま書き写したと言ったほうが正しいかもというレベル。

まとめてみた結果として、今テキスト3周目ですが大切な部分が全然理解できてなかったなという感想です。この記事がお役に立てば嬉しいです。

モデルの役割とは

コントローラーからモデルにデータを取るよう要求すると、モデルからデータベースへSQLコマンドが送られる。

モデルは、PHPのプログラムとDBの間で命令やデータを翻訳し送受する役割を果たしているので、モデルは「SQLPHPの同時通訳」といえる。


phpMyadminを使おう

テキストではphpMyadminを使うとなっていますが、MAMPを使わずもしvagrant環境でやるなら、Sequel proという無料のアプリを使ってデータベース、テーブルの作成をするといいかもです。ダウンロードはこちらから。

DBの接続設定はこれでできました。

f:id:toshi3arai3:20190427120312p:plain

SSH Passwordはvagrantのversionによって変わるみたいですが、僕の場合はvagrant 2.2.3で、passwordはvagrantでした。

Sequel proの使い方は特に難しくないです。テーブル作ってデータ入れるだけなので、phpMyadmin使ったことある人なら直感でなんとなく使えると思います。

CakePHPのデータベース設定について

作成したデータベースとテーブルをCakePHPのプログラム内から使えるようにするために、configフォルダ内にあるapp.phpというファイルの設定を変更する必要があります。この辺は事前に一度ドットインストールをやっておくと何をするのかのイメージがつかみやすいと思います。

テキストでは画像のように変更するよう指示がありますが、もしvagrant環境でやるなら、usernameはroot、passwordは空欄に設定すればOKです。

f:id:toshi3arai3:20190427120420p:plain
なぜそのようにするかと言うと、ここではMySQLに接続する必要があります。先程Sequel Proで利用したMySQLのUsernameとPasswordを入れる必要があります。

私の場合、rootにはパスワードを設定していませんでした。ですので、ここではPasswordは空欄で問題ないです。(間違えていたらすみません。また、バージョンによってはrootでパスワードが初期設定される事もあるようです。)

コードはこのようになります。

f:id:toshi3arai3:20190427120451p:plain

ドットインストールやれば分かると思いますが、timezoneは+09:00にするとChapter6の時にいい感じになると思います。(多分)

app.phpの設定変更前と変更後でこのように変わります。無事接続できていますね。(CakePHPのversionによって表示が変わると思います。)

f:id:toshi3arai3:20190427120834p:plain

これが

f:id:toshi3arai3:20190427120852p:plain

こう!!



エンティティが俺を悩ませる

テキストによると、モデルという部分は実は存在しなくて、モデルとはテーブルとエンティティという2つのクラスを組み合わせとして用意される。とのことです。なんのこっちゃ。

f:id:toshi3arai3:20190427121129p:plain

テーブルは理解できるけど、エンティティがよく分からず(未だによく分かってない)苦しみました。今は、テーブルのデータを変更とかするのに必要なもの。という雑な認識でいます。

さて、テーブルとエンティティのクラスを作りましょう。この辺は特に問題ないと思う。唯一気をつけるのは、エンティティのクラス名は、使用するテーブル名の単数形にするということ。

今回People(人々)というテーブル名なので、単数形のPerson(人)という名前になることを留意しよう。

イメージ的に、テーブルはレコードの集まりなので複数形。エンティティは各レコード(単数)を扱うので単数形の名前になる。と考えるとわかりやすいかな。

次にこれらテーブルとエンティティを使ってデータベースにアクセスするコントローラーを用意する。

コントローラーを作ったら、ビューテンプレートの用意が必要。その際に、Templateフォルダ内にPeopleというフォルダを作成して、その中にindex.ctpというファイルを作る。この一連の流れ忘れがちな私です。

ここまでやったらブラウザでpeopleテーブルに保存したレコードが一覧で出てくるんだけど、こっから色々理解しないといけないことがある。

f:id:toshi3arai3:20190223221220j:plain

 

PeopleControllerの中でこんなコードがある。

$data = $this->People->find('all');

これはPeopleテーブルから全エンティティ(レコード)を取り出す処理を行っている。

モデルと連携したコントローラーでは、テーブルクラスと同じ名前のプロパティ(この場合Peopleのこと)が自動的に用意されて、そこにテーブルクラスのインスタンスが組み込まれるようになっているらしい。

このPeopleControllerは「Peopleモデルを扱うコントローラー」です。

Peopleモデルは、PeopleTableというテーブルとPersonエンティティとして作成されている。(モデルはテーブルとエンティティという2つのクラスを組み合わせとして用意されるってあったね。)

PeopleControllerクラスには、このPeopleTableクラスのインスタンスが「People」という名前のプロパティとして組み込まれるんだって。

そういうCakePHPのルールなんだろうね。だから、このあたりの名前の付け方のルールは覚えておかなきゃだね。

テキストの画像を見ると一番理解しやすいと思う。

f:id:toshi3arai3:20190427121257j:plain

findメソッドについて

ここではfindというメソッドを使って、データを呼び出している。

$変数 = $this->テーブル->find('all');

引数にallを指定しているから、そのテーブルの全エンティティ(今回だとPeopleテーブルだね)をまとめて返してくれている。

この後に、これをベースにして色々検索方法を試していくから、これはしっかり覚える必要がある。ただ、これまでMySQLとかやってきた人ならそんな難しくないと思う。

 

返り値は「Query」

findメソッドを使って返されるのは「Query」というクラスのインスタンスで、データベースから情報を受け取るのに使うもの。今は、「findを呼び出すとオブジェクト(query)が取り出せて、そこから検索したエンティティとかも取り出せる。」という基本的な流れを抑えておく。

 

toArrayメソッド

index.ctpにこんなコードを書きました。

<?php foreach($data->toArray() as $obj): ?>

toArrayメソッドは$dataに保管したオブジェクト(Query)から、レコードのデータだけを配列にまとめて取り出すもの。

配列として取り出せば、後はforeachで順に値を取り出して処理することが出来る。
toArrayは今後よく出てくるので覚えておいたほうが良いです。

ここで何をやってるかはこの画像を見ると流れが分かりやすい。

f:id:toshi3arai3:20190427121425j:plain

 

テーブルクラスの基本設定

ここでは、PeopleTable.phpのクラス部分をいくつか修正するんだけど、1点だけ分からないところがあった。

public function initialize(array $config)

このコードの引数に(array $config)とあるが、なんで引数が2個?2個あるならカンマで区切るのでは?と思っていたけど、これは$configというはarray(配列)じゃなきゃだめ。と変数の型指定をしている。

PHP 型宣言」とかでググると出てくるが、こういった機能があることを知らずに結構悩んだ。一応Qiita貼っておく。

qiita.com

 

エンティティの$_accessible設定

$_accessibleという変数は、「値の一括代入」を行うのに必要なもの。

例えば、フォームなどから値を送信してエンティティを作成するときに、送られたフォームのデータをまとめてエンティティに設定することが出来るので便利。

英語を意味を理解すると、この変数の働きも理解しやすい。

accessibleはaccess + ableが合わさったもの。

access(アクセス) + able(〜できる)なので、アクセスできるという意味になる。
ここのableは中学英語のbe able to(なになに出来る)のableと同じです。

$dataの内容を調べる。というところで、print_rという関数が使われています。
これはPHPマニュアルを見ると

print_r — Prints human-readable information about a variable

と書いているので、変数について人間が読めるような形でプリントをしてくれる関数ですね。

PHP: print_r - Manual

getでエンティティを取り出す

$data = $this->People->get($id);

「get」メソッドは、引数に指定したIDのエンティティを取り出すメソッド。引数にはプライマリーキーの値を指定する。

返される値は、エンティティのインスタンスで、配列などになっていない。
getによるエンティティの取り出しはエンティティ取得の基本中の基本なので、しっかり覚える。

エンティティの作成

エンティティは新たに作成して保存を行うことで、それがデータベーステーブルにレコードとして保存されるようになっている。

新しいレコードを追加するときは、新しいエンティティのインスタンスを用意し、保存のメソッドを呼び出すだけ。

 

ビューテンプレートの作成

fromタグ生成部分で、最初の引数に$entityという変数が設定されている。これは、コントローラー側で用意するエンティティのオブジェクト。
これを設定しておくことにより、エンティティの値が自動的に入力フィールドに割り振られていく。
「エンティティの作成用フォームをフォームヘルパーで作る場合は、必ずエンティティのインスタンスを第1引数に設定する」ということは覚えておく。

フォームの値を取り出す

$data = $this->request->data['People'];

add.ctpのフォームでは、nameフィールドはtext('People.name')となっている。

Peopleがフォームの名前、nameがフィールドの名前と考えると分かりやすい。
こうすると、data['People']['name']に値が保管される。

まず、data['People']という値が用意されて、この中にフォームの値が連想配列としてまとめて保管される。なので、data['People']を取り出せば、Peopleフォームから送られたデータがまるごと取り出せる。

新しいエンティティの作成

$entity = $this->People->newEntity( );

エンティティのインスタンスは、対応するテーブルクラスの「newEntity」メソッドを使う。

テーブル->newEntity(データ);

とすることで、テーブルに保管されるエンティティのインスタンスが作成できる。

引数には、そのエンティティに保管するデータを連想配列にまとめたものを用意する。
request->data['People']で取り出したものをそのまま引数に渡せばOK.

ここでは引数に$dataを指定していて、$dataには$this->People->find('all')でもってきたDBの全データが配列で入っている。

リダイレクトについて

return $this->redirect(['action'=>アクション]);
これでリダイレクト出来る。

エンティティの更新

ここ重要なのにあんまり分かってなかったです。説明は画像が分かりやすい。

f:id:toshi3arai3:20190427121916j:plain

URLを生成するためのメソッド

$変数 = $this->Url->build(['controller'=>'〇〇', 'action'=>'xx']);

これで指定のコントローラーの指定アクションへのURLが作成される。

 

フォームの値でエンティティを更新する

送られてきたフォームの値を使ってエンティティの内容を更新する際はテーブルクラスの「patchEntity」というメソッドを使う。

$this->People->patchEntity($entity, $data);

第1引数のエンティティの内容を、第2引数の値で更新できる。

エンティティの更新は「patchEntityでエンティティを更新、saveで保存」という流れで行う。

おわりに

語尾がかしこまった感じのところはほぼテキストそのままコピーしたんだなって察してください!ちょっとまとめるつもりが、分かっていない所が多すぎて膨大な量になってしまいました。引き続きがんばりましょー。