100 Laravel practice problems with solutions

Want real confidence building Laravel apps, not just watching tutorials? This post gives you 100 Laravel practice problems with clear, step-by-step solutions. You’ll work through routing, controllers, Blade, Eloquent, migrations, forms, middleware, and APIs. Each problem is explained simply — try it first, then check the answer. Perfect for beginners and interview prep. Pick a challenge and start mastering Laravel today.

Try it: 100 PHP practice problems with solutions

1. Create a route that responds to /hello with the text “Welcome to Laravel”.

php

Route::get('/hello', function () {
    return 'Welcome to Laravel';
});

2. Create a route that accepts a name parameter and returns “Hello, {name}”.

php

Route::get('/hello/{name}', function ($name) {
    return "Hello, $name";
});

3. Create a route /sum/{a}/{b} that returns the sum of two numbers.

php

Route::get('/sum/{a}/{b}', function ($a, $b) {
    return $a + $b;
});

4. Create a controller UserController with a method index that returns “List of users”.

php

php artisan make:controller UserController

php

// app/Http/Controllers/UserController.php
namespace App\Http\Controllers;
class UserController extends Controller
{
    public function index()
    {
        return 'List of users';
    }
}

5. Register a route that calls the index method of UserController.

php

Route::get('/users', [UserController::class, 'index']);

6. Create a GET route /profile that returns a view profile.blade.php with a variable name.

php

Route::get('/profile', function () {
    return view('profile', ['name' => 'John Doe']);
});

blade

<!-- resources/views/profile.blade.php -->
<h1>Profile of {{ $name }}</h1>

7. Create a POST route /submit that accepts form data and returns the submitted name.

php

Route::post('/submit', function (\Illuminate\Http\Request $request) {
    return 'Submitted: ' . $request->input('name');
});

8. Use route name for the /user/profile route and generate a URL using the route helper.

php

Route::get('/user/profile', function () {
    return route('profile');
})->name('profile');

9. Create a route group with prefix admin and middleware auth.

php

Route::prefix('admin')->middleware('auth')->group(function () {
    Route::get('/dashboard', function () {
        return 'Admin dashboard';
    });
});

10. Create a resource controller PostController with all resourceful methods.

bash

php artisan make:controller PostController --resource

11. Register the resourceful route for PostController.

php

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

12. Generate a migration for a products table with columns: name, price, description.

bash

php artisan make:migration create_products_table

php

// database/migrations/xxxx_xx_xx_create_products_table.php
public function up()
{
    Schema::create('products', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->decimal('price', 8, 2);
        $table->text('description')->nullable();
        $table->timestamps();
    });
}

13. Run all pending migrations.

bash

php artisan migrate

14. Create a model Product with fillable fields namepricedescription.

bash

php artisan make:model Product -m

php

// app/Models/Product.php
protected $fillable = ['name', 'price', 'description'];

15. Use Eloquent to insert a new product into the database.

php

Product::create([
    'name' => 'Laptop',
    'price' => 999.99,
    'description' => 'High performance laptop'
]);

16. Retrieve all products from the database and return as JSON.

php

$products = Product::all();
return response()->json($products);

17. Update a product with id=1, change its price to 899.99.

php

$product = Product::find(1);
$product->price = 899.99;
$product->save();

18. Delete a product with id=2.

php

Product::destroy(2);

19. Create a form request StoreProductRequest with validation rules: name required, price numeric.

bash

php artisan make:request StoreProductRequest

php

// app/Http/Requests/StoreProductRequest.php
public function rules()
{
    return [
        'name' => 'required|string|max:255',
        'price' => 'required|numeric|min:0',
    ];
}

20. Use the form request in a controller method to store a product.

php

use App\Http\Requests\StoreProductRequest;

public function store(StoreProductRequest $request)
{
    $product = Product::create($request->validated());
    return redirect()->route('products.index');
}

21. Create a custom validation rule that ensures a field is uppercase.

php

use Illuminate\Support\Facades\Validator;
Validator::extend('uppercase', function ($attribute, $value, $parameters, $validator) {
    return strtoupper($value) === $value;
});

22. Use the unique validation rule on a email field during user registration.

php

'email' => 'required|email|unique:users,email'

23. Display validation errors in a Blade view.

blade

@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif

24. Create a Blade layout layouts/app.blade.php with a yield section content.

blade

<!-- resources/views/layouts/app.blade.php -->
<html>
<head><title>App</title></head>
<body>
    @yield('content')
</body>
</html>

25. Extend the layout in a child view and define the content section.

blade

@extends('layouts.app')
@section('content')
    <h1>Welcome</h1>
@endsection

26. Use a Blade component named alert that accepts a type prop (success, error).

bash

php artisan make:component Alert

blade

<!-- resources/views/components/alert.blade.php -->
<div class="alert alert-{{ $type }}">
    {{ $slot }}
</div>

php

// app/View/Components/Alert.php
public $type;
public function __construct($type = 'info')
{
    $this->type = $type;
}

blade

<x-alert type="success">Operation successful!</x-alert>

27. Create a middleware CheckAge that blocks access if age < 18.

bash

php artisan make:middleware CheckAge

php

// app/Http/Middleware/CheckAge.php
public function handle($request, $next)
{
    if ($request->input('age') < 18) {
        return redirect('home');
    }
    return $next($request);
}

28. Register the middleware globally in app/Http/Kernel.php.

php

protected $routeMiddleware = [
    'check.age' => \App\Http\Middleware\CheckAge::class,
];

29. Apply the check.age middleware to a route group.

php

Route::middleware(['check.age'])->group(function () {
    Route::get('/adults-only', function () {
        return 'Welcome adult';
    });
});

30. Use Eloquent’s where clause to get products with price > 100.

php

$expensive = Product::where('price', '>', 100)->get();

31. Use Eloquent’s orderBy to sort products by name descending.

php

$sorted = Product::orderBy('name', 'desc')->get();

32. Use the with method to eager load a relationship (e.g., posts on a User model).

php

$users = User::with('posts')->get();

33. Define a one‑to‑many relationship posts on User model.

php

// app/Models/User.php
public function posts()
{
    return $this->hasMany(Post::class);
}

34. Define the inverse one‑to‑many relationship user on Post model.

php

// app/Models/Post.php
public function user()
{
    return $this->belongsTo(User::class);
}

35. Create a seeder that inserts 10 random users into the database.

bash

php artisan make:seeder UserSeeder

php

// database/seeders/UserSeeder.php
public function run()
{
    \App\Models\User::factory(10)->create();
}

36. Run the seeder.

bash

php artisan db:seed --class=UserSeeder

37. Use database transactions to safely update a product and its inventory.

php

use Illuminate\Support\Facades\DB;
DB::transaction(function () {
    $product = Product::find(1);
    $product->price = 199;
    $product->save();
    Inventory::where('product_id', 1)->decrement('quantity', 1);
});

38. Create a query scope active in the Product model that returns products with status = active.

php

// app/Models/Product.php
public function scopeActive($query)
{
    return $query->where('status', 'active');
}

39. Use the active scope to retrieve active products.

php

$activeProducts = Product::active()->get();

40. Use Laravel’s query builder to perform a raw SQL select.

php

$results = DB::select('SELECT * FROM products WHERE price > ?', [50]);

41. Create a custom artisan command SendEmails.

bash

php artisan make:command SendEmails

php

// app/Console/Commands/SendEmails.php
protected $signature = 'emails:send {user}';
public function handle()
{
    $user = User::find($this->argument('user'));
    $this->info("Sending email to {$user->email}");
}

42. Register the command and call it via php artisan emails:send 1.
It is automatically registered after creation; just run php artisan emails:send 1.

43. Schedule a task to run daily at midnight (e.g., prune old records).

php

// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
    $schedule->command('records:prune')->daily();
}

44. Use the artisan tinker REPL to retrieve the first product.

bash

php artisan tinker
>>> App\Models\Product::first();

45. Create an event OrderShipped and its listener SendShipmentNotification.

bash

php artisan make:event OrderShipped
php artisan make:listener SendShipmentNotification --event OrderShipped

php

// app/Events/OrderShipped.php
// app/Listeners/SendShipmentNotification.php

46. Dispatch the OrderShipped event after an order is updated.

php

event(new OrderShipped($order));

47. Create a notification class InvoicePaid that sends an email.

bash

php artisan make:notification InvoicePaid

php

// app/Notifications/InvoicePaid.php
public function via($notifiable)
{
    return ['mail'];
}
public function toMail($notifiable)
{
    return (new MailMessage)->line('Your invoice has been paid.');
}

48. Send the notification to a user.

php

$user->notify(new InvoicePaid());

49. Use Laravel’s built‑in authentication scaffolding (UI) for login/register.

bash

composer require laravel/ui
php artisan ui bootstrap --auth
npm install && npm run dev

50. Protect a route with the auth middleware.

php

Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware('auth');

51. Get the currently authenticated user’s ID in a controller.

php

$userId = auth()->id();

52. Hash a password using the Hash facade before storing.

php

use Illuminate\Support\Facades\Hash;
$hashed = Hash::make('plain-text-password');

53. Verify a plain password against a hashed one.

php

if (Hash::check('plain-text-password', $hashed)) {
    // correct
}

Try it: 100 MySQL practice problems with solutions

54. Create a policy for the Post model to restrict update to the owner.

bash

php artisan make:policy PostPolicy --model=Post

php

// app/Policies/PostPolicy.php
public function update(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

55. Authorize the update action in a controller using the policy.

php

$this->authorize('update', $post);

56. Use pagination on a product list (10 per page).

php

$products = Product::paginate(10);

blade

{{ $products->links() }}

57. Implement soft deletes for the Product model.

bash

php artisan make:migration add_soft_deletes_to_products_table

php

// migration: $table->softDeletes();
// Model: use SoftDeletes;

58. Retrieve trashed (soft-deleted) products.

php

$trashed = Product::onlyTrashed()->get();

59. Restore a soft-deleted product.

php

$product = Product::withTrashed()->find(5);
$product->restore();

60. Use Laravel’s env() helper to read the APP_NAME configuration.

php

$appName = env('APP_NAME', 'Laravel');

61. Create a custom helper function formatPrice that adds currency symbol.

php

// app/Helpers/helpers.php
if (! function_exists('formatPrice')) {
    function formatPrice($price)
    {
        return '$' . number_format($price, 2);
    }
}

62. Autoload the helpers file via composer.json.

json

"autoload": {
    "files": ["app/Helpers/helpers.php"]
}

63. Use Redis to cache a product query for 60 seconds.

php

use Illuminate\Support\Facades\Cache;
$product = Cache::remember('product.1', 60, function () {
    return Product::find(1);
});

64. Use the cache helper to store a value permanently.

php

cache(['key' => 'value']);

65. Create a job SendWelcomeEmail and dispatch it on the queue.

bash

php artisan make:job SendWelcomeEmail

php

dispatch(new SendWelcomeEmail($user));

66. Run the queue worker to process jobs.

bash

php artisan queue:work

67. Use Laravel’s Str helper to generate a random string of length 10.

php

use Illuminate\Support\Str;
$random = Str::random(10);

68. Use Collection methods to filter and map data.

php

$filtered = Product::all()->filter(function ($product) {
    return $product->price > 100;
})->map(function ($product) {
    return $product->name;
});

Try it: CSS practice problems with solutions

69. Create a database index on products.name column via a migration.

php

Schema::table('products', function (Blueprint $table) {
    $table->index('name');
});

70. Use lazy or chunk to process large data without memory issues.

php

Product::chunk(100, function ($products) {
    foreach ($products as $product) {
        // process
    }
});

71. Create a scheduled artisan command that sends a weekly report every Monday.

php

$schedule->command('report:weekly')->mondays()->at('08:00');

72. Use Laravel’s local scope to get products with stock > 0.

php

public function scopeInStock($query)
{
    return $query->where('stock', '>', 0);
}

73. Use the firstOrCreate method to find a user by email or create new one.

php

$user = User::firstOrCreate(
    ['email' => 'john@example.com'],
    ['name' => 'John Doe', 'password' => bcrypt('secret')]
);

74. Create a many‑to‑many relationship between User and Role with pivot table.

php

// User model
public function roles()
{
    return $this->belongsToMany(Role::class);
}

75. Sync roles for a user (assign role IDs 1,2,3).

php

$user->roles()->sync([1,2,3]);

76. Use withCount to get the number of posts for each user.

php

$users = User::withCount('posts')->get();
foreach ($users as $user) {
    echo $user->posts_count;
}

77. Handle SQL exceptions using custom try‑catch.

php

try {
    DB::insert('insert into products (name) values (?)', ['Laptop']);
} catch (\Illuminate\Database\QueryException $e) {
    if ($e->getCode() == 23000) {
        // Duplicate entry
    }
}

78. Create a custom error page for 404 (resources/views/errors/404.blade.php).

blade

<!-- resources/views/errors/404.blade.php -->
<h1>Page not found</h1>
<p>The requested page does not exist.</p>

79. Use config helper to define and retrieve a custom configuration settings.timezone.

php

// config/settings.php
return ['timezone' => 'UTC'];

php

$tz = config('settings.timezone');

80. Use service container to bind an interface to a concrete implementation.

php

use App\Contracts\PaymentGateway;
use App\Services\StripeGateway;
$this->app->bind(PaymentGateway::class, StripeGateway::class);

81. Resolve a class from the service container by type‑hinting in a controller constructor.

php

public function __construct(PaymentGateway $gateway)
{
    $this->gateway = $gateway;
}

82. Create a global middleware that logs every request URL and method.

php

// app/Http/Middleware/LogRequest.php
public function handle($request, $next)
{
    \Log::info($request->method() . ' ' . $request->fullUrl());
    return $next($request);
}

83. Register the middleware as web group middleware in Kernel.php.

php

protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\LogRequest::class,
    ],
];

84. Use route helper to generate absolute URL for named route product.show with parameter id.

php

$url = route('product.show', ['id' => 5]);

85. Create a signed URL that expires in 30 minutes for a route invoice.download.

php

$url = URL::temporarySignedRoute('invoice.download', now()->addMinutes(30), ['id' => 1]);

86. Verify a signed request in the controller using hasValidSignature middleware.

php

Route::get('/invoice/{id}/download', function ($id) {
    // ...
})->middleware('signed')->name('invoice.download');

87. Use Storage facade to upload a file to the public disk.

php

use Illuminate\Support\Facades\Storage;
$path = Storage::disk('public')->putFile('uploads', $request->file('avatar'));

88. Generate a symbolic link for public/storage to storage/app/public.

bash

php artisan storage:link

89. Create a mail class OrderShipped and send it.

bash

php artisan make:mail OrderShipped

php

Mail::to($user->email)->send(new OrderShipped($order));

90. Use markdown mail template for the OrderShipped mail.

php

public function build()
{
    return $this->markdown('emails.orders.shipped');
}

91. Use the env file to set QUEUE_CONNECTION=database and create the jobs table.

bash

php artisan queue:table
php artisan migrate

92. Specify the queue name high when dispatching a job.

php

dispatch((new ProcessPodcast)->onQueue('high'));

93. Use dispatchAfterResponse to run a job after the HTTP response is sent.

php

dispatchAfterResponse(new SendNotification);

94. Create a custom validation rule object Uppercase.

bash

php artisan make:rule Uppercase

php

app/Rules/Uppercase.php
public function passes($attribute, $value)
{
    return strtoupper($value) === $value;
}
public function message()
{
    return 'The :attribute must be uppercase.';
}

95. Use the custom rule in a validator.

php

use App\Rules\Uppercase;
'code' => ['required', new Uppercase]

96. Use lazyLoading detection to identify N+1 queries.

php

// In AppServiceProvider
Model::preventLazyLoading(! app()->isProduction());

97. Use dd (dump and die) to inspect a variable.

php

dd(Product::all());

98. Create a singleton binding in the service container that returns the same instance each time.

php

$this->app->singleton(SomeService::class, function ($app) {
    return new SomeService($app->make(Config::class));
});

99. Use throw_unless helper to throw an exception unless condition is true.

php

throw_unless($user->isAdmin(), AuthorizationException::class);

Try it: 100 Javascript practice problems with solutions

100. Deploy a Laravel application by optimizing the configuration and caching routes.

bash

php artisan config:cache
php artisan route:cache
php artisan view:cache

Final Thought

You did it — 100 Laravel problems conquered! Can you feel that electric buzz? That’s the thrill of knowing you didn’t just study Laravel, you built with it! Every route you mapped, every controller you crafted, every Eloquent query you finessed — it all adds up to one undeniable truth: you’re a Laravel developer now, and nothing can stop you!

Think about how far you’ve come! From simple Blade views to full API endpoints, you’ve unlocked level after level like a coding superhero. The magic of Laravel is no longer a mystery — it’s your playground! Every new project, every client, every job interview is about to meet a version of you that’s sharper, faster, and bursting with confidence.

Don’t let the momentum fade! Take this fire and build that dream app you’ve been thinking about. Tackle an even bigger challenge. Bookmark this page as your personal trophy cabinet — proof that you can master anything you set your mind to. The web is waiting for what you’ll create next! Go build, go shine, and keep that joyful Laravel spark alive!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top