Build Rest API in Laravel 9
It's completed tutorail, showing how to build API using Laravel 9

This new article would like to share how I built a REST API
application. After you
practice with this article, you will be able to create an application which can perform
operation CRUD (Create, Read, Update, and Delete)
as an API using Laravel
.
What we cover in this articles
We use Laravel, Livewire, Tailwind CSS, Laravel Breeze(Starter Kits for Authentication) and below is our content which we will cover is this article.
- Setup Laravel project
- Configure database
- Install Laravel Breeze
- Install Livewire
- Implement CRUD operations
- Running the application
Setup Laravel project
To install a fresh Laravel 9 application
composer create-project laravel/laravel laravel-api
where laravel-api
is your project name.
Configure database connection
Now you have to configure the database variable in .env
to connect your laravel application with the database server.
DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=database_name // your database nameDB_USERNAME=database_user_name // your database userDB_PASSWORD=database_password // your datbase password
Create Model
Open a new command line interface and run the follwoing command from the project folder to generate a product model with migration
php artisan make:model Product -m
Next, open your migration file inside database/migrations
<?php use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; return new class extends Migration{ /** * Run the migrations. * * @return void */ public function up() { Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('reference'); $table->string('name'); $table->longText('description'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('products'); }};
Install Laravel Breeze && Livewire
To make things more manageable, we use Laravel Breeze, a starter kit for authentication with Tailwind CSS 3. So we don't need to install and configure Tailwind.
- To Install Laravel Breeze via composer
composer require laravel/breeze
- To Setup breeze ui and auth scaffolding
php artisan breeze:install
- To Install dependencies
npm install && npm run dev
- To migrate
php artisan mgirate
- Install Livewire
composer require livewire/livewire
To activate Livewire on a page, we need to add @livewireStyles
and @livewireScripts
every page you want to use it.
Now let add it to our resources/views/layouts/app.blade.php
<!DOCTYPE html><html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Livewire CRUD') }}</title> <!-- Fonts --> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap"> <!-- Styles --> <link rel="stylesheet" href="{{ asset('css/app.css') }}"> <!-- Scripts --> <script src="{{ asset('js/app.js') }}" defer></script> <!-- Add Livewire Style --> @livewireStyles </head> <body class="font-sans antialiased"> <div class="min-h-screen bg-gray-100"> @include('layouts.navigation') <!-- Page Heading --> <header class="bg-white shadow"> <div class="px-4 py-6 mx-auto max-w-7xl sm:px-6 lg:px-8"> {{ $header }} </div> </header> <!-- Page Content --> <main> {{ $slot }} </main> </div> <!-- Add Livewire Script --> @livewireScripts </body></html>
Implement CRUD Operations
- Create
Post
Model and Migrations
php artisan make:model Post -m
After running the command above, you will get a migration. We add field title
, description
.
<?php use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema; class CreatePostsTable extends Migration{ /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->text('description'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('posts'); }}
You also generate a Model file in App/Models/Post.php
as below.
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model; class Post extends Model{ use HasFactory; protected $fillable = [ 'title', 'description' ];}
Now you can hit a command php artisan migrate
to migrate your database schema
- Now let's create controller
php artisan make:controller PostController
and update our controller with code below.
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class PostController extends Controller{ /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { return view('post'); }}
Create route for Post by edit routes/web.php
and add code below.
Route::get('post', [PostController::class,'index'])->name('post.index');
- Creating a Livewire Component To create a livewire component, run the following command:
php artisan make:livewire Post
This will create a new Post.php
class file and place it in the App\Views\Components
folder. Then, a corresponding
view
template is created and placed in resources/views/components
. To display the component, you can then use this Blade
syntax: <x-post/>
.
You can further explore Laravel Blade components in the documentation.
Now Let's create template file for post
in resources/views/post.blade.php
and add content as below.
<x-app-layout> <x-slot name="header"> <h2 class="text-xl font-semibold leading-tight text-gray-800"> Post </h2> </x-slot> <div class="py-12"> <div class="mx-auto max-w-7xl sm:px-6 lg:px-8"> <div class="overflow-hidden bg-white shadow-sm sm:rounded-lg"> <div class="p-6 bg-white border-b border-gray-200"> <livewire:post /> </div> </div> </div> </div></x-app-layout>
Next, You need to update the Post
component in app/Http/Livewire/Post.php
with code below.
<?php namespace App\Http\Livewire; use App\Models\Post;use Livewire\Component;use Livewire\WithPagination; class PostForm extends Component{ use WithPagination; public $title; public $description; public $post_id; protected $rules = [ 'title' => 'required', 'description' => 'required', ]; public function storePost() { $this->validate(); $post = Post::create([ 'title' => $this->title, 'description' => $this->description, ]); $this->reset(); } public function edit($id) { $post = Post::find($id); $this->post_id = $post->id; $this->title = $post->title; $this->description = $post->description; } public function update() { $post = Post::updateOrCreate( [ 'id' => $this->post_id, ], [ 'title' => $this->title, 'description' => $this->description, ], ); $this->reset(); } public function destroy($id) { Post::destroy($id); } public function render() { return view('livewire.post', ['posts' => Post::latest()->paginate(10)]); }}
Now you need to update livewire view component in resources/views/livewire/post.blade.php
<div> <h4 class="mb-4 text-2xl font-bold">Post </h4> <div> <div class="container mx-auto"> <form method="POST" wire:submit.prevent="storePost"> @csrf <div> <label for="title">Title</label> <input type="text" wire:model.lazy="title" class="w-full py-2 rounded"> @error('title') <span class="text-red-600">{{ $message }}</span> @enderror </div> <div class="mt-8"> <label class="block mb-2 text-xl">Description </label> <textarea wire:model.lazy="description" rows="3" cols="20" class="w-full rounded"> </textarea> @error('description') <span class="text-red-600">{{ $message }}</span> @enderror </div> <button type="submit" class="px-4 py-2 mt-4 text-white bg-blue-600 rounded"> Submit </button> <button type="submit" wire:click="update" class="px-4 py-2 text-white bg-indigo-600 rounded"> Update </button> </form> </div> <div class="flex flex-col mt-8"> <div class="py-2"> <div class="min-w-full border-b border-gray-200 shadow"> <table class="min-w-full"> <thead> <tr> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Id </th> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Title </th> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Edit </th> <th class="px-6 py-3 text-left text-gray-500 border-b border-gray-200 bg-gray-50"> Delete </th> </tr> </thead> <tbody class="bg-white"> @foreach($posts as $post) <tr> <td class="px-6 py-4 border-b border-gray-200"> <div class="flex items-center"> <div class="ml-4"> <div class="text-sm text-gray-900"> {{ $post->id }} </div> </div> </div> </td> <td class="px-6 py-4 border-b border-gray-200"> <div class="text-sm text-gray-900"> {{ $post->title }} </div> </td> <td class="px-6 py-4 border-b border-gray-200"> <button wire:click="edit({{ $post->id }})" class="px-4 py-2 text-white bg-blue-600"> Edit </button> </td> <td class="px-6 py-4 text-sm text-gray-500 border-b border-gray-200"> <button wire:click="destroy({{ $post->id }})" class="px-4 py-2 text-white bg-red-600"> Delete </button> </td> </tr> @endforeach </tbody> </table> </div> {{ $posts->links() }} </div> </div> </div></div>
- Running the application Now let's serve the application
php artisan serve
Then you can visit 127.0.0.1:8000
- Everything should work as normal, please share this posts If it's helpful to you.
- If you have issued with this post, please reach me on twitter
@iamputhea