03 Apr 2022 - nicolas
composer create-project laravel/laravel:^8.0 myAppNameHere
cd myAppNameHere
php artisan serve
set .env file:
DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
create file database/database.sqlite
shell commands:
sed -i 's/DB_CONNECTION=.*/DB_CONNECTION=sqlite/' .env
touch database/database.sqlite
create the model and migration files:
php artisan make:model Product --migration
update the migration file in laravel-sanctum-api/database/migrations/2022_09_16_210904_create_products_table.php to add columns to the model:
<?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->string('slug');
$table->string('description')->nullable();
$table->decimal('price', 5, 2);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('products');
}
}
execute the migration to update the database:
php artisan migrate
update laravel-sanctum-api/routes/api.php:
<?php
use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
// endpoint GET /api/products
Route::get('/products', function () {
return Product::all();
});
add fillable property to the model for POST requests:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
use HasFactory;
protected $fillable = [
'name',
'slug',
'description',
'price',
];
}
update laravel-sanctum-api/routes/api.php:
Illuminate\Support\Facades\Route::post('/products', function () {
return \App\Models\Product::create([
'name' => 'product name 1',
'slug' => 'product-slug-1',
'description' => 'product description 1',
'price' => '123.45',
]);
});
now using request data:
Illuminate\Support\Facades\Route::post('/products', function (Request $request) {
return \App\Models\Product::create($request->all());
});
now adding validation:
Illuminate\Support\Facades\Route::post('/products', function (Request $request) {
$request->validate([
'name' => 'required',
'slug' => 'required',
'price' => 'required',
]);
return \App\Models\Product::create($request->all());
});
create controller with blank CRUD methods (--api):
php artisan make:controller ProductController --api
refactor routes:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
Route::get('/products', [ProductController::class, 'index']);
Route::get('/products/{id}', [ProductController::class, 'show']);
Route::post('/products', [ProductController::class, 'store']);
or use the Route::Ressource method:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\ProductController;
Route::resource('products', ProductController::class);
update the controller file:
<?php
namespace App\Http\Controllers;
use App\Models\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return Product::all();
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'slug' => 'required',
'price' => 'required',
]);
return Product::create($request->all());
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
return Product::find($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)
{
$product = Product::find($id);
$product->update($request->all());
return $product;
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
return Product::destroy($id);
}
}
add route in laravel-sanctum-api/routes/api.php:
Route::get('/products/search/{name}', [ProductController::class, 'search']);
controller:
/**
* @param string $name
* @return \Illuminate\Http\Response
*/
public function search($name)
{
$product = Product::where('name', 'like', "%{$name}%")->get();
return Product::where('name', 'like', "%{$name}%")->get();
}
composer require laravel/sanctum:^2.9 # for laravel 8
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
update laravel-sanctum-api/app/Http/Kernel.php file:
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
protect a route:
Route::group(['middleware' => 'auth:sanctum'], function () {
Route::get('/easter-egg', function () {
return 'hello';
});
});
create a Controller:
php artisan make:controller AuthController
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
class AuthController extends Controller
{
public function register(Request $request)
{
$fields = $request->validate([
'name' => 'required|string',
'email' => 'required|string|unique:users,email',
'password' => 'required|string|confirmed',
]);
$user = User::create([
'name' => $fields['name'],
'email' => $fields['email'],
'password' => bcrypt($fields['password']),
]);
$token = $user->createToken('myapptoken')->plainTextToken;
$response = [
'user' => $user,
'token' => $token,
];
return response($response, 201);
}
}
add a public register route in laravel-sanctum-api/routes/api.php:
Route::post('/register', [AuthController::class, 'register']);
usage:
send a POST request to get a token:
{ "name": "lara clette", "email": "lara@clette.com", "password": "hello", "password_confirmation": "hello" }add a header in requests on protected routes:
Authorization Bearer: tokenHere
update the controller:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
class AuthController extends Controller
{
//
// ...
//
public function logout(Request $request)
{
auth()->user()->tokens()->delete();
return [
'message' => 'Logged out.',
];
}
}
add a protected register route in laravel-sanctum-api/routes/api.php:
Route::post('/logout', [AuthController::class, 'logout']);
update the controller:
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
class AuthController extends Controller
{
//
// ...
//
public function login(Request $request)
{
$fields = $request->validate([
'email' => 'required|string',
'password' => 'required|string',
]);
// check email
$user = User::where('email', $fields['email'])->first();
// check password
if (null === $user || false === Hash::check($fields['password'], $user->password)) {
return response([
'message' => 'Bad creds'
], 401);
}
$token = $user->createToken('myapptoken')->plainTextToken;
$response = [
'user' => $user,
'token' => $token,
];
return response($response, 201);
}
}
add a public register route in laravel-sanctum-api/routes/api.php:
Route::post('/logout', [AuthController::class, 'logout']);