Quantcast
Channel: 初心者タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 21089

cakephp チュートリアル Blogでつまづいた話

$
0
0

はじめに

会社に入社して会社行ものために、php(cakephp)を学ぶ研修で、cakePHPのチュートリアル(主にBlog)をしたときに、つまずいた点を記事として残そうかと思います。

*ブログチュートリアル
https://book.cakephp.org/3/ja/tutorials-and-examples/blog/blog.html

つまずいた所

*admin権限ではないユーザーがログインした場合のアクション権限

=>ユーザーが投稿した記事のみ編集・削除できる機能実装(ほんとに最後...)

ここにすごくcakephp初心者の自分は苦労しました...

認可(誰が何にアクセスするのを許可するか)

ログインしてるのか・してないかでアクセスを分ける

まずユーザーの種類にadmin(管理者)とauther(著者)の2種類あります。

そこの使い分けはまず、全体に認証をかけたいようなときはAppControllerappcontrollerでAuthコンポーネントの設定します。

*ちなみに、コントローラの拡張をコンポーネント!モデルはビヘイバー!Viewはヘルパーというものがあります。

publicfunctioninitialize(){$this->loadComponent('Flash');$this->loadComponent('Auth',[//Authコンポーネントの読み込み'authorize'=>['Controller'],'loginRedirect'=>[//ログイン後のリダイレクト先'controller'=>'Articles','action'=>'index'],'logoutRedirect'=>[//ログアウト後のリダイレクト先'controller'=>'Pages','action'=>'display','home']]);}

続きにAppContorollerに

//isAuthorizedはAuthコンポーネントで定義されている!publicfunctionisAuthorized($user){// roleというカラムで、adminを定義して管理者はすべての操作に権限を与えるif(isset($user['role'])&&$user['role']==='admin'){returntrue;}//その他のロールの場合はデフォルトで拒否とする(許可したい場合は各コントローラで個別に設定)returnfalse;}// 共通メソッド beforeFilterでコントローラーのメソッドよりも先に実行する(ロールバック)publicfunctionbeforeFilter(\Cake\Event\Event$event){//beforeFilterでisAuthorizedメソッドよりも先に実行してくれるので//認証なしでアクセスできるアクションの指定$this->Auth->allow(['index','view','display']);$this->set('auth',$this->Auth->user());}

ユーザーの権限

AppConroller 内でやるかわりに、 各個別のコントローラーにさらなるルールを追加します。
追加しようとしているルールというのは、 ArticlesController によって、著者は記事を作成できるが、 自分のものではない記事を編集・削除できないようにする、というもの(本題)。

まずはArticlesControllerの編集

//Authコンポーネントで定義されているメソッド(認証済みであるという意味)publicfunctionisAuthorized($user){//addアクションのリクエストであればtrueを返す = つまり登録ユーザー全員が記事を追加できますif($this->request->getParam('action')==='add'){// LoginUserであれば実行可能なので、trueを返すreturntrue;}//(in_array — 配列に値があるかチェックする)  編集や削除のリクエストである場合if(in_array($this->request->getParam('action'),['edit','delete'])){//pass.0はURL内で渡されたパラメータを表します、つまりURLのアクションの下のパスセグメント( / で区切ったキーワード)を数字をインデックスとする配列で呼べるようにする。//'pass.0' とインデックスを指定すると配列の先頭要素、つまりパスセグメントの先頭要素を取り出せる。$articleId=(int)$this->request->getParam('pass.0');// actionがedit,deleteの場合、request($articleId)の値とuserテーブルのuser_idの比較を行う。if($this->Articles->isOwnedBy($articleId,$user['id'])){//一致すればtrueを返して、編集削除を許可するreturntrue;}}//  比較がfalseの場合、AppControllerのisAuthorizedへ、//  権限が'admin'の場合はtrue、それ以外はfalse。returnparent::isAuthorized($user);}}

ちなみにisOwnedByはarticleテーブルで定義する!

publicfunctionisOwnedBy($articleId,$userId){return$this->exists(['id'=>$articleId,'user_id'=>$userId]);}

モデルのアソシエーション

関係するモデルはArticlesテーブルとUsersテーブルが関係あります。

ここが大事!

つまり、投稿した記事のidとログインしたuser_idとが紐付かなければなりません!

アソシエーションを組みます!

ArticlesTable

publicfunctioninitialize(array$config){parent::initialize($config);$this->table('articles');$this->displayField('title');$this->primaryKey('id');$this->addBehavior('Timestamp');// アソシエーション//*foreignKeyはリレーションする「先」のテーブルの、紐づけるカラム(外部キー)$this->belongsTo('Users',['foreignKey'=>'user_id']);$this->belongsTo('Categories',['foreignKey'=>'category_id']);}

*ここで迷ったのは、Userstable.phpもアソシエーション 定義しないでいいの???

今回は投稿した記事(=ArticlesControllerのaddアクションのみ)なのでいりません!!

これで、ArticlesControllerでusersテーブルでのデータを持ってくることができます!

最後にコントローラーのメソッド!!

投稿した記事(addアクション)にuser_idを紐付ける

// 記事追加機能publicfunctionadd(){//newEntityとは 新規追加、保存処理をするときに使用新しく保存されるときにデータの検証が行われる$article=$this->Articles->newEntity();//コントローラの処理でHTTPリクエストメソッドが「Post」でない場合はエラーに飛ばす、if($this->request->is('post')){//ここでuserテーブルのuser_idと紐付けてくれる(ここ大事です!!)$article->user_id=$this->Auth->user('id');// patchEntity メソッドは、データがエンティティーにコピーされる前に 検証を行います$article=$this->Articles->patchEntity($article,$this->request->getData());if($this->Articles->save($article)){$this->Flash->success(__('Your article has been saved.'));return$this->redirect(['action'=>'index']);}$this->Flash->error(__('Unable to add your article.'));}$this->set('article',$article);$categories=$this->Articles->Categories->find('treeList');$this->set(compact('categories'));}

これで無事に投稿した記事とuser_idが紐付きました!
先ほどArticlesControllerで定義したisAuthorizedメソッドが効いてアクセス制限を分けることができました!!

最後に

チュートリアルはここまで優しく書いてもないですし、理解するにのに苦労しました!
最後はわざと書いてません(多分..)
デバックしたりすることで、今回のエラーをがアソシエーション されてない事に気付き対処することができました!

参考
https://sites.google.com/site/kobashijiangyiyong/detabesu/e-detabesu-she-ji-yan-xi-3-4

https://qiita.com/ota-yuki/items/31b25ef1e73fd1466d42

http://bashalog.c-brains.jp/15/06/15-101855.php


Viewing all articles
Browse latest Browse all 21089

Trending Articles