Refer to https://bootcamp.laravel.com/blade/installation.
Setup API
php artisan install:api
Create Chirp API Controllers:
php artisan make:controller Api/ChirpController --api
Define API Route for Chirp in routes/api.php
:
<?php
use App\Http\Controllers\Api\ChirpController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
Route::get('/chirps', [ChirpController::class, 'index']);
Create Chirp resource & collection:
php artisan make:resource ChirpResource
php artisan make:resource ChirpCollection
Disable data
wraping in resource:
<?php
namespace App\Providers;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
JsonResource::withoutWrapping();
}
}
Return list of chirps in Api/ChirpController
in index
:
return new ChirpCollection(Chirp::all());
Return chirp details in Api/ChirpController
in show
:
return new ChirpResource(Chirp::findOrFail($id));
Setup auth API endpoints - login, register & logout
Update your the OpenAPI Specification for Chirps API as in here.
Create new controller for handling Auth related:
php artisan make:controller Api/AuthController
Then update the controller as in here.
Update the routes/api.php
:
<?php
use App\Http\Controllers\Api\AuthController;
use App\Http\Controllers\Api\ChirpController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
Route::post('/register', [AuthController::class, 'register']);
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::post('/logout', [AuthController::class, 'logout']);
});
Route::get('/chirps', [ChirpController::class, 'index']);
Route::get('/chirps/{chirp}', [ChirpController::class, 'show']);
In app/Models/User.php
, add HasApiTokens
trait:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasFactory, Notifiable, HasApiTokens;
Next, open up your Insomnia, create new collection. Import collection from here.
Then open up the Enviroment settings, update base environment as following:
{
"scheme": "http",
"base_path": "/api",
"host": "127.0.0.1",
"bearerToken": "bearerToken",
"base_url": "{{ _.scheme }}://{{ _.host }}{{ _.base_path }}"
}
Now you can test your API endpoints for register, login and logout.
php artisan config:publish cors
Set the in config/cors.php
:
'supports_credentials' => true,
Install Pest:
composer remove phpunit/phpunit
composer require pestphp/pest --dev --with-all-dependencies
Setup Pest:
on Linux / Mac:
./vendor/bin/pest --init
on Windows, run:
vendor\bin\pest.bat --init
Create API unit test:
php artisan make:test ApiTest --pest
Update your unit test as in here.
To run the unit test, specifically to tests/Feature/ApiTest.php
:
vendor/bin/pest tests/Feature/ApiTest.php
or on Windows:
vendor\bin\pest.bat tests/Feature/ApiTest.php
Create artisan command:
php artisan make:command ReloadAllCachesCommand
Then update the codes as in here.
To use the command:
php artisan reload:caches
Create mail class:
php artisan make:mail WelcomeMail
Update class as in here.
Create view for welcome mail:
php artisan make:view mail.welcome
Update the mail view as in here.
Use routes/console.php
, copy as in here.
Test the email:
php artisan test:mail
Open your browser at http://127.0.0.1:8025 to see new welcome email.
Create Markdown Mail
php artisan make:mail ThankYou --markdown
Update the view as in here.
Use routes/console.php
, copy as in here.
Create notifications
table.
php artisan make:notifications-table
php artisan migrate
Create notification class:
php artisan make:notification WelcomeNotification --markdown=notifications.welcome
Then update our app/Notifications/WelcomeNotification.php
as in here.
Then update the view for the notifications as in here.
Send notification, by update routes/console.php
as in here.
php artisan test:notify
Create listener for registered user event:
php artisan make:listener SendWelcomeNotification --event=\\Illuminate\\Auth\\Events\\Registered
Update the listener as in here.
Then go and register new account. Any new registration will get notification.
Create an artisan command which send daily quote to all users. Make use of the custom artisan command, notification, event & listeners.
php artisan make:command SendDailyQuoteCommand
php artisan make:notification SendQuoteNotification --markdown=notifications.quote
php artisan make:event SendQuote
php artisan make:listener SendQuoteNotification --event=SendQuote
Update .env
to point to OAuth Server(Laravel Passport), the Client ID and Secret which generated using php artisan passport:client
command in OAuth Server and redirect URI which to handle the authentication process after approval from OAuth Server.
# OAuth Server URL
OAUTH_SERVER_URL=http://127.0.0.1:8000
# App's client id and secret
## Get this value from php artisan passport:client - Client ID
OAUTH_CLIENT_ID=
## Get this value from php artisan passport:client - Client Secret
OAUTH_CLIENT_SECRET=
# App's callback / redirect URL
OAUTH_REDIRECT_URI=http://127.0.0.1:8001/oauth/callback
In config/services.php, add the following:
'passport' => [
'url' => env('OAUTH_SERVER_URL'),
'client_id' => env('OAUTH_CLIENT_ID'),
'client_secret' => env('OAUTH_CLIENT_SECRET'),
'redirect_url' => env('OAUTH_REDIRECT_URI'),
],
In routes/web.php, disable the following section by comment it:
// Route::get('/', function () {
// return view('welcome');
// });
In routes/auth.php, add the following codes, which handle the OAuth process:
/**
* Handle OAuth
*/
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
Route::get('/', function () {
$query = http_build_query([
'client_id' => config('services.passport.client_id'),
'redirect_uri' => config('services.passport.redirect_uri'),
'response_type' => 'code',
'scope' => '',
]);
// redirect to OAuth Server, then require to login/register.
// after that require to authorize the chirper app to access.
return redirect(
config('services.passport.url') . '/oauth/authorize?' . $query
);
});
Route::get('/oauth/callback', function (Request $request) {
// get the access token
$response = Http::asForm()->post(config('services.passport.url') . '/oauth/token', [
'grant_type' => 'authorization_code',
'client_id' => config('services.passport.client_id'),
'client_secret' => config('services.passport.client_secret'),
'redirect_uri' => config('services.passport.redirect_uri'),
'code' => $request->code,
]);
try {
$data = $response->json();
$accessToken = data_get($data, 'access_token');
// use access token to get user's details
$response = Http::withToken($accessToken)->get(config('services.passport.url') . '/api/user');
abort_if(! $response->ok(), 'Invalid Crendentials');
$data = $response->json();
// if user's not exists, create it, else retrieve it.
if(! User::where('email', data_get($data, 'email'))->exists()) {
$user = User::create([
'name' => data_get($data, 'name'),
'email' => data_get($data, 'email'),
'password' => Hash::make(date('Ymd').rand(1,10000))
]);
} else {
$user = User::where('email', data_get($data, 'email'))->first();
}
// login user
Auth::login($user);
// redirect to profile page.
return redirect('profile');
} catch (\Throwable $th) {
abort(401, $th->getMessage());
}
});