Table of Contents
Cakephp 3 – Instructions for creating Articles Controller
In this article, we will create basic functions: add, edit, delete, view articles in the Articles table created in Lesson 1.
The controller files in CakePHP 3 are created in src/Controller, a basic controller will look like below:
<?php namespace AppController; class ArticlesController extends AppController { }
Now we create action for above controller, first action index equivalent to url: http://localhost:8888/cakephp_3_7_2/articles/index(http://localhost:8888/cakephp_3_7_2/articles). And in this action will be queries with Model and return data to Template in View.
<?php namespace AppController; class ArticlesController extends AppController { public function index() { $this->loadComponent('Paginator'); $articles = $this->Paginator->paginate($this->Articles->find()); $this->set(compact('articles')); } }
The default action in a controller will be index(), we can edit the above url through Routing, which will be learned in the following articles. In the above action we will get all the posts via find() and use the Paginator component to paginate the data. Then use the set() method to pass the data out of the view with the $articles variable.
Create Articles list Template.
The place to save files outside the view is src/Template inside a folder corresponding to the Controller, here ArticlesController, this folder will be called Articles. In turn, create the Articles folder and the index.ctp file with the following content:
<!-- File: src/Template/Articles/index.ctp --> <h1>Articles</h1> <table> <tr> <th>Title</th> <th>Created</th> </tr> <?php foreach ($articles as $article): ?> <tr> <td> <?= $this->Html->link($article->title, ['action' => 'view', $article->slug]) ?> </td> <td> <?= $article->created->format('Y-m-d H:i:s') ?> </td> </tr> <?php endforeach; ?> </table>
In the above paragraph using HTMLHelper to create specific links this is the tag with link(), the first parameter is the text to display and the second parameter is the redirect URL. With Helpers we will also learn more carefully in another article.
Now run the url: http://localhost:8888/cakephp_3_7_2/articles we will see a list of articles in the articles table, as shown below:
Create View action to view details of an article.
When we click on the article name on the list page we will switch to this action view with the url: http://localhost:8888/cakephp_3_7_2/articles/view/first-post, ‘first-post’ is the slug
// Add to existing src/Controller/ArticlesController.php file public function view($slug = null) { $article = $this->Articles->findBySlug($slug)->firstOrFail(); $this->set(compact('article')); }
Using the slug of the post title, we will rely on it to query the data with findBySlug(), get the first element, or get a NotFoundException exception with firstOrFail().
The set() method to get the data out of the view. You can replace the slug with the post id to get the data. And if using slug, when inserting, updating must check and convert it to slug form (especially for accented Vietnamese).
Create Template to view article details
We will create the view.ctp file in src/Template/Articles/view.ctp:
<!-- File: src/Template/Articles/view.ctp --> <h1><?= h($article->title) ?></h1> <p><?= h($article->body) ?></p> <p><small>Created: <?= $article->created->format('Y-m-d H:i:s') ?></small></p> <p><?= $this->Html->link('Edit', ['action' => 'edit', $article->slug]) ?></p>
Visit the list again and click on the articles to see the details.
Create action to add posts
We will create more articles with add() action in ArticlesController.php, here its content is as follows:
<?php // src/Controller/ArticlesController.php namespace AppController; class ArticlesController extends AppController { public function initialize() { parent::initialize(); $this->loadComponent('Paginator'); $this->loadComponent('Flash'); // Include the FlashComponent } public function index() { $articles = $this->Paginator->paginate($this->Articles->find()); $this->set(compact('articles')); } public function view($slug = null) { $article = $this->Articles->findBySlug($slug)->firstOrFail(); $this->set(compact('article')); } public function add() { $article = $this->Articles->newEntity(); if ($this->request->is('post')) { $article = $this->Articles->patchEntity($article, $this->request->getData()); $article->user_id = 1; 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); }
In the above paragraph, using Component Flash to show the message outside the view, the add() action works as follows:
If POST method is used then proceed to save the data through the Articles model, if not, return the form with more data, we can display an error in this case.
$this->request->getData(); used to get data posted via
To save the data, pass the data through Article Entity( $this->Articles->patchEntity()) . If there is a field in the data table that is not posted, we can default to the same value as the code above ( $article->user_id = 1; ) the current user_id is not available, so the default is 1.
Proceed to save the data $this->Articles->save($articles); If successful, use $this->Flash->success() to display the message. Layout displays the message as Flash->render() ?> in the file src/Template/Layout/default.ctp.
Finally use $this->redirect to move back to the required action.
Create Template to add articles
<!-- File: src/Template/Articles/add.ctp --> <h1>Add Article</h1> <p><?= $this->Html->link('Articles', ['action' => 'index']) ?></p> <?php echo $this->Form->create($article); // Hard code the user for now. echo $this->Form->control('user_id', ['type' => 'hidden', 'value' => 1]); echo $this->Form->control('title'); echo $this->Form->control('body', ['rows' => '3']); echo $this->Form->button(__('Save Article')); echo $this->Form->end(); ?>
The above method is also the FormHelper supported by CakePHP:
$this->Form->create(); tạo form
$this->Form->control(); tạo các input
$this->Form->button(); tạo các button trong form
$this->Form->end(); kết thúc form
Return src/Template/Articles/index.ctp, create Add button to get access to add article functionality, by adding
Html->link(‘Add Article’, [‘action’ => ‘add’]) ?>
Add Slug in model Articles
If the data is currently added, it will fail, because the slug value in the data to be added does not exist and the Articles table has a NOT NULL slug field. The slug value is taken based on title after processing, here the processing is only done at a simple level, it will have errors with accented Vietnamese.
// in src/Model/Table/ArticlesTable.php namespace AppModelTable; use CakeORMTable; // the Text class use CakeUtilityText; // Add the following method. public function beforeSave($event, $entity, $options) { if ($entity->isNew() && !$entity->slug) { $sluggedTitle = Text::slug($entity->title); // trim slug to maximum length defined in schema $entity->slug = substr($sluggedTitle, 0, 191); } }
Of course, with the above code, there is still no duplicate check of the data.
Add action Edit Post
Add the following in ArticlesController.php
public function edit($slug) { $article = $this->Articles->findBySlug($slug)->firstOrFail(); if ($this->request->is(['post', 'put'])) { $this->Articles->patchEntity($article, $this->request->getData()); if ($this->Articles->save($article)) { $this->Flash->success(__('Your article has been updated.')); return $this->redirect(['action' => 'index']); } $this->Flash->error(__('Unable to update your article.')); } $this->set('article', $article); }
In the above code, it is quite similar to the Add action, except that there is a $slug check to get the data and put it out in the view, along with it is to check if there exist 2 POST or PUT methods, then update the data.
Create Template Edit Posts
We will proceed to create the edit.ctp file in src/Template/Articles/edit.ctp, which has the same content as add.ctp
<h1>Edit Article</h1> <p><?= $this->Html->link('Articles', ['action' => 'index']) ?></p> <?php echo $this->Form->create($article); echo $this->Form->control('user_id', ['type' => 'hidden']); echo $this->Form->control('title'); echo $this->Form->control('body', ['rows' => '3']); echo $this->Form->button(__('Save Article')); echo $this->Form->end(); ?>
What to do is add a link so that from the list you can access to edit each post. We modify the list file (index.ctp)
<!-- File: src/Template/Articles/index.ctp --> <h1>Articles</h1> <p><?= $this->Html->link('Add Article', ['action' => 'add']) ?></p> <table> <tr> <th>Title</th> <th>Created</th> <th>Action</th> </tr> <!-- Here is where we iterate through our $articles query object, printing out article info --> <?php foreach ($articles as $article): ?> <tr> <td> <?= $this->Html->link($article->title, ['action' => 'view', $article->slug]) ?> </td> <td> <?= $article->created->format('Y-m-d H:i:s') ?> </td> <td> <?= $this->Html->link('Edit', ['action' => 'edit', $article->slug]) ?> </td> </tr> <?php endforeach; ?> </table>
Simple Validation Articles
At the moment if adding or editing there will be no check for added inputs. And to do this validation is what is used:
Add the following simple validation to src/Model/Table/ArticlesTable.php
public function validationDefault(Validator $validator) { $validator ->notEmpty('title', 'Please fill this field') ->minLength('title', 10) ->maxLength('title', 255) ->requirePresence('body') ->notEmpty('body') ->add('body', 'length', [ 'rule' => ['minLength', 10], 'message' => 'Articles must have a substantial body.' ] ); return $validator; }
validationDefault() is the method that will be called when the controller calls save(), about how to use Validation we will have a separate post. You can test by entering title or body under 10 characters, the corresponding error message will appear as default in the above code.
Create action Delete Post
Now is the action to delete a post
public function delete($slug) { $this->request->allowMethod(['post', 'delete']); $article = $this->Articles->findBySlug($slug)->firstOrFail(); if ($this->Articles->delete($article)) { $this->Flash->success(__('The {0} article has been deleted.', $article->title)); return $this->redirect(['action' => 'index']); } }
Similar to the above actions is to check the data in $slug, delete with delete() in the model and show the message of successful deletion in $this->Flash->success, then $this->redirect to list. Here using $this->request->allowMethod([‘post’, ‘delete’]); this is how CakePHP restricts the methods passed to the action in the controller, with this paragraph it only allows deletion when there is a post or delete method, other methods will have an error.
Finally, in order to delete it, it is also necessary to add to the list a link to perform this task. The content of the index.ctp file is changed as follows:
<!-- File: src/Template/Articles/index.ctp --> <h1>Articles</h1> <p><?= $this->Html->link('Add Article', ['action' => 'add']) ?></p> <table> <tr> <th>Title</th> <th>Created</th> <th>Action</th> </tr> <?php foreach ($articles as $article): ?> <tr> <td> <?= $this->Html->link($article->title, ['action' => 'view', $article->slug]) ?> </td> <td> <?= $article->created->format('Y-m-d H:i:s') ?> </td> <td> <?= $this->Html->link('Edit', ['action' => 'edit', $article->slug]) ?> <?= $this->Form->postLink( 'Delete', ['action' => 'delete', $article->slug], ['confirm' => 'Are you sure?']) ?> </td> </tr> <?php endforeach; ?> </table>
We use $this->Form->postLink() which is the method of FormHelper, with the above method will create a link using Javascript to POST data via delete() action in the controller.
Let’s end here, in this article we get acquainted with how to create a controller, model, view, how to post data, simple validation. All of these are just getting used to, I will go into each one more deeply in the next posts.
[thongbao]
- If you have any questions, please leave a comment below and I will reply as soon as possible.
- Thank you for reading.
[/thongbao]