6. Implementing CRUD Functionality in the PostController

To implement CRUD functionality on posts, I will make changes to the PostController.php file. These changes involve adding the following methods to the PostController:

  • index() - Returns a view showing all of the posts.
  • show() - Returns a view showing a single post, based on an id.
  • create() - Returns a view with a form to create a new post.
  • store() - Persists the values from the create form's POST request to the database.
  • edit() - Returns a view with a form to edit an existing post, based on an id.
  • update() - Persists the values from the edit form's PUT request to the database, based on an id.
  • destroy() - Deletes a post from the database, based on an id.
I have also added a reusable validation function at the bottom of the post controller file, which can be seen at the bottom of this blog post - this function is used as part of the store and update functions.

Index function: In the index function, I will retrieve all of the posts using get(), which will be ordered by the most recent posts first using latest(). The posts index view (resources/views/posts/index.blade.php) is then returned, with an array of posts sent as an argument.


Show function: The show function takes a post id as a parameter (automatically retrieved by Laravel) and the posts show view (resources/views/posts/show.blade.php) is then returned, with a single post being sent as an argument.


Create function: The create function returns the posts create view (resources/views/posts/show.blade.php). This view contains a create form, where users will be able to create a new post.


Store function: The store function starts by validating the fields from the post create form request. This reusable validation function is used when posts are created or updated, it is shown at the bottom of this article.

Then, a new post instance is created using the heading, subheading and body fields from the request.  As it stands, the user_id foreign key will be set to the id of the current logged in user, but because I've not yet added authentication to any routes, guest users will still be able to create posts. When testing the store function with a guest user, I had to change the user_id foreign key to a hard-coded value of 1 (or any valid user id). The post is then saved to the database with the save() method.

Next, I want to check if a user is attempting to upload an image - if the request does contain an image, it is stored in the storage/app/public/img/posts directory using the storeAs() method, where the image is converted to a .jpg format and is saved as 'post_img_[post id].jpg'. This means that every post can have a single uniquely named image associated with it, however, it is not required. It was necessary for me to create a symbolic link between the storage/app/public and public/storage directories:
php artisan storage:link
When an image is stored, it is then also added to the public/storage directly thanks to the link created between the two directories. Image mime types and file sizes are checked within the reusable validation function.

Finally, the home view is returned, using the named route 'home' (resources/views/home.blade.php). The home view was added by the application scaffolding and requires authentication to be accessed. For this reason, I also tested the return using the welcome view (resources/views/welcome.blade.php), which is accessible by all users.


Edit function: The edit function takes a post id as a parameter (automatically retrieved by Laravel) and the posts edit view (resources/views/posts/edit.blade.php) is then returned, with a single post being sent as an argument.


Update function: The update function takes a post id as a parameter (automatically retrieved by Laravel). The update method starts by validating the fields from the post edit form request. Again, this reusable validation function is used when posts are created or updated, it is shown at the bottom of this article. A valid request is then persisted to the database using an update() method.

Again, like the store function, I want to check if a user is attempting to upload an image. If the request does contain an image, the image will be stored using the same naming convention mentioned above (i.e. 'post_img_[post id].jpg'). An old image will be overwritten by any new image with the same name, meaning that there will never be errors caused by duplicate file name. As before, the image mime types and file sizes are checked within the reusable validation function.

The home view is returned, using the named route 'home' (resources/views/home.blade.php). The home view was added by the application scaffolding and requires authentication to be accessed. For this reason, I also tested the return using the welcome view (resources/views/welcome.blade.php), which is accessible by all users.


Destroy function: The destroy function takes a post id as a parameter (automatically retrieved by Laravel). A post is deleted using the destroy() method, where it deletes a post from the database based on the post's id.

The home view is returned, using the named route 'home' (resources/views/home.blade.php). The home view was added by the application scaffolding and requires authentication to be accessed. For this reason, I also tested the return using the welcome view (resources/views/welcome.blade.php), which is accessible by all users.


*EDIT* I have since updated the destroy() function to remove an image from the public storage directory. This was added after gaining some application feedback, where I realised that orphan files were left behind when a post was being deleted. Below is a screen capture of the updated destroy() function - when a post is to be deleted, I first check if an associated image file exists. If a file does exist, then the image is deleted using the unlink() method. Afterwards, the post is removed from the database. (Note: this screen capture was taken after having implemented authorisation.)




Validation function: The function below is a reusable validation function that is utilised by both the store and update functions. The purpose of this function is to validate input gathered from the create and edit forms, once they are submitted. It declares that the heading, subheading and body values are all required (can't be empty). Additionally, the mime type and file size (max. 2MB) of images are checked.

Comments