Câu Hỏi Phỏng Vấn PHP Laravel Developer 2026: Hướng Dẫn Chuẩn Bị Toàn Diện

Hướng dẫn toàn diện để chuẩn bị cho buổi phỏng vấn PHP Laravel developer năm 2026. Bao gồm các câu hỏi kỹ thuật về Eloquent ORM, Service Container, authentication, queue và testing.

Câu Hỏi Phỏng Vấn PHP Laravel Developer 2026

Câu hỏi phỏng vấn PHP Laravel developer kiểm tra cả kiến thức framework và nguyên lý thiết kế phần mềm. Với việc Laravel 13 được phát hành vào tháng 3 năm 2026 giới thiệu AI SDK, PHP Attributes và Passkey authentication, nhà tuyển dụng kỳ vọng ứng viên thể hiện sự am hiểu về các tính năng mới nhất cùng với những kiến thức nền tảng cốt lõi.

Các Lĩnh Vực Trọng Tâm Phỏng Vấn

Phỏng vấn Laravel thường bao gồm năm trụ cột chính: quan hệ Eloquent ORM và hiệu năng, Service Container và dependency injection, các mô hình authentication và authorization, xử lý queue và job, cùng với chiến lược testing. Các vị trí senior còn bổ sung thêm quyết định kiến trúc và kiến thức về hệ sinh thái package.

Câu Hỏi Eloquent ORM và Database

Eloquent vẫn là chủ đề được thảo luận nhiều nhất trong các buổi phỏng vấn Laravel. Nhà tuyển dụng đánh giá liệu ứng viên có hiểu về lazy vs eager loading, các loại quan hệ và tối ưu hóa query hay không.

H: Vấn đề N+1 query là gì và Laravel giải quyết nó như thế nào?

Vấn đề N+1 xảy ra khi code thực thi một query để lấy collection, sau đó thêm N query bổ sung để load dữ liệu liên quan cho mỗi item. Laravel cung cấp eager loading thông qua with() để giải quyết vấn đề này.

app/Http/Controllers/PostController.phpphp
// Vấn đề N+1: 1 query cho posts + N queries cho authors
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->author->name; // Kích hoạt một query cho mỗi post
}

// Giải pháp: Eager load với with()
$posts = Post::with('author')->get(); // Tổng cộng 2 queries
foreach ($posts as $post) {
    echo $post->author->name; // Không có query bổ sung
}

Laravel 13 duy trì strict mode trong môi trường development, sẽ throw exception khi lazy loading xảy ra, giúp phát hiện sớm các vấn đề N+1.

H: Giải thích sự khác biệt giữa hasOne, hasMany, belongsTobelongsToMany.

Quan HệVị Trí Foreign KeyVí Dụ
hasOneTrên model liên quanUser hasOne Profile (profiles.user_id)
hasManyTrên model liên quanUser hasMany Posts (posts.user_id)
belongsToTrên model hiện tạiPost belongsTo User (posts.user_id)
belongsToManyBảng pivotUser belongsToMany Roles (bảng role_user)

H: Làm thế nào để xử lý soft deletes và các tác động của nó là gì?

app/Models/Post.phpphp
use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;
    
    // Các record soft-deleted được loại trừ mặc định
    // Để bao gồm chúng:
    // Post::withTrashed()->get();
    // Để chỉ lấy những record đã xóa:
    // Post::onlyTrashed()->get();
}

Soft deletes thêm cột deleted_at. Các query tự động loại trừ record soft-deleted trừ khi được yêu cầu rõ ràng. Điều này ảnh hưởng đến unique constraints và yêu cầu compound indexes bao gồm deleted_at để có hiệu năng tối ưu.

Service Container và Dependency Injection

Service Container là cốt lõi của Laravel. Hiểu về binding, resolution và contextual injection phân biệt developer junior với senior.

H: Sự khác biệt giữa bind, singleton và instance trong Service Container là gì?

app/Providers/AppServiceProvider.phpphp
public function register(): void
{
    // bind: Instance mới mỗi lần resolve
    $this->app->bind(PaymentService::class, function ($app) {
        return new PaymentService($app->make(StripeClient::class));
    });
    
    // singleton: Cùng một instance trong suốt request
    $this->app->singleton(CartService::class, function ($app) {
        return new CartService();
    });
    
    // instance: Bind một instance đã tồn tại
    $analytics = new AnalyticsService('UA-xxxxx');
    $this->app->instance(AnalyticsService::class, $analytics);
}

H: Contextual binding hoạt động như thế nào?

Contextual binding cho phép inject các implementation khác nhau dựa trên class nào cần dependency đó.

app/Providers/AppServiceProvider.phpphp
public function register(): void
{
    $this->app->when(PhotoController::class)
        ->needs(Filesystem::class)
        ->give(function () {
            return Storage::disk('photos');
        });

    $this->app->when(VideoController::class)
        ->needs(Filesystem::class)
        ->give(function () {
            return Storage::disk('videos');
        });
}

Câu Hỏi Authentication và Authorization

Laravel 13 mở rộng các tính năng authentication với hỗ trợ passkey native. Các buổi phỏng vấn thường bao gồm cả authentication truyền thống và hiện đại.

H: Giải thích sự khác biệt giữa Gates và Policies.

Gates là các closure đơn giản xác định liệu user có được phép thực hiện action hay không. Policies nhóm logic authorization xung quanh một model cụ thể.

app/Providers/AppServiceProvider.phpphp
use Illuminate\Support\Facades\Gate;

public function boot(): void
{
    // Gate: Closure đơn giản
    Gate::define('edit-settings', function (User $user) {
        return $user->isAdmin();
    });
}

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

// Sử dụng trong controller
public function update(Request $request, Post $post)
{
    $this->authorize('update', $post);
    // Hoặc: Gate::authorize('edit-settings');
}

H: Làm thế nào để implement Passkey authentication trong Laravel 13?

routes/web.phpphp
use Illuminate\Support\Facades\Route;

Route::middleware('web')->group(function () {
    Route::post('/passkey/register', [PasskeyController::class, 'store']);
    Route::post('/passkey/authenticate', [PasskeyController::class, 'authenticate']);
});

// app/Http/Controllers/PasskeyController.php
use Illuminate\Support\Facades\Auth;
use Laravel\Passkey\Passkey;

class PasskeyController extends Controller
{
    public function store(Request $request)
    {
        $passkey = Passkey::createFor($request->user());
        return response()->json(['passkey' => $passkey]);
    }
    
    public function authenticate(Request $request)
    {
        $user = Passkey::authenticate($request->credential);
        Auth::login($user);
        return redirect('/dashboard');
    }
}

Câu Hỏi Queue và Job

Hiểu về xử lý background rất quan trọng để xây dựng các ứng dụng có khả năng mở rộng.

H: Khi nào nên sử dụng queue và làm thế nào để xử lý job thất bại?

Queue nên được sử dụng cho các thao tác tốn thời gian mà không yêu cầu phản hồi ngay lập tức: gửi email, xử lý hình ảnh, gọi API bên thứ ba.

app/Jobs/ProcessPodcast.phpphp
class ProcessPodcast implements ShouldQueue
{
    use Queueable;
    
    public $tries = 3;
    public $backoff = [60, 300, 600]; // Exponential backoff
    public $timeout = 120;
    
    public function __construct(public Podcast $podcast) {}
    
    public function handle(AudioProcessor $processor): void
    {
        $processor->process($this->podcast->audio_path);
    }
    
    public function failed(\Throwable $exception): void
    {
        // Gửi thông báo cho admin
        Notification::route('mail', 'admin@example.com')
            ->notify(new JobFailed($this->podcast, $exception));
    }
}

// Dispatch job
ProcessPodcast::dispatch($podcast)
    ->onQueue('podcasts')
    ->delay(now()->addMinutes(5));

H: Giải thích job batching và các trường hợp sử dụng.

Job batching cho phép thực thi một nhóm job và thực hiện callback khi toàn bộ batch hoàn thành.

app/Http/Controllers/ImportController.phpphp
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;

public function import(Request $request)
{
    $jobs = collect($request->users)->map(function ($userData) {
        return new ImportUser($userData);
    });
    
    $batch = Bus::batch($jobs)
        ->then(function (Batch $batch) {
            // Tất cả job hoàn thành thành công
            Notification::send($batch->createdBy, new ImportCompleted());
        })
        ->catch(function (Batch $batch, \Throwable $e) {
            // Phát hiện job thất bại đầu tiên trong batch
            Log::error('Batch failed', ['batch_id' => $batch->id]);
        })
        ->finally(function (Batch $batch) {
            // Batch đã hoàn thành thực thi
        })
        ->allowFailures()
        ->dispatch();
    
    return response()->json(['batch_id' => $batch->id]);
}

Câu Hỏi Testing

Ứng dụng Laravel được test kỹ lưỡng thể hiện sự trưởng thành về mặt kỹ thuật. Nhà tuyển dụng kỳ vọng sự quen thuộc với PHPUnit và Pest.

H: Cách tiếp cận feature testing so với unit testing trong Laravel như thế nào?

Unit tests kiểm tra các class riêng lẻ một cách độc lập. Feature tests kiểm tra toàn bộ luồng HTTP request.

tests/Unit/Services/DiscountServiceTest.phpphp
use App\Services\DiscountService;

test('calculates percentage discount correctly', function () {
    $service = new DiscountService();
    $result = $service->calculate(100, 'SAVE20');
    
    expect($result)->toBe(80.0);
});

// tests/Feature/Api/ProductTest.php
use App\Models\Product;
use App\Models\User;

test('authenticated users can create products', function () {
    $user = User::factory()->create();
    
    $response = $this->actingAs($user)
        ->postJson('/api/products', [
            'name' => 'Laravel Course',
            'price' => 99.99,
        ]);
    
    $response->assertStatus(201)
        ->assertJsonPath('data.name', 'Laravel Course');
    
    $this->assertDatabaseHas('products', [
        'name' => 'Laravel Course',
        'user_id' => $user->id,
    ]);
});

H: Làm thế nào để mock external services trong test?

tests/Feature/PaymentTest.phpphp
use App\Services\PaymentGateway;
use Mockery;

test('processes payment successfully', function () {
    $mock = Mockery::mock(PaymentGateway::class);
    $mock->shouldReceive('charge')
        ->once()
        ->with(100, 'tok_visa')
        ->andReturn(['status' => 'success', 'id' => 'ch_123']);
    
    $this->app->instance(PaymentGateway::class, $mock);
    
    $response = $this->postJson('/api/payments', [
        'amount' => 100,
        'token' => 'tok_visa',
    ]);
    
    $response->assertStatus(200)
        ->assertJsonPath('payment_id', 'ch_123');
});

Câu Hỏi Laravel 13 và Các Tính Năng Hiện Đại

H: Giải thích tính năng AI SDK mới trong Laravel 13.

Laravel 13 giới thiệu abstraction first-party để tương tác với các AI provider.

config/ai.php đã được cấu hình với providerphp
// app/Services/ContentService.php
use Illuminate\Support\Facades\AI;

class ContentService
{
    public function generateSummary(string $content): string
    {
        $response = AI::chat()
            ->system('You are a helpful assistant that summarizes content.')
            ->user("Summarize this: {$content}")
            ->generate();
        
        return $response->text;
    }
    
    public function streamResponse(string $prompt)
    {
        return AI::chat()
            ->user($prompt)
            ->stream();
    }
}

H: PHP Attributes cải thiện Laravel 13 như thế nào?

app/Http/Controllers/UserController.phpphp
use Illuminate\Routing\Attributes\Get;
use Illuminate\Routing\Attributes\Middleware;

#[Middleware('auth')]
class UserController extends Controller
{
    #[Get('/users/{user}')]
    public function show(User $user)
    {
        return view('users.show', compact('user'));
    }
    
    #[Get('/users/{user}/edit')]
    #[Middleware('can:edit,user')]
    public function edit(User $user)
    {
        return view('users.edit', compact('user'));
    }
}

Câu Hỏi Kiến Trúc và Best Practices

Các vị trí senior thường bao gồm câu hỏi thiết kế hệ thống.

H: Làm thế nào để cấu trúc một ứng dụng Laravel lớn?

Các ứng dụng lớn được hưởng lợi từ việc tổ chức theo domain-driven.

text
app/
├── Domain/
│   ├── Orders/
│   │   ├── Actions/
│   │   │   └── CreateOrderAction.php
│   │   ├── Models/
│   │   │   └── Order.php
│   │   ├── Events/
│   │   │   └── OrderCreated.php
│   │   └── Services/
│   │       └── OrderService.php
│   └── Users/
│       ├── Actions/
│       ├── Models/
│       └── Services/
├── Http/
│   └── Controllers/
└── Providers/

H: Giải thích việc implement Repository pattern trong Laravel.

app/Repositories/Contracts/UserRepositoryInterface.phpphp
interface UserRepositoryInterface
{
    public function find(int $id): ?User;
    public function findByEmail(string $email): ?User;
    public function create(array $data): User;
    public function paginate(int $perPage = 15): LengthAwarePaginator;
}

// app/Repositories/EloquentUserRepository.php
class EloquentUserRepository implements UserRepositoryInterface
{
    public function __construct(private User $model) {}
    
    public function find(int $id): ?User
    {
        return $this->model->find($id);
    }
    
    public function findByEmail(string $email): ?User
    {
        return $this->model->where('email', $email)->first();
    }
    
    public function create(array $data): User
    {
        return $this->model->create($data);
    }
    
    public function paginate(int $perPage = 15): LengthAwarePaginator
    {
        return $this->model->paginate($perPage);
    }
}

// app/Providers/RepositoryServiceProvider.php
public function register(): void
{
    $this->app->bind(
        UserRepositoryInterface::class,
        EloquentUserRepository::class
    );
}

Sẵn sàng chinh phục phỏng vấn Laravel?

Luyện tập với mô phỏng tương tác, flashcards và bài kiểm tra kỹ thuật.

Kết Luận

Phỏng vấn PHP Laravel developer năm 2026 kiểm tra sự hiểu biết sâu sắc về các tính năng framework và khả năng đưa ra quyết định kiến trúc đúng đắn. Ứng viên nên chuẩn bị cho các câu hỏi thực hành về Eloquent ORM, Service Container, authentication, queue và testing. Hiểu về các tính năng Laravel 13 như AI SDK và PHP Attributes thể hiện sự nhận thức về sự phát triển của hệ sinh thái. Tập trung vào việc viết code sạch, có thể test và dễ bảo trì, cùng với khả năng giải thích các đánh đổi giữa các cách tiếp cận khác nhau sẽ giúp ứng viên thành công trong các buổi phỏng vấn Laravel.

Thử thách hôm nay

Bạn có tìm ra lỗi trong Laravel không?

Một đoạn mã thật, một lỗi ẩn, mỗi ngày một lượt. Không cần tài khoản để thử.

Anthony Fillion-Maillet

Viết bởi

Anthony Fillion-Maillet

Người sáng lập SharpSkill

Lập trình viên fullstack hơn 10 năm. Anh điều hành SharpSkill và chịu trách nhiệm về mọi nội dung đăng tại đây.

Cập nhật ngày 7 tháng 9, 2026

Thẻ

#php
#laravel
#interview
#web development
#backend

Chia sẻ

Bài viết liên quan