What you'll learn
In this part of the series, you'll learn the following:
- What is validation
- How to implement validation in Laravel
- Implement table relationships
What is Validation?
Validation, in the scope of this project, is the process of making sure the input going into the API is the required and acceptable one, and the output the API is sending back to the user is the correct and useful one.
Validation in Laravel
Laravel makes validation easy to work with by providing developers with a validate
method that is available on all incoming HTTP
requests. That said, to show you how validation works in Laravel, I'll set up validation for the store
functions of both the PostController
and AuthorController
.
First, I'll check what I get when I send nothing with the POST
request in Postman:
- The purple box is the type of request I made, which is a
POST
request. - The yellow box is the URL I sent the request to;
localhost:8000/api/posts
. - The red box is the data I sent with the request, which is nothing.
- The green box is the result of the request, which is the default validation error, telling me
Field 'title' doesn't have a default value
, which means I need to provide thetitle
of the post I want to create, not because it's required though, but because it is listed in the$fillable
array inside thePost
model and because I didn't add a default value to it inside the migrations file. But that error doesn't look good, and most times, you only want a simple error message like"title is required"
or something similar that you can send back to the client, so they know what the issue is and how to move forward.
So to send a better error message, go to your PostController
's store
function and add the following code:
$request->validate([
'title' => 'required',
'author_id' => 'required',
'body' => 'required'
]);
The above code makes use of the validate
method on the $request
object, and adds the required fields as an array, in my case the title
, author_id
, and body
fields are required to successfully create a post.
So your store
function now looks like so:
public function store(Request $request)
{
$request->validate([
'title' => 'required',
'author_id' => 'required',
'body' => 'required'
]);
return Post::create($request->all());
}
Now send the same request I sent at the beginning of the section to see the new and readable error message: The description of the above image is the same as the previous one, except for the green box, which in this case, shows nicely formatted error messages.
Note: You need to set the
Accept
header in your HTTP client toapplication/json
for all your requests, especially when you set validation messages like you did above or thevalidate
method might not work.
Lets do the same for the AuthorController
's store
function, like so:
public function store(Request $request)
{
$request->validate([
'author_email' => 'required|unique',
'author_name' => 'required',
]);
return Author::create($request->all());
}
Notice the
required|unique
?, this allows you to avoid saving the same Author to the database multiple times by making sure all the requests to create a new Author contain an email that has not been previously registered.
This is all for validation in our application, you can read more on validation in Laravel here. Next, we'll move on to table relationships continuation.
Table relationships (Contd.)
In the first part of the series, you learned that to use the relationship feature in Laravel, you need to have two or more tables in the database.
In this section, I'm going to show you how to connect the Author
table to the Post
in a way that a single Author can have multiple posts. To do that, go to your Author
model file, and add the following code inside the class, like so:
public function posts()
{
return $this->hasMany(Post::class);
}
The above code makes use of the hasMany
method to create an eloquent relationship that uses the author_id
as a foreign key to connect the tables.
Note: You need to have the
'author_id'
in your post table for the above to work, else you'll need to put the name of the field you use to uniquely identify each author as a foreign key next to the class so:$this->hasMany(Post::class, 'foreign_key')
. The above code works without the foreign key because Laravel assumes that you use the parent model name with_id
suffix as your foreign key, which is correct in my case:author_id
.
Next, you need to create a controller function that returns the list of posts for a particular author, you do that inside the AuthorController
like so:
public function get_posts($id)
{
$posts = Author::find($id)->posts;
return $posts;
}
The above code makes use of the find
method with the id
as a parameter on the Author model, and then it returns all the posts of that author.
After that, connect the above get_posts
function to a route by adding the following code to your api.php
file like so:
Route::get('/author/posts/{id}', [AuthorController::class, 'get_posts']);
The above route connects the get_posts
function to any GET request that goes to the http://localhost:8000/api/authors/posts/2 route
, which will then return all the posts for the author with the id
of 2 like so:
- The purple box is the type of request I made, which is a
GET
request. - The yellow box is the URL I sent the request to;
http://localhost:8000/api/author/posts/2
. - The green box is the result, which is all the posts that belong to the author.
Connecting a post to a single author
We've looked at how to get posts from a single author. Now let's look at how to get the author of a post. To do this, add the following code to your Post
model:
public function Author()
{
return $this->belongsTo(Author::class);
}
The above code connects the Post
table to the Author
table inversely. After that, add the following code to the PostController
like so:
public function get_author($id)
{
$author = Post::find($id)->author;
return $author;
}
The above code makes use of the find
method with the id
as a parameter on the Post model, and then it returns the author of that post.
Next, connect the above get_author
function to a route by adding the following code to your api.php
file like so:
Route::get('/posts/author/{id}', [PostController::class, 'get_author']);
The above route connects the get_author
function to any GET request that goes to the http://localhost:8000/api/post/author/6
route, which will then return the author of the post with the id
of 6 like so:
- The purple box is the type of request I made, which is a
GET
request. - The yellow box is the URL I sent the request to;
http://localhost:8000/api/post/author/6
. - The green box is the result, which is the author of the post.
Recap
In this part of the series, you learned about and how to do the following:
- Check if the validation works on an endpoint
- Validate the request object using the
validate
method - Create a one-to-many relationship between
Author
andPost
using thehasMany
method - Create the inverse of the one-to-many relationship between
Author
andPost
using thebelongsTo
method - Connect the newly created functionalities to routes
In the next part, you'll learn how to set up Laravel Sanctum for the API authentication, and create the Sign-Up, Sign In, and Logout functionalities.