I hope everything is going well for you. I'm going to show you how to create a rest API in Laravel today. We'll build a restful API with Laravel 6 from the ground up. Rest APIs are increasingly widely used in web development.
Here, I'll show you how to use a passport to authenticate a rest API in a Laravel 7 application. In this tutorial, I'll teach you how to create restful api authentication in Laravel 7 using eloquent api resources. In Laravel 7, you can easily learn rest api for crud module with authentication.
When working with mobile applications, you must use the Rest API. If your programme is intended for both web and mobile platforms, you'll need to create an API for mobile development.
Laravel, on the other hand, makes it simple to create APIs. You can easily accomplish it with a passport if you have authentication in your mobile app. Passport in Laravel 7 provides a means to generate auth tokens for verifying users.
If you also want to create a rest API for your mobile app, you may follow this guide for step-by-step instructions on how to create a rest API with Laravel 7. If you're a beginner, don't worry; I'll walk you through this guide step by step.
This tutorial will teach you how to use the Laravel passport. That is, how to make use of the Laravel passport. I'll use Laravel passport for api authentication in this tutorial, and a simple e-commerce project to generate restful api crud. So, let's get started on our laravel rest api tutorial with a passport example.
Step 1: Install Laravel
I'll walk you through everything step by step. First, we'll create a new Laravel 6 application with the commands below. So, open a terminal OR a command prompt and type the following command:
composer create-project --prefer-dist laravel/laravel api
Step 2: Setup Passport
In this stage, we'll use the Composer package management to install passport, so open a terminal and type the following command:
composer require laravel/passport
Following the successful installation of the package, we must obtain default migration in order to create new passport tables in our database. So, let's run the command below.
php artisan migrate
The next step is to use the command to install passport. It will generate token keys for security using the passport:install
command. So, let's run the command below:
php artisan passport:install
Step 3: Passport Configuration
We must configure three things in this step: the model, the service provider, and the auth config file. So all you have to do now is keep track of the changes in that file.
The HasApiTokens
class of Passport was added to the model.
Passport::routes()
was added to AuthServiceProvider.
We added api auth configuration to auth.php
app/User.php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Laravel\Passport\HasApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens, Notifiable;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
}
app/Providers/AuthServiceProvider.php
namespace App\Providers;
use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
public function boot()
{
$this->registerPolicies();
}
}
config/auth.php
return [
.....
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
.....
]
Step 4: Create API Routes
Route::post('register', 'API\RegisterController@register');
Route::post('login', 'API\RegisterController@login');
Route::apiResource('/products','ProductController');
Route::group(['prefix' => 'products'],function() {
Route::apiResource('/{product}/reviews','ReviewController');
});
Step 5: Create Model Migration and Controller and Factory
php artisan make:model Product -fmr
php artisan make:model Review -fmr
app/Http/Controllers/API/BaseController.php
namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller as Controller;
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/RegisterController.php
namespace App\Http\Controllers\API;
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']);
}
}
}
Step 6: Setup database table
Open your migration table and put the code below into it.
database/migrations/products.php
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->text('detail');
$table->double('price');
$table->string('stock');
$table->double('discount');
$table->integer('user_id')->unsigned();
$table->timestamps();
});
database/migrations/reviews.php
Schema::create('reviews', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('product_id');
$table->string('customer');
$table->text('review');
$table->double('star');
$table->timestamps();
});
Step 7: Make relationship between product and review
We must now establish a link between the Product model and the Review model. To make it work, copy and paste the code into your product and review model.
app/Product.php
namespace App;
use App\Review;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'name', 'detail', 'stock','price','discount'
];
public function reviews()
{
return $this->hasMany(Review::class);
}
}
app/Review.php
namespace App;
use App\Product;
use Illuminate\Database\Eloquent\Model;
class Review extends Model
{
protected $fillable = [
'customer', 'star', 'review'
];
public function product()
{
return $this->belongsTo(Product::class);
}
}
Step 8: Setup factory
Our database table and relationship are now complete. We can now run our migrate command to save that table in our database. So, after you've set up your database, run php artisan migrate and open it up.
database/factory/ProductFactory.php
use Faker\Generator as Faker;
$factory->define(Product::class, function (Faker $faker) {
return [
"name" => $faker->word,
"detail" => $faker->paragraph,
"price" => $faker->numberBetween(100,1000),
"stock" => $faker->randomDigit,
"discount" => $faker->numberBetween(2,30),
"user_id" => function(){
return \App\User::all()->random();
}
];
});
database/factory/ReviewFactory.php
use Faker\Generator as Faker;
$factory->define(Review::class, function (Faker $faker) {
return [
"product_id" => function(){
return App\Product::all()->random();
},
"customer" => $faker->name,
"review" => $faker->paragraph,
"star" => $faker->numberBetween(0,5)
];
});
Our factory setup is now complete. It's now time to add some dummy data. So, open your command prompt and paste the following command lines one after the other.
php artisan tinker
factory(\App\Product::class,50)->create()
factory(\App\Review::class,50)->create()
exit
We now have 50 products and 50 reviews for our products after running this command.
Step 9: Setup Product Controller
Now it's time to get the data for our API from the database. So Open
app\Http\Controllers\ProductController.php
namespace App\Http\Controllers;
use App\Http\Requests\ProductRequest;
use App\Http\Resources\ProductCollection;
use App\Http\Resources\ProductResource;
use App\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class ProductController extends Controller
{
public function __construct()
{
$this->middleware('auth:api')->except('index','show');
}
public function index()
{
return ProductCollection::collection(Product::paginate(5));
}
public function store(ProductRequest $request)
{
$product = new Product;
$product->name = $request->name;
$product->detail = $request->description;
$product->price = $request->price;
$product->stock = $request->stock;
$product->discount = $request->discount;
$product->save();
return response([
'data' => new ProductResource($product)
],Response::HTTP_CREATED);
}
public function show(Product $product)
{
return new ProductResource($product);
}
public function update(Request $request, Product $product)
{
$this->userAuthorize($product);
$request['detail'] = $request->description;
unset($request['description']);
$product->update($request->all());
return response([
'data' => new ProductResource($product)
],Response::HTTP_CREATED);
}
public function destroy(Product $product)
{
$product->delete();
return response(null,Response::HTTP_NO_CONTENT);
}
public function userAuthorize($product)
{
if(Auth::user()->id != $product->user_id){
//throw your exception text here;
}
}
}
Step 10: Create Resource Collection
Simply type the following commands to create a product resource and a review resource.
php artisan make:resource ProductCollection
php artisan make:resource ProductResouce
php artisan make:resource ReviewResource
Following this command, three files will be added to the app/Http/Resources
slug. Why did we build this resource or collection, for example? We can return our api data without this, but if you use Collection or Resource, you can adjust your return data. How did you do it? Look
app/Http/Resources/ProductCollection.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class ProductCollection extends Resource {
public function toArray($request)
{
return [
'name' => $this->name,
'totalPrice' => round((1-($this->discount/100)) * $this->price,2),
'discount' => $this->discount,
'rating' => $this->reviews->count() > 0 ? round($this->reviews->sum('star')/$this->reviews->count(),2) : 'No rating yet',
'href' => [
'link' => route('products.show',$this->id)
]
];
}
}
As you can see, the name of our return data field contains information such as name, totalPrice, discount, and so on. You are free to use whatever name you choose. However, if you don't use it, you won't be able to update your outcome data. We may also add other field names to offer more information for a certain data. I hope you can see why we require a resource or collection.
app/Http/Resources/ProductResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class ProductResource extends Resource
{
public function toArray($request)
{
return [
'name' => $this->name,
'description' => $this->detail,
'price' => $this->price,
'stock' => $this->stock == 0 ? 'Out of stock' : $this->stock,
'discount' => $this->discount,
'totalPrice' => round((1-($this->discount/100)) * $this->price,2),
'rating' => $this->reviews->count() > 0 ? round($this->reviews->sum('star')/$this->reviews->count(),2) : 'No rating yet',
'href' => [
'reviews' => route('reviews.index',$this->id)
]
];
}
}
app/Http/Resources/ReviewResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class ReviewResource extends JsonResource
{
public function toArray($request)
{
return [
'customer' => $this->customer,
'body' => $this->review,
'star' => $this->star,
];
}
}
Step 11: Create Custom Request
For handling form data, Laravel provides a default Request. However, for a given model, we can utilise a custom request. To make a request, copy and paste the code below.
php artisan make:request Product
php artisan make:request Review
Now go to app/Http/Requests
and you'll see two new files.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ProductRequest extends FormRequest
{
public function authorize()
{
return true; //Only authorize user can do this operation if false then unauthorize user can do
}
public function rules()
{
return [
'name' => 'required|max:255|unique:products',
'description' => 'required',
'price' => 'required|max:10',
'stock' => 'required|max:6',
'discount' => 'required|max:2'
];
}
}
True or false is returned by the authorize()
method. If true, it will only work for authenticated users; if false, it will work for all users. HTML form data was validated using the rules()
method.
app/Http/Requests/ReviewRequest.php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ReviewRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
"customer" => "required",
"star" => "required|integer|between:0,5",
"review" => "required"
];
}
}
Step 12: Setup review controller
app/Http/Controllers/ReviewController.php
namespace App\Http\Controllers;
use App\Http\Resources\ReviewResource;
use App\Product;
use App\Review;
use Illuminate\Http\Request;
class ReviewController extends Controller
{
public function index(Product $product)
{
return ReviewResource::collection($product->reviews);
}
public function store(ReviewRequest $request , Product $product)
{
$review = new Review($request->all());
$product->reviews()->save($review);
return response([
'data' => new ReviewResource($review)
],Response::HTTP_CREATED);
}
public function update(Request $request, Product $procduct, Review $review)
{
$review->update($request->all());
}
public function destroy(Product $product, Review $review)
{
$review->delete();
return response(null,Response::HTTP_NO_CONTENT);
}
}
Everything for our rest api development project is now complete. So now you're ready to use Postman to run our Rest Api data. In Laravel, we are now able to operate a full restful api as well as a passport api. So, let's execute our example, so use the command below to run it quickly:
php artisan serve
Ensure that the following headers are used in the details api:
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$accessToken,
]
I hope you will like the content and it will help you to learn How to Create REST API in Laravel7 using Passport
If you like this content, do share.