In this article, I will guide you through the process of building a RESTful API with CRUD (Create, Read, Update, Delete) operations in Laravel 10. Laravel is a powerful PHP framework that provides a robust set of tools for developing web applications, and its RESTful API capabilities make it an excellent choice for building APIs.
One of the essential aspects of modern web development is building APIs that allow seamless communication between different applications and services. With Laravel's built-in support for API development, you can create a secure and efficient API that follows REST principles.
To enhance the security of our API, we will utilize Laravel Passport for authentication. Laravel Passport provides a simple and convenient way to implement OAuth2 server functionality, allowing us to authenticate and authorize API requests.
In this article, we will cover the step-by-step process of setting up Laravel Passport authentication for our API and implementing the CRUD operations. We will explore how to create endpoints for creating, reading, updating, and deleting resources, following RESTful conventions.
By the end of this article, you will have a solid understanding of building a RESTful API in Laravel 10, including implementing CRUD operations and securing it with Passport authentication.
This knowledge will empower you to create powerful and secure APIs for your web applications, opening up opportunities for seamless integration with other systems.
So, let's dive in and explore the world of Laravel 10 REST API development with Passport authentication!
Install Laravel 10 by running the following command in your terminal:
composer create-project --prefer-dist laravel/laravel api-project
Configure your database credentials in the .env
file.
Install Laravel Passport by running the following command.
composer require laravel/passport
Run the migration to create the necessary tables for Passport.
php artisan migrate
Generate encryption keys for Passport.
php artisan passport:install
Now, we have to configure the model, service provider, and auth config file.
1. HasApiTokens class of Passport has been added to the User model,
Add the below code in app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Passport\HasApiTokens;
class User extends Authenticatable implements MustVerifyEmail
{
use Notifiable,HasApiTokens;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}
2. In AuthServiceProvider we have added "Passport::routes()"
Add below code app/Providers/AuthServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
use Laravel\Passport\Passport;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Models\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
3. We have added API auth configuration in auth.php.
In config/auth.php add the below code.
<?php
return [
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
];
To store the data for our API resource, we need to create a table in the database and a corresponding model in Laravel.
php artisan make:migration create_products_table
Open the generated migration file located in the database/migrations
directory. In this file, define the table schema for your resource. Specify the columns you need, their types, and any additional constraints.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateProductsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('detail');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('products');
}
}
Next, run the migration to create the product table in the database by executing the command.
php artisan migrate
After creating the table, let's generate a model Product.
And add the below code in the app/Models/Product.php file
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'name', 'detail'
];
}
The fillable
property is used to specify which attributes can be mass-assigned when creating or updating Product
records.
Open the routes/api.php
file and define the API routes for your application. For example, to define routes for the products
resource, you can use the following code:
routes/api.php
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\RegisterController;
use App\Http\Controllers\API\ProductController;
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::post('register', [RegisterController::class, 'register']);
Route::post('login', [RegisterController::class, 'login']);
Route::middleware('auth:api')->group( function () {
Route::resource('products', ProductController::class);
});
The middleware('auth:api')
ensures that the routes are protected and only accessible to authenticated users.
Now, I have created BaseController, ProductController, and RegisterController in the API folder.
app/Http/Controllers/API/BaseController.php
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class BaseController extends Controller
{
public function sendResponse($result, $message)
{
$response = [
'success' => true,
'data' => $result,
'message' => $message,
];
return response()->json($response, 200);
}
public function sendError($error, $errorMessages = [], $code = 404)
{
$response = [
'success' => false,
'message' => $error,
];
if(!empty($errorMessages)){
$response['data'] = $errorMessages;
}
return response()->json($response, $code);
}
}
app/Http/Controllers/API/ProductController.php
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Product;
use Validator;
use App\Http\Controllers\API\BaseController as BaseController;
use App\Http\Resources\Product as ProductResource;
class ProductController extends BaseController
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$products = Product::all();
return $this->sendResponse(ProductResource::collection($products), 'Products Retrieved Successfully.');
}
/**
* 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
*/
public function store(Request $request)
{
$input = $request->all();
$validator = Validator::make($input, [
'name' => 'required',
'detail' => 'required'
]);
if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}
$product = Product::create($input);
return $this->sendResponse(new ProductResource($product), 'Product Created Successfully.');
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$product = Product::find($id);
if (is_null($product)) {
return $this->sendError('Product not found.');
}
return $this->sendResponse(new ProductResource($product), 'Product Retrieved Successfully.');
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$input = $request->all();
$validator = Validator::make($input, [
'name' => 'required',
'detail' => 'required'
]);
if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}
$product = Product::find($id);
$product->name = $input['name'];
$product->detail = $input['detail'];
$product->save();
return $this->sendResponse(new ProductResource($product), 'Product Updated Successfully.');
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
$product = Product::find($id);
$product->delete();
return $this->sendResponse([], 'Product Deleted Successfully.');
}
}
app/Http/Controllers/API/RegisterController.php
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Controllers\API\BaseController as BaseController;
use App\User;
use Illuminate\Support\Facades\Auth;
use Validator;
class RegisterController extends BaseController
{
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'c_password' => 'required|same:password',
]);
if($validator->fails()){
return $this->sendError('Validation Error.', $validator->errors());
}
$input = $request->all();
$input['password'] = bcrypt($input['password']);
$user = User::create($input);
$success['token'] = $user->createToken('MyApp')->accessToken;
$success['name'] = $user->name;
return $this->sendResponse($success, 'User register successfully.');
}
public function login(Request $request)
{
if(Auth::attempt(['email' => $request->email, 'password' => $request->password])){
$user = Auth::user();
$success['token'] = $user->createToken('MyApp')->accessToken;
$success['name'] = $user->name;
return $this->sendResponse($success, 'User login successfully.');
}
else{
return $this->sendError('Unauthorised.', ['error'=>'Unauthorised']);
}
}
}
Eloquent API Resources allow you to transform your model data into a custom format for API responses. Let's create an API Resource for the Product
model to control how the Product
data is presented in the API responses.
To generate an API Resource for the Product
model, run the following Artisan command.
php artisan make:resource Product
Now, a new file was created on this app/Http/Resources/Product.php path.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class Product extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'detail' => $this->detail,
'created_at' => $this->created_at->format('d/m/Y'),
'updated_at' => $this->updated_at->format('d/m/Y'),
];
}
}
In the toArray()
method, you define the structure of the response array by specifying the attributes to include from the Product
model. You can add additional attributes or customize the response format as needed.
Now, I have used POSTMAN API for testing purposes, Postman is a collaboration platform for API development. Postman's features simplify each step of building an API and streamline collaboration so you can create better APIs faster.
Here I have added some screenshots with descriptions of the postman for your better understanding.
1 - Register API: Verb: GET, URL:http://localhost:8000/api/register
2 - After successfully registering in postman we need to add an access token in the headers.
3 - Login API: Verb: GET, URL:http://localhost:8000/api/login
4 - Create Product List API: Verb: GET, URL:http://localhost:8000/api/products
5 - Product Show API: Verb: GET, URL:http://localhost:8000/api/products/{id}
6 - Product Update API: Verb: PUT, URL:http://localhost:8000/api/products/{id}
7 - Product Delete API: Verb: DELETE, URL:http://localhost:8000/api/products/{id}
You might also like:
- Read Also: Building Complete CRUD Application in Laravel 10
- Read Also: Convert HTML to PDF in Python: Step-by-Step Guide
- Read Also: Importing Excel File into Database Using Python
- Read Also: How to Get Current Date and Time in Python