DEV Community

Tanzim Ibthesam
Tanzim Ibthesam

Posted on • Updated on

Making Api CRUD(Create,Read,Update,Delete) with Laravel 8 n API Authentication with sanctum

Here I am going to mention about how you can make an API with Laravel 8 and Using PostMan. This is inspired from Traversy Medias videos on Laravel APi and Authentication with sanctum Laravel 8 REST API With Sanctum Authentication. SO you can definitely go and watch that.

1.Creating a new Laravel project

laravel new laravel-api-sanctum

2.Create a model Product along with Controllers,Seeders,Factory

php artisan make:model Product -a it creates model,factory,seeder here its not essential to create Seeders and Factory but I showed this command so that it can help in future development when you need to use seeders and factories.

3.In Product migrations table

$table->id();
$table->string('name');
$table->string('slug');
$table->string('description')->nullable();
$table->decimal('price',5,2);
$table->timestamps();
Enter fullscreen mode Exit fullscreen mode

Then run php artisan migrate

4. API testing and routes api.php

Usually in Laravel when we use web.php,when we want to make Single Page Application or mobile apps we need api for that we need to use api.php
in api.php we can write

Route::post('/products', function () {

    return Product::create([
        'name'=>'Product One',
         'slug'=>'product-one',
         'description'=>'Details of Product One',
         'price'=>9.99

    ]);

});

Enter fullscreen mode Exit fullscreen mode

Then just go to Product.php and for mass assignment. It is a process through which an array of data will be saved to specific model. Here model is Product
In Product.php we need to write protected $guarded=[];
In Postman while sending requests we get
CREATE
Alt Text
This is how we send post requests in POSTMAN
READ

public function index(){
  return Product::all();
}
Enter fullscreen mode Exit fullscreen mode

This is how we can get all products data in PostMan

Alt Text
To send request through Controller in ProductController.php

Now let us try to make requests through Controller. Here its a Resource Controller
In api.php

Route::post('/products', [ProductController::class,'store']);
Enter fullscreen mode Exit fullscreen mode

In ProductController.php

 public function store(Request $request)
    {
        //
       return Product::create($request->all());
    }
Enter fullscreen mode Exit fullscreen mode

If we again send get requests to Postman we will get all 3 products
But if we try to insert data without any field it must give us an error
VALIDATION ERROR

public function store(Request $request)
    {
        //
        $request->validate([
            'name'=>'required',
            'description'=>'required',
            'slug'=>'required',
            'price'=>'required'


        ]);
       return Product::create($request->all());
    }
Enter fullscreen mode Exit fullscreen mode

Get a single product from the route
Now instead of writing each and every route we can write it in a Resource Controller
Route::resource('products', ProductController::class);

Update data
In ProductController.php

  public function update(Request $request,$id)
    {
        //
        $product=Product::find($id);
        $product->update($request->all());
        return $product;

    }
Enter fullscreen mode Exit fullscreen mode

While we send requests to PostMan for Update this is what it give us
Alt Text
Here we can specify the id we want to update
DELETE
Delete Data
In ProductController.php

public function destroy($id)
    {
        //
        return Product::destroy($id);
    }

Enter fullscreen mode Exit fullscreen mode

If we send delete request in Postman we get

Alt Text
We are deleting as per id.

For search
In ProductController.php

 public function search($name)
    {
        //
        return Product::where('name','like','%'.$name.'%')->get();
    }
Enter fullscreen mode Exit fullscreen mode

In Postman while sending search requests
Alt Text

API Authentication with Sanctum

Now we are done with API CRUD part we will now enable API authentication with Sanctum
To install Laravel sanctum
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
In app/Http/Kernel.php

'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
Enter fullscreen mode Exit fullscreen mode

In User.php we need to write use use Laravel\Sanctum\HasApiTokens on top and HasAPiTokens below

use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
     use HasApiTokens, HasFactory, Notifiable;
Enter fullscreen mode Exit fullscreen mode

In api.php
Public routes means here anyone can view the products all products or individual products

/public routes 
Route::get('/products', [ProductController::class,'index']);
// Route::resource('products', ProductController::class);
Route::get('/products/{id}', [ProductController::class,'show']);

//Protected routes-Only authenticated users can have access to protected routes//
Route::group(['middleware' => ['auth:sanctum']], function () {
     Route::post('/products',[ProductController::class,'store']);
     Route::put('/products/{id}',[ProductController::class,'update']);
     Route::delete('/products/{id}',[ProductController::class,'delete']);


 });
Enter fullscreen mode Exit fullscreen mode

Auth Controller
Create a new Controller for Authentication
php artisan make:controller AuthController

Register method

public function register(Request $request){
        $fields=$request->validate([
            'name'=>'required|string',
            'email'=>'required|string|unique:users,email',
            'password'=>'required|string|confirmed'


        ]);

        $user=User::create([
            'name'=>$fields['name'],
            'email'=>$fields['email'],
             'password'=>bcrypt($fields['password'])

        ]);

        $token=$user->createToken('myapptoken')->plainTextToken;

        $response=[
            'user'=>$user,
            'token'=>$token

        ];

        return response($response,201);

    }
Enter fullscreen mode Exit fullscreen mode

In api.php

Route::post('/register',[AuthController::class,'register']);

Enter fullscreen mode Exit fullscreen mode

In
api.php
Register

Route::post('/register',[AuthController::class,'register']);
Enter fullscreen mode Exit fullscreen mode

Testing out in Postman
If we dont give anything it returns us validation errors

Alt Text

So here we see upon registration it gives us a token
Here with help of the token an authenticated user can post,edit and delete
Now we see it gives us a new token
With this token I will be able to gain access to protected routes. If we send post requests we need to use bearer select the bearer token option token and insert the token

Alt Text
While we send post request now we can post data
Now we need to create Logout function in AuthController.php

 public function logout(Request $request){
        auth()->user()->tokens()->logout();

        return [
            'message'=>'Logged out'
        ];
    }
Enter fullscreen mode Exit fullscreen mode

In api.php

Route::group(['middleware' => ['auth:sanctum']], function () {
     Route::post('/products',[ProductController::class,'store']);
     Route::put('/products/{id}',[ProductController::class,'update']);
     Route::delete('/products/{id}',[ProductController::class,'delete']);
     Route::post('/logout',[AuthController::class,'logout']);


 });
Enter fullscreen mode Exit fullscreen mode

If we now insert the token in bearer token and try to logout
Alt Text
We see the message as logged out the token is no longer valid
Now we can delete,update and post if we are authenticated using that Token

Top comments (9)

Collapse
 
saanchitapaul profile image
Sanchita Paul • Edited

I am getting error during logout. I didn't use any relation ,then why it's showing MorphMany error ?

<title>🧨 Call to undefined method Illuminate\Database\Eloquent\Relations\MorphMany::logout()</title>

Collapse
 
tanzimibthesam profile image
Tanzim Ibthesam

Hello Sanchita can you please check whether you have written the logout method in Controller properly.Thanks

Collapse
 
saanchitapaul profile image
Sanchita Paul

I solved this using delete method. It was showing error using logout.

public function logout(Request $request){
//auth()->user()->tokens()->logout();
auth()->user()->currentAccessToken()->delete();
return [
'message'=>'You're logged out'
];
}

Thread Thread
 
tanzimibthesam profile image
Tanzim Ibthesam

Thanks

Collapse
 
kiryadev profile image
Kirill

Bad examples about $request->all(...).
Good decision is $request->validated(); or Product::create($request->validate(...))

Collapse
 
tanzimibthesam profile image
Tanzim Ibthesam

Thanks so much for your feedback yes will correct it and such feedback really helps to understand the mistakes

Collapse
 
dgloriaweb profile image
dgloriaweb

Hi, forgot how to add a joined table to the index function pls help!!
This doesn't work

return Question::all()
->with(compact('language'));

Collapse
 
tanzimibthesam profile image
Tanzim Ibthesam

Can you explain your models and relations

Collapse
 
dgloriaweb profile image
dgloriaweb

Oh, thanks, I've figure it out.

return Question::with('language')->get();