Learn Laravel 8

03 Apr 2022 - nicolas

summary

create project

composer create-project laravel/laravel:^8.0 myAppNameHere
cd myAppNameHere
php artisan serve

list artisan commands

php artisan
php artisan list

create test

create feature test:

php artisan make:test MyClassNameHereTest

create model

php artisan make:model modelNameHere

to create a migration file in the meantime, add -m

php artisan make:model modelNameHere -m
php artisan make:model modelNameHere --migration

update .env file with the database credentials

run the migration

php artisan migrate

create controller

php artisan make:controller MyControllerNameHereController -r
php artisan make:controller MyControllerNameHereController  --resource

create request

php artisan make:request MyRequestNameHereRequest

create routes

add routes in routes/api.php

Route::httpVerbHere('pluralResourceNameHere', "ControllerNameHere@controllerMethodNameHere");

Example

initial tutorial from Smit Pipaliya

create project

composer create-project laravel/laravel:^8.0 my-public-api
cd my-public-api
php artisan serve

create model

php artisan make:model Post -m

where app/Models/Post.php can be modified like so:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFactory;

    protected $table = 'posts';
    protected $fillable = [
    	'name',
    	'image',
    	'description'
    ];
}

and the migration file like that:

<?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('name');
            $table->string('image');
            $table->text('description');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

update .env file with the database credentials:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3307
DB_DATABASE=my-public-api
DB_USERNAME=root
DB_PASSWORD=

run the migration

php artisan migrate

create controller

this controller will perform CRUD operations

php artisan make:controller PostController -r
php artisan make:controller PostController  --resource

will create the file app/Http/Controllers/PostController.php

create request

this request object will validate requests to our API

php artisan make:request PostStoreRequest

will create the file app/Http/Requests/PostStoreRequest.php

create routes

add routes in routes/api.php

Route::get('posts', [PostController::class, 'index']);
Route::post('posts', [PostController::class, "store"]);
Route::get('posts/{id}', [PostController::class, "show"]);
Route::put('posts/{id}', [PostController::class, "update"]);
Route::delete('posts/{id}', [PostController::class, "destroy"]);

or

Route::resource('posts','PostController');

or

Route::resources([
    'posts' => PostController::class,
]);

list posts

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $posts = Post::all();

        return response()->json([
            'posts' => $posts,
        ], 200);
    }
}

show post

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        $post = Post::find($id);

        if (!$post) {
            return response()->json([
                'message' => 'Post Not Found.'
            ], 404);
        }

        return response()->json([
            'post' => $post
        ], 200);
    }
}

create post

controller:

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\Request;
use App\Http\Requests\PostStoreRequest;
use Illuminate\Support\Facades\Storage;

class PostController extends Controller
{
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(PostStoreRequest $request)
    {
        try {
            $imageName = Str::random(32) . "." . $request->image->getClientOriginalExtension();
            Post::create([
                'name' => $request->name,
                'image' => $imageName,
                'description' => $request->description
            ]);
            // Save Image in directory storage/app/public
            Storage::disk('public')->put($imageName, file_get_contents($request->image));

            return response()->json([
                'message' => "Post successfully created."
            ], 200);
        } catch (\Exception $e) {

            return response()->json([
                'message' => "Something went really wrong!"
            ], 500);
        }
    }
}

request validation:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class PostStoreRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        if (request()->isMethod('post')) {
            return [
                'name' => 'required|string|max:258',
                'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
                'description' => 'required|string'
            ];
        }

        return [
            'name' => 'required|string|max:258',
            'image' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
            'description' => 'required|string'
        ];
    }

    public function messages()
    {
        if(request()->isMethod('post')) {
            return [
                'name.required' => 'Name is required',
                'image.required' => 'Image is required',
                'description.required' => 'Description is required'
            ];
        }

        return [
            'name.required' => 'Name is required',
            'description.required' => 'Description is required'
        ];
    }
}

Update post

if the request is using form-data instead of json, create a POST request with _method parameter set to PUT:

  curl --location --request POST 'http://127.0.0.1:8000/api/posts/1' \
      --header 'Accept: application/json' \
      --form 'image=@"/path/to/myImage.jpg"' \
      --form 'name="my post name updated"' \
      --form 'description="my post description updated"' \
      --form '_method="PUT"'
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Support\Str;
use App\Http\Requests\PostStoreRequest;
use Illuminate\Support\Facades\Storage;

class PostController extends Controller
{
    public function update(PostStoreRequest $request, $id)
    {
        try {
            $post = Post::find($id);

            if (!$post) {

                return response()->json([
                    'message' => 'Post Not Found.'
                ], 404);
            }

            $post->name = $request->name;
            $post->description = $request->description;

            if ($request->image) {
                // Public storage
                $storage = Storage::disk('public');

                // Delete stored image
                if ($storage->exists($post->image)) {
                    $storage->delete($post->image);
                }

                // Image name
                $imageName = Str::random(32) . "." . $request->image->getClientOriginalExtension();
                $post->image = $imageName;

                // Image save in public folder
                $storage->put($imageName, file_get_contents($request->image));
            }

            // Update Post
            $post->save();

            return response()->json([
                'message' => "Post successfully updated."
            ], 200);
        } catch (\Exception $e) {

            return response()->json([
                'message' => "Something went really wrong!"
            ], 500);
        }
    }
}

Delete post

<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Support\Str;
use App\Http\Requests\PostStoreRequest;
use Illuminate\Support\Facades\Storage;

class PostController extends Controller
{
    public function destroy($id)
    {
        // find post
        $post = Post::find($id);

        if (!$post) {

            return response()->json([
                'message' => "Post $id not found.",
            ], 404);
        }

        // delete image file
        $storage = Storage::disk('public');

        if ($storage->exists($post->image)) {
            $storage->delete($post->image);
        }

        // delete post
        $post->delete();

        return response()->json([
            'message' => "Post $id deleted."
        ], 200);
    }
}