# Soluções Laravel: Padrões Avançados, Depuração e Perguntas de Entrevista 2026 > Dominar soluções Laravel com padrões arquiteturais avançados, técnicas de depuração e conhecimentos essenciais para entrevistas. Classes de serviço, padrão Repository, depuração com Telescope e perguntas frequentes. - Published: 2026-08-25 - Updated: 2026-08-25 - Author: Anthony Fillion-Maillet - Tags: laravel, php, debugging, design-patterns, interview - Reading time: 12 min --- As soluções Laravel para aplicações em produção exigem muito mais do que operações CRUD básicas. A diferença entre um desenvolvedor Laravel júnior e sênior se manifesta na estruturação do código, nos métodos de depuração e na capacidade de responder perguntas arquiteturais durante entrevistas técnicas. > **O que os recrutadores procuram** > > As vagas sênior de Laravel esperam que os candidatos expliquem o Service Container, demonstrem fluxos de trabalho de depuração com Telescope ou Debugbar, e justifiquem quando usar padrões como Repository versus consultas Eloquent diretas. ## Classes de Serviço: Extraindo Lógica de Negócio dos Controllers Os controllers no Laravel lidam com preocupações HTTP: receber requisições, validar entradas e retornar respostas. A lógica de negócio pertence a classes de serviço dedicadas, tornando o código testável e reutilizável através de controllers, comandos e jobs. ```php // app/Services/OrderService.php // Service class encapsulating order business logic namespace App\Services; use App\Models\Order; use App\Models\User; use App\Exceptions\InsufficientStockException; use App\Jobs\SendOrderConfirmationEmail; use Illuminate\Support\Facades\DB; class OrderService { public function __construct( private InventoryService $inventory, private PaymentService $payment ) {} /** * Create an order with full validation and side effects * * @throws InsufficientStockException */ public function createOrder(User $user, array $items, string $paymentMethod): Order { // Validate stock availability before starting transaction foreach ($items as $item) { if (!$this->inventory->hasStock($item['product_id'], $item['quantity'])) { throw new InsufficientStockException($item['product_id']); } } return DB::transaction(function () use ($user, $items, $paymentMethod) { // Create order record $order = $user->orders()->create([ 'status' => 'pending', 'total' => $this->calculateTotal($items), ]); // Attach order items foreach ($items as $item) { $order->items()->create($item); $this->inventory->decrementStock($item['product_id'], $item['quantity']); } // Process payment $this->payment->charge($user, $order->total, $paymentMethod); $order->update(['status' => 'paid']); // Queue confirmation email SendOrderConfirmationEmail::dispatch($order); return $order; }); } private function calculateTotal(array $items): int { return collect($items)->sum(fn($item) => $item['price'] * $item['quantity']); } } ``` ```php // app/Http/Controllers/OrderController.php // Controller delegating to service class namespace App\Http\Controllers; use App\Http\Requests\CreateOrderRequest; use App\Services\OrderService; use Illuminate\Http\JsonResponse; class OrderController extends Controller { public function __construct( private OrderService $orderService ) {} public function store(CreateOrderRequest $request): JsonResponse { $order = $this->orderService->createOrder( $request->user(), $request->validated('items'), $request->validated('payment_method') ); return response()->json(['order_id' => $order->id], 201); } } ``` As classes de serviço podem ser injetadas em qualquer lugar do Laravel: controllers, comandos, outros serviços ou classes de job. A [documentação do Service Container](https://laravel.com/docs/11.x/container) cobre a resolução automática e os bindings. ## Padrão Repository: Quando Eloquent Direto Não É Suficiente O padrão Repository adiciona uma camada de abstração entre a lógica de negócio e o acesso a dados. Este padrão se mostra valioso quando as aplicações precisam trocar fontes de dados, cachear resultados de consultas de forma transparente, ou isolar lógica de consultas complexas. > **Contexto de entrevista** > > Os candidatos são frequentemente perguntados se usam o padrão Repository com Laravel. A resposta correta depende do contexto: repositórios agregam valor para aplicações grandes com requisitos de dados complexos, mas criam abstração desnecessária para aplicações CRUD simples. ```php // app/Repositories/Contracts/UserRepositoryInterface.php // Interface defining the contract namespace App\Repositories\Contracts; use App\Models\User; use Illuminate\Support\Collection; interface UserRepositoryInterface { public function findById(int $id): ?User; public function findByEmail(string $email): ?User; public function getActiveUsers(): Collection; public function getUsersWithRecentOrders(int $days = 30): Collection; public function create(array $data): User; public function update(User $user, array $data): User; } ``` ```php // app/Repositories/EloquentUserRepository.php // Eloquent implementation of the repository namespace App\Repositories; use App\Models\User; use App\Repositories\Contracts\UserRepositoryInterface; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Cache; class EloquentUserRepository implements UserRepositoryInterface { public function findById(int $id): ?User { return Cache::remember( "user.{$id}", now()->addMinutes(10), fn() => User::find($id) ); } public function findByEmail(string $email): ?User { return User::where('email', $email)->first(); } public function getActiveUsers(): Collection { return User::where('status', 'active') ->orderBy('name') ->get(); } public function getUsersWithRecentOrders(int $days = 30): Collection { return User::whereHas('orders', function ($query) use ($days) { $query->where('created_at', '>=', now()->subDays($days)); }) ->with(['orders' => fn($q) => $q->latest()->limit(5)]) ->get(); } public function create(array $data): User { $user = User::create($data); Cache::forget("user.{$user->id}"); return $user; } public function update(User $user, array $data): User { $user->update($data); Cache::forget("user.{$user->id}"); return $user->fresh(); } } ``` ```php // app/Providers/RepositoryServiceProvider.php // Binding interface to implementation namespace App\Providers; use App\Repositories\Contracts\UserRepositoryInterface; use App\Repositories\EloquentUserRepository; use Illuminate\Support\ServiceProvider; class RepositoryServiceProvider extends ServiceProvider { public function register(): void { $this->app->bind( UserRepositoryInterface::class, EloquentUserRepository::class ); } } ``` A implementação do repositório gerencia o cache internamente, permitindo que as classes de serviço se concentrem nas regras de negócio em vez da invalidação de cache. ## Depuração de Aplicações Laravel com Telescope [Laravel Telescope](https://laravel.com/docs/11.x/telescope) fornece um assistente de depuração que registra requisições, exceções, consultas de banco de dados, jobs e muito mais. A depuração em produção requer entender quais métricas importam e como filtrar o ruído. ```php // config/telescope.php // Telescope configuration for different environments return [ 'enabled' => env('TELESCOPE_ENABLED', true), // Only record slow queries in production 'query' => [ 'slow' => env('TELESCOPE_SLOW_QUERY_THRESHOLD', 100), // milliseconds ], // Prune old entries to manage database size 'storage' => [ 'database' => [ 'connection' => env('DB_CONNECTION', 'mysql'), 'chunk' => 1000, ], ], ]; ``` ```php // app/Providers/TelescopeServiceProvider.php // Custom filtering for Telescope entries namespace App\Providers; use Laravel\Telescope\IncomingEntry; use Laravel\Telescope\Telescope; use Laravel\Telescope\TelescopeApplicationServiceProvider; class TelescopeServiceProvider extends TelescopeApplicationServiceProvider { public function register(): void { Telescope::night(); $this->hideSensitiveRequestDetails(); // Filter out noise in production Telescope::filter(function (IncomingEntry $entry) { // Always record exceptions and slow queries if ($entry->isException()) { return true; } if ($entry->isSlowQuery()) { return true; } // Skip health check endpoints if ($entry->isRequest() && str_starts_with($entry->content['uri'] ?? '', '/health')) { return false; } // Skip static asset requests if ($entry->isRequest() && preg_match('/\.(css|js|png|jpg|svg)$/', $entry->content['uri'] ?? '')) { return false; } // Record everything in local environment if ($this->app->environment('local')) { return true; } // Production: only record failures and slow operations return $entry->isFailedRequest() || $entry->isFailedJob() || $entry->hasMonitoredTag(); }); } protected function hideSensitiveRequestDetails(): void { // Hide sensitive data from Telescope UI Telescope::hideRequestParameters(['password', 'password_confirmation', 'token']); Telescope::hideRequestHeaders(['authorization', 'cookie']); } } ``` O método `isSlowQuery()` marca as consultas de banco de dados que excedem o limite configurado. A análise de consultas lentas revela índices ausentes e problemas N+1 que ferramentas de profiling como [Debugbar](https://github.com/barryvdh/laravel-debugbar) também detectam. ## Perguntas de Entrevista Comuns e Respostas Sólidas As entrevistas técnicas para vagas de Laravel seguem padrões. As perguntas abaixo aparecem frequentemente, e as respostas demonstram a profundidade que os entrevistadores esperam. ### O Que É o Service Container e Por Que É Importante? O Service Container é o [container de injeção de dependências](https://laravel.com/docs/11.x/container) do Laravel. Ele gerencia as dependências das classes e realiza a injeção de dependências automaticamente. Quando um construtor de controller tem um type-hint de `OrderService`, o container resolve e injeta uma instância. ```php // Automatic resolution: container reads type hints and builds dependencies public function __construct(OrderService $service) { // $service is automatically instantiated and injected } // Manual binding for interfaces or complex setup $this->app->bind(PaymentGateway::class, function ($app) { return new StripeGateway( config('services.stripe.key'), config('services.stripe.secret') ); }); // Singleton: same instance throughout the request $this->app->singleton(MetricsCollector::class, function ($app) { return new MetricsCollector( $app->make(Cache::class) ); }); ``` O container permite um acoplamento fraco: as classes dependem de abstrações (interfaces) em vez de implementações concretas, tornando os testes e a troca de implementações simples. ### Como o Laravel Gerencia Transações de Banco de Dados? O Laravel encapsula as operações de banco de dados em transações usando o método `DB::transaction()`. As transações garantem a atomicidade: ou todas as operações são bem-sucedidas, ou tudo é revertido. ```php // Simple transaction with automatic rollback on exception DB::transaction(function () { $user = User::create(['email' => 'test@example.com']); $user->profile()->create(['bio' => 'New user']); // If profile creation fails, user creation rolls back }); // Manual transaction control for complex flows DB::beginTransaction(); try { $order = Order::create($data); PaymentGateway::charge($order->total); DB::commit(); } catch (PaymentFailedException $e) { DB::rollBack(); throw $e; } // Nested transactions use savepoints DB::transaction(function () { User::create(['email' => 'outer@test.com']); DB::transaction(function () { // This creates a savepoint Profile::create(['user_id' => 1]); }); // Inner failure only rolls back to savepoint }); ``` Os entrevistadores frequentemente perguntam em seguida sobre deadlocks. A resposta: o Laravel tenta novamente as transações que falham devido a deadlocks (configurável através do segundo argumento de `DB::transaction()`). ### Explique os Middleware e Forneça um Caso de Uso Real Os [Middleware](/technologies/laravel/interview-questions/middleware) filtram as requisições HTTP que entram na aplicação. Cada middleware pode inspecionar, modificar ou rejeitar requisições antes que cheguem aos controllers. ```php // app/Http/Middleware/EnsureTeamMember.php // Custom middleware checking team membership namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class EnsureTeamMember { public function handle(Request $request, Closure $next, string $role = 'member'): Response { $team = $request->route('team'); if (!$request->user()->belongsToTeam($team)) { abort(403, 'You are not a member of this team.'); } if ($role === 'admin' && !$request->user()->isTeamAdmin($team)) { abort(403, 'Admin access required.'); } return $next($request); } } ``` ```php // routes/web.php // Applying middleware to routes Route::middleware(['auth', 'team.member:admin'])->group(function () { Route::get('/teams/{team}/settings', [TeamController::class, 'settings']); Route::put('/teams/{team}/settings', [TeamController::class, 'updateSettings']); }); ``` Os middleware são executados em ordem. O middleware de autenticação deve ser executado antes do middleware de autorização, e o middleware de logging tipicamente envolve tudo. ## Resolvendo o Problema de Consultas N+1 O problema N+1 gera uma consulta para a coleção inicial mais uma consulta por item ao acessar os relacionamentos. Uma lista de 100 artigos com autores produz 101 consultas em vez de 2. ```php // Problem: 101 queries for 100 articles $articles = Article::all(); foreach ($articles as $article) { echo $article->author->name; // Each access triggers a query } // Solution: eager load with 2 queries total $articles = Article::with('author')->get(); foreach ($articles as $article) { echo $article->author->name; // No additional queries } // Nested eager loading for complex relationships $articles = Article::with([ 'author.profile', 'comments' => fn($query) => $query->latest()->limit(5), 'comments.user', 'tags', ])->get(); ``` O Laravel pode [prevenir o lazy loading](/technologies/laravel/interview-questions/database-migrations) em desenvolvimento para detectar problemas N+1 precocemente: ```php // app/Providers/AppServiceProvider.php use Illuminate\Database\Eloquent\Model; public function boot(): void { Model::preventLazyLoading(!$this->app->isProduction()); } ``` Com esta configuração, acessar um relacionamento não carregado lança uma exceção em desenvolvimento, forçando um eager loading explícito. ## Classes Action para Operações de Propósito Único As classes Action encapsulam operações únicas que podem ser invocadas de múltiplos pontos de entrada. Diferentemente das classes de serviço que agrupam métodos relacionados, as actions lidam com uma única tarefa com entradas e saídas claras. ```php // app/Actions/CreateUserAction.php // Single-purpose action class namespace App\Actions; use App\Models\User; use App\Notifications\WelcomeNotification; use Illuminate\Support\Facades\Hash; class CreateUserAction { public function execute(array $data): User { $user = User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); $user->notify(new WelcomeNotification()); return $user; } } ``` ```php // Usage in controller public function store(RegisterRequest $request, CreateUserAction $action) { $user = $action->execute($request->validated()); return redirect()->route('dashboard'); } // Usage in command public function handle(CreateUserAction $action) { $user = $action->execute([ 'name' => $this->argument('name'), 'email' => $this->argument('email'), 'password' => $this->argument('password'), ]); $this->info("Created user: {$user->id}"); } // Usage in test public function test_user_creation(): void { $action = new CreateUserAction(); $user = $action->execute([ 'name' => 'Test User', 'email' => 'test@example.com', 'password' => 'password', ]); $this->assertDatabaseHas('users', ['email' => 'test@example.com']); } ``` As classes Action funcionam bem com o [sistema de jobs](/technologies/laravel/interview-questions/queues-jobs) do Laravel: a action contém a lógica, e o job gerencia o enfileiramento e o comportamento de retry. ## Arquitetura Orientada a Eventos com Events e Listeners Os eventos desacoplam o momento em que algo acontece das reações a esse evento. Quando um pedido é realizado, o evento `OrderPlaced` é disparado. Os listeners cuidam do envio de emails, atualização de analytics e notificação de armazéns independentemente. ```php // app/Events/OrderPlaced.php // Event class carrying order data namespace App\Events; use App\Models\Order; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class OrderPlaced { use Dispatchable, InteractsWithSockets, SerializesModels; public function __construct( public Order $order ) {} } ``` ```php // app/Listeners/SendOrderConfirmation.php // Queued listener for email namespace App\Listeners; use App\Events\OrderPlaced; use App\Notifications\OrderConfirmationNotification; use Illuminate\Contracts\Queue\ShouldQueue; class SendOrderConfirmation implements ShouldQueue { public function handle(OrderPlaced $event): void { $event->order->user->notify( new OrderConfirmationNotification($event->order) ); } } ``` ```php // app/Listeners/UpdateInventoryAnalytics.php // Another listener for the same event namespace App\Listeners; use App\Events\OrderPlaced; use App\Services\AnalyticsService; use Illuminate\Contracts\Queue\ShouldQueue; class UpdateInventoryAnalytics implements ShouldQueue { public function __construct( private AnalyticsService $analytics ) {} public function handle(OrderPlaced $event): void { foreach ($event->order->items as $item) { $this->analytics->recordSale( $item->product_id, $item->quantity, $event->order->created_at ); } } } ``` ```php // Dispatching the event OrderPlaced::dispatch($order); // Or using the event helper event(new OrderPlaced($order)); ``` Os listeners que implementam `ShouldQueue` são executados de forma assíncrona, evitando que operações lentas bloqueiem a resposta HTTP. ## Pontos Chave para Desenvolvedores Laravel - As classes de serviço extraem a lógica de negócio dos controllers, melhorando a testabilidade e permitindo reutilização através de contextos HTTP, CLI e de fila - O padrão Repository agrega valor quando as aplicações precisam de cache, abstração de fonte de dados ou encapsulação de consultas complexas, mas cria sobrecarga para CRUD simples - Os filtros do Telescope reduzem o ruído em produção ao registrar apenas exceções, consultas lentas e operações com falha - O Service Container gerencia a injeção de dependências automaticamente através de type hints, com bindings explícitos para interfaces e configurações complexas - Os problemas N+1 desaparecem com eager loading via `with()`, e `Model::preventLazyLoading()` detecta eager loads ausentes durante o desenvolvimento - As classes Action lidam com operações de propósito único invocáveis de controllers, comandos, testes e jobs - Os eventos desacoplam "o que aconteceu" de "o que deveria acontecer em seguida", com listeners em fila gerenciando os efeitos colaterais de forma assíncrona - As respostas em entrevistas devem demonstrar compreensão dos trade-offs: quando os padrões ajudam versus quando adicionam complexidade desnecessária --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/laravel/laravel-solutions-advanced-patterns-debugging-interview