DEV Community

Cover image for Mini App Using Laravel Rest API Only ( back-end ) and Insomnia
Chabba Saad
Chabba Saad

Posted on • Updated on

Mini App Using Laravel Rest API Only ( back-end ) and Insomnia

in this tutorial we are going to create a mini full stack application using laravel for back-end as a CRUD REST API and Angular for front-end .

required tools for this application

  • WampServer or XAMPP for using Apache and MySQL for our Database

  • Download the Composer installer for Windows

after Runing the installer, it will set up Composer globally on your system.

https://getcomposer.org/download/

composer global require laravel/installer
Enter fullscreen mode Exit fullscreen mode

there is two way to install laravel project in our machine ,
Run the following command to create a new Laravel project:

laravel new my-laravel-api
Enter fullscreen mode Exit fullscreen mode

Image description
final results should look like this :

Image description

or we can install laravel with Composer

composer create-project  laravel/laravel my-laravel-api
Enter fullscreen mode Exit fullscreen mode

if you want to install specific version there is so many Syntax , this is the most popular :

composer create-project laravel/laravel=7.4 my-laravel-api
Enter fullscreen mode Exit fullscreen mode

Installation Steps

cd my-laravel-api
Enter fullscreen mode Exit fullscreen mode

*Installation Sanctum : *

Laravel Sanctum is a lightweight package for Laravel that enables token-based authentication for APIs. It simplifies the process of generating, managing, and authenticating tokens, providing a secure way to protect API endpoints.

  1. installing sanctum
composer require laravel/sanctum
Enter fullscreen mode Exit fullscreen mode

Image description

After successfully install package, we need to publish configuration file with following command :

The above command will create a create_personal_access_tokens_table.php in your /database/migrations folder and a sanctum.php file inside the /config folder, once you have verified the creation of those two files, the next thing to do is to migrate the new migration file, and you do that with the following command:

php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
Enter fullscreen mode Exit fullscreen mode

create migration for data :

php artisan make:migration create_posts_table 
Enter fullscreen mode Exit fullscreen mode

replace your migration in posts with any column you want to add:

    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->longText('description');
            $table->timestamps();
        });
    }
Enter fullscreen mode Exit fullscreen mode

or we can create student model and migration with same command line

creating our model with migration file:

php artisan make:model Post -m
Enter fullscreen mode Exit fullscreen mode

updating our model with this lines :

class Post extends Model
{
    use HasFactory;

    protected $fillable = ['title', 'description'];
}
Enter fullscreen mode Exit fullscreen mode

now we should create a database manually in mysql and add it to the . env file :

Image description

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=tplaravel
DB_USERNAME=root
DB_PASSWORD=
Enter fullscreen mode Exit fullscreen mode

we require to get default migration for create new sanctum tables and posts in our database. so let's run bellow command.

php artisan migrate
Enter fullscreen mode Exit fullscreen mode

the result should look like this :

Image description

  1. Create sancthum Auth and CRUD Controller
php artisan make:controller Api\AuthController
php artisan make:controller Api\PostController --model=Post
Enter fullscreen mode Exit fullscreen mode

Now update AuthContoller with

<?php

namespace App\Http\Controllers\Api;

use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Laravel\Sanctum\PersonalAccessToken;
class AuthController extends Controller
{
    /**
     * Create User
     * @param Request $request
     * @return User 
     */
    public function createUser(Request $request)
    {
        try {
            //Validated
            $validateUser = Validator::make(
                $request->all(),
                [
                    'name' => 'required',
                    'email' => 'required|email|unique:users,email',
                    'password' => 'required'
                ]
            );

            if ($validateUser->fails()) {
                return response()->json([
                    'status' => false,
                    'message' => 'validation error',
                    'errors' => $validateUser->errors()
                ], 401);
            }

            $user = User::create([
                'name' => $request->name,
                'email' => $request->email,
                'password' => Hash::make($request->password)
            ]);

            return response()->json([
                'status' => true,
                'message' => 'User Created Successfully',
                'token' => $user->createToken("API TOKEN")->plainTextToken
            ], 200);
        } catch (\Throwable $th) {
            return response()->json([
                'status' => false,
                'message' => $th->getMessage()
            ], 500);
        }
    }

    /**
     * Login The User
     * @param Request $request
     * @return User
     */
    public function loginUser(Request $request)
    {
        try {
            $validateUser = Validator::make(
                $request->all(),
                [
                    'email' => 'required|email',
                    'password' => 'required'
                ]
            );

            if ($validateUser->fails()) {
                return response()->json([
                    'status' => false,
                    'message' => 'validation error',
                    'errors' => $validateUser->errors()
                ], 401);
            }

            if (!Auth::attempt($request->only(['email', 'password']))) {
                return response()->json([
                    'status' => false,
                    'message' => 'Email & Password does not match with our record.',
                ], 401);
            }

            $user = User::where('email', $request->email)->first();

            return response()->json([
                'status' => true,
                'message' => 'User Logged In Successfully',
                'token' => $user->createToken("API TOKEN")->plainTextToken
            ], 200);
        } catch (\Throwable $th) {
            return response()->json([
                'status' => false,
                'message' => $th->getMessage()
            ], 500);
        }
    }

public function logoutUser(Request $request)
    {
     // Get bearer token from the request
        $accessToken = $request->bearerToken();

        // Get access token from database
        $token = PersonalAccessToken::findToken($accessToken);

        // Revoke token
        $token->delete();
        return [
            'message' => 'user logged out'
        ];
    }


}

Enter fullscreen mode Exit fullscreen mode

custumize message for not login users :

first step go to Middleware/Authenticate.php

use Illuminate\Auth\AuthenticationException;

// replace your redirect method by this one : 


    protected function redirectTo($request)
    {
        if ($request->expectsJson()) {
            throw new AuthenticationException('Unauthenticated.');
        }

        return response()->json(['valid' => auth()->check()]);
    }

Enter fullscreen mode Exit fullscreen mode

To change the "Route [login] not defined" error message in Laravel Sanctum's controller, you can modify the app/Exceptions/Handler.php file. Follow these steps:

Open the app/Exceptions/Handler.php file.

Inside the render method, add the following code:

use Illuminate\Auth\AuthenticationException;
use Illuminate\Validation\ValidationException;

  public function render($request, Throwable $exception)
        {
        if ($exception instanceof AuthenticationException) {
            return response()->json(['message' => 'you are not logged'], 401);
        }


        return parent::render($request, $exception);
    }
Enter fullscreen mode Exit fullscreen mode

not logged

and update your PostController :

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $posts = Post::all();

        return response()->json([
            'status' => true,
            'posts' => $posts
        ]);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        //
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    // store one post with our request post api { "title" : "test","description":"details"}
    // public function store(Request $request)
    // {
    //     $post = Post::create($request->all());

    //     return response()->json([
    //         'status' => true,
    //         'message' => "Post Created successfully!",
    //         'post' => $post
    //     ], 200);
    // }

    public function store(Request $request)
    {
        $postsData = $request->all();

        $posts = [];

        foreach ($postsData as $postData) {
            $post = Post::create($postData);
            $posts[] = $post;
        }

        return response()->json([
            'status' => true,
            'posts' => $posts
        ], 201);
    }

    /**
     * Display the specified resource.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $post = Post::find($id);

        if (!$post) {
            return response()->json([
                'status' => false,
                'message' => 'Post not found'
            ], 404);
        }

        return response()->json([
            'status' => true,
            'post' => $post
        ]);
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function edit(Post $post)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, Post $post)
    {
        $post->update($request->all());

        return response()->json([
            'status' => true,
            'message' => "Post Updated successfully!",
            'post' => $post
        ], 200);
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Models\Post  $post
     * @return \Illuminate\Http\Response
     */
    public function destroy(Post $post)
    {
        $post->delete();

        return response()->json([
            'status' => true,
            'message' => "Post Deleted successfully!",
        ], 200);
    }
}

Enter fullscreen mode Exit fullscreen mode
php artisan route:clear
Enter fullscreen mode Exit fullscreen mode

In routes\api.php file update the API

In Laravel, the Route::apiResource() method is used to define a set of RESTful API routes for a resource. In this case, the resource being defined is posts, and it is associated with the PostController class.

The apiResource() method automatically generates the following routes for the posts resource:

GET /posts: get lists of all posts.

Image description

POST /posts: Creates a new post.

Image description

GET /posts/{id}: Retrieves a specific post by its ID.

Image description

PUT /posts/{id}: Updates a specific post by its ID.

Image description

DELETE /posts/{id}: Deletes a specific post by its ID.

Image description

PATCH /posts/{id}:Updates a specific column in a post by its ID.

Image description

dont forget to add Bearer in your curl or header options after login or register for every action you want to call because we are using middleware for securing our Rest API

Image description

note :

By using either the $fillable or $guarded property, you have control over which attributes can be assigned via mass assignment, providing a level of security and control over your model's data.

 protected $fillable = ['title', 'description'];
Enter fullscreen mode Exit fullscreen mode

example of storing multi posts with our rest api :

[
    {
        "title": "t2",
        "description": "details"
    },
    {
        "title": "t3",
        "description": "more details"
    }
]
Enter fullscreen mode Exit fullscreen mode

Image description

Route::post('/auth/register', [AuthController::class, 'createUser']);
Route::post('/auth/login', [AuthController::class, 'loginUser']);
Route::post('/auth/logout', [AuthController::class, 'logoutUser']);
Route::apiResource('posts', PostController::class)->middleware('auth:sanctum');

Enter fullscreen mode Exit fullscreen mode

Github Code Source :

Top comments (0)