# 📚 Material de Estudo Completo: PHP 8 e Laravel
## Estilo Banca IDECAN — Concursos Públicos
---
> **Observação:** A banca IDECAN costuma cobrar conceitos teóricos, sintaxe, boas práticas, recursos novos de versão, e diferenças entre versões. Este material cobre os tópicos mais recorrentes com questões no estilo da banca.
---
## SUMÁRIO
1. [PHP 8 — Novidades e Recursos](#1-php-8--novidades-e-recursos)
2. [Tipos e Declarações de Tipo](#2-tipos-e-declarações-de-tipo)
3. [Orientação a Objetos em PHP 8](#3-orientação-a-objetos-em-php-8)
4. [Tratamento de Erros e Exceções](#4-tratamento-de-erros-e-exceções)
5. [PHP 8.1 e 8.2 — Principais Adições](#5-php-81-e-82--principais-adições)
6. [Laravel — Fundamentos](#6-laravel--fundamentos)
7. [Eloquent ORM](#7-eloquent-orm)
8. [Rotas, Controllers e Middleware](#8-rotas-controllers-e-middleware)
9. [Blade Template Engine](#9-blade-template-engine)
10. [Migrations, Seeders e Factories](#10-migrations-seeders-e-factories)
11. [Autenticação e Autorização](#11-autenticação-e-autorização)
12. [Artisan CLI](#12-artisan-cli)
13. [Questões no Estilo IDECAN com Gabarito](#13-questões-no-estilo-idecan-com-gabarito)
---
## 1. PHP 8 — Novidades e Recursos
### 1.1 JIT Compiler (Just In Time)
O PHP 8 introduziu o **compilador JIT**, que converte código PHP em código de máquina nativo em tempo de execução, melhorando o desempenho em operações computacionalmente intensivas.
- O JIT é habilitado via `opcache.jit` no `php.ini`
- Dois modos principais: **Tracing JIT** e **Function JIT**
- Maior ganho em aplicações CPU-bound (processamento numérico)
```ini
; php.ini
opcache.enable=1
opcache.jit_buffer_size=100M
opcache.jit=tracing
```
---
### 1.2 Named Arguments (Argumentos Nomeados)
Permitem passar argumentos para funções usando o **nome do parâmetro**, independente da ordem.
```php
// PHP 8+
function criarUsuario(string $nome, int $idade, string $email) { ... }
criarUsuario(
email: 'joao@email.com',
nome: 'João',
idade: 30
);
```
**Vantagens:**
- Código mais legível
- Possibilidade de pular parâmetros opcionais
---
### 1.3 Match Expression
Substitui o `switch` com sintaxe mais limpa, sem necessidade de `break` e com comparação estrita (`===`).
```php
$status = 2;
$resultado = match($status) {
1 => 'Ativo',
2, 3 => 'Pendente',
4 => 'Inativo',
default => 'Desconhecido',
};
echo $resultado; // Pendente
```
**Diferenças do `switch`:**
| Característica | `switch` | `match` |
|---|---|---|
| Comparação | Fraca (`==`) | Estrita (`===`) |
| `break` | Necessário | Desnecessário |
| Retorna valor | Não | Sim |
| Fall-through | Sim | Não |
---
### 1.4 Nullsafe Operator (`?->`)
Permite encadear chamadas de métodos/propriedades sem verificar `null` a cada passo.
```php
// Antes do PHP 8
$cidade = null;
if ($user !== null) {
if ($user->getAddress() !== null) {
$cidade = $user->getAddress()->getCity();
}
}
// PHP 8 com Nullsafe
$cidade = $user?->getAddress()?->getCity();
```
---
### 1.5 Union Types
Permite declarar que um parâmetro ou retorno aceita **múltiplos tipos**.
```php
function processar(int|string $valor): int|float {
return is_string($valor) ? strlen($valor) : $valor * 1.5;
}
```
---
### 1.6 Attributes (Anotações Nativas)
PHP 8 substituiu DocBlocks por **Attributes nativos** para metadados.
```php
#[Attribute]
class Route {
public function __construct(public string $path) {}
}
#[Route('/home')]
class HomeController {
// ...
}
```
---
### 1.7 Constructor Property Promotion
Elimina código boilerplate ao declarar e inicializar propriedades no construtor.
```php
// Antes do PHP 8
class Produto {
public string $nome;
public float $preco;
public function __construct(string $nome, float $preco) {
$this->nome = $nome;
$this->preco = $preco;
}
}
// PHP 8 — Constructor Promotion
class Produto {
public function __construct(
public string $nome,
public float $preco,
private int $estoque = 0
) {}
}
```
---
### 1.8 Fibers (PHP 8.1)
Mecanismo de concorrência cooperativa (corrotinas) para execução assíncrona.
```php
$fiber = new Fiber(function (): void {
$valor = Fiber::suspend('fiber');
echo "Valor recebido: " . $valor . "\n";
});
$value = $fiber->start();
echo $value . "\n"; // fiber
$fiber->resume('hello');
```
---
## 2. Tipos e Declarações de Tipo
### 2.1 Tipos Escalares
`int`, `float`, `string`, `bool`
### 2.2 Tipos Compostos
- `array`, `callable`, `iterable`
- Union Types: `int|string`
- Intersection Types (PHP 8.1): `Countable&Iterator`
### 2.3 Tipos Especiais
- `void` — função não retorna valor
- `never` (PHP 8.1) — função nunca retorna (lança exceção ou chama `exit`)
- `mixed` — qualquer tipo
- `static` — retorna instância da classe atual
### 2.4 Nullable Types
```php
function buscar(?int $id): ?string {
if ($id === null) return null;
return "Item $id";
}
```
---
## 3. Orientação a Objetos em PHP 8
### 3.1 Classes Abstratas vs Interfaces
| Característica | Classe Abstrata | Interface |
|---|---|---|
| Instanciamento direto | Não | Não |
| Pode ter implementação | Sim | Não (só assinaturas) |
| Herança múltipla | Não | Sim (múltiplas interfaces) |
| Visibilidade dos métodos | Qualquer | Sempre `public` |
| Constantes | Sim | Sim |
### 3.2 Traits
Mecanismo para reutilização de código em múltiplas classes.
```php
trait Auditavel {
public function log(string $msg): void {
echo "[LOG] $msg\n";
}
}
class Pedido {
use Auditavel;
}
$pedido = new Pedido();
$pedido->log('Pedido criado');
```
### 3.3 Enums (PHP 8.1)
```php
enum Status {
case Ativo;
case Inativo;
case Pendente;
}
enum Cor: string {
case Vermelho = 'red';
case Azul = 'blue';
}
echo Cor::Vermelho->value; // red
```
### 3.4 Readonly Properties (PHP 8.1)
```php
class Usuario {
public readonly string $nome;
public function __construct(string $nome) {
$this->nome = $nome; // Só pode ser atribuído uma vez
}
}
$u = new Usuario('João');
$u->nome = 'Maria'; // ERRO! Propriedade readonly
```
---
## 4. Tratamento de Erros e Exceções
### 4.1 Hierarquia de Erros
```
Throwable
├── Error
│ ├── TypeError
│ ├── ValueError
│ ├── ArithmeticError
│ └── ParseError
└── Exception
├── RuntimeException
├── InvalidArgumentException
├── LogicException
└── ...
```
### 4.2 Try-Catch-Finally
```php
try {
$resultado = dividir(10, 0);
} catch (DivisionByZeroError $e) {
echo "Divisão por zero: " . $e->getMessage();
} catch (TypeError $e) {
echo "Tipo errado: " . $e->getMessage();
} finally {
echo "Sempre executado";
}
```
### 4.3 Captura múltipla (PHP 8)
```php
catch (InvalidArgumentException | RuntimeException $e) {
// Trata ambas as exceções
}
```
---
## 5. PHP 8.1 e 8.2 — Principais Adições
### PHP 8.1
- **Enums** (puros e backed)
- **Readonly Properties**
- **Fibers**
- **Intersection Types** (`A&B`)
- **never** return type
- **array_is_list()** — verifica se array é lista
- **Constantes em interfaces** e traits
### PHP 8.2
- **Readonly Classes** — todas as propriedades são readonly
- **DNF Types** (Disjunctive Normal Form): `(A&B)|null`
- **Constantes em traits**
- Depreciação de propriedades dinâmicas (sem declaração)
```php
// PHP 8.2 - Readonly Class
readonly class Ponto {
public function __construct(
public float $x,
public float $y,
) {}
}
```
---
## 6. Laravel — Fundamentos
### 6.1 O que é Laravel?
Laravel é um **framework PHP** de código aberto que segue o padrão **MVC (Model-View-Controller)** e utiliza diversas convenções para facilitar o desenvolvimento web.
**Principais Características:**
- Eloquent ORM
- Blade Template Engine
- Artisan CLI
- Sistema de Migrations
- Autenticação integrada
- Sistema de Filas (Queues)
- Eventos e Listeners
- Service Container (IoC)
- Facades
### 6.2 Ciclo de Requisição no Laravel
```
Request HTTP
→ index.php
→ Kernel HTTP (bootstrap)
→ Middleware (pipeline)
→ Router
→ Controller
→ Response
```
### 6.3 Service Container e Service Provider
**Service Container:** Motor de injeção de dependências do Laravel.
```php
// Registrar binding
app()->bind(PagamentoInterface::class, PagamentoPix::class);
// Resolver
$pagamento = app(PagamentoInterface::class);
```
**Service Provider:** Classe responsável por registrar serviços no container.
```php
class AppServiceProvider extends ServiceProvider {
public function register(): void {
$this->app->bind(PagamentoInterface::class, PagamentoPix::class);
}
public function boot(): void {
// Após todos os providers registrados
}
}
```
### 6.4 Facades
Fornecem interface estática para classes no Service Container.
```php
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
Cache::put('chave', 'valor', 3600);
DB::table('usuarios')->get();
Log::info('Usuário autenticado');
```
---
## 7. Eloquent ORM
### 7.1 Definindo um Model
```php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Produto extends Model {
protected $table = 'produtos'; // opcional se seguir convenção
protected $primaryKey = 'id';
public $timestamps = true;
protected $fillable = ['nome', 'preco', 'descricao'];
protected $hidden = ['senha'];
protected $casts = [
'preco' => 'float',
'ativo' => 'boolean',
'criado_em' => 'datetime',
];
}
```
### 7.2 Operações CRUD
```php
// Criar
$produto = Produto::create(['nome' => 'Caneta', 'preco' => 2.50]);
// ou
$produto = new Produto();
$produto->nome = 'Caneta';
$produto->save();
// Ler
$produtos = Produto::all();
$produto = Produto::find(1);
$produto = Produto::findOrFail(1); // lança ModelNotFoundException
$produto = Produto::where('preco', '>', 10)->first();
// Atualizar
$produto->preco = 3.00;
$produto->save();
// ou
Produto::where('id', 1)->update(['preco' => 3.00]);
// Deletar
$produto->delete();
Produto::destroy(1);
Produto::destroy([1, 2, 3]);
```
### 7.3 Query Builder
```php
DB::table('produtos')
->select('nome', 'preco')
->where('ativo', true)
->whereIn('categoria_id', [1, 2, 3])
->orderBy('preco', 'desc')
->limit(10)
->get();
```
### 7.4 Relacionamentos Eloquent
```php
// Um para Um (hasOne)
class Usuario extends Model {
public function perfil(): HasOne {
return $this->hasOne(Perfil::class);
}
}
// Um para Muitos (hasMany)
class Categoria extends Model {
public function produtos(): HasMany {
return $this->hasMany(Produto::class);
}
}
// Muitos para Muitos (belongsToMany)
class Produto extends Model {
public function tags(): BelongsToMany {
return $this->belongsToMany(Tag::class);
}
}
// Pertence a (belongsTo)
class Produto extends Model {
public function categoria(): BelongsTo {
return $this->belongsTo(Categoria::class);
}
}
```
### 7.5 Eager Loading (Evita N+1)
```php
// N+1 Problem (ruim)
$produtos = Produto::all();
foreach ($produtos as $produto) {
echo $produto->categoria->nome; // Query por produto!
}
// Eager Loading (correto)
$produtos = Produto::with('categoria')->get();
$produtos = Produto::with(['categoria', 'tags'])->get();
// Lazy Eager Loading
$produtos->load('categoria');
```
### 7.6 Scopes
```php
class Produto extends Model {
// Local scope
public function scopeAtivo(Builder $query): Builder {
return $query->where('ativo', true);
}
public function scopePrecoMinimo(Builder $query, float $preco): Builder {
return $query->where('preco', '>=', $preco);
}
}
// Uso
$produtos = Produto::ativo()->precoMinimo(10)->get();
```
### 7.7 Soft Delete
```php
use Illuminate\Database\Eloquent\SoftDeletes;
class Produto extends Model {
use SoftDeletes;
}
$produto->delete(); // Marca deleted_at, não remove
$produto->forceDelete(); // Remove fisicamente
Produto::withTrashed()->get(); // Inclui deletados
Produto::onlyTrashed()->get(); // Só deletados
$produto->restore(); // Restaura
```
---
## 8. Rotas, Controllers e Middleware
### 8.1 Rotas
```php
// routes/web.php
Route::get('/produtos', [ProdutoController::class, 'index']);
Route::post('/produtos', [ProdutoController::class, 'store']);
Route::get('/produtos/{id}', [ProdutoController::class, 'show']);
Route::put('/produtos/{id}', [ProdutoController::class, 'update']);
Route::delete('/produtos/{id}', [ProdutoController::class, 'destroy']);
// Resource (gera todas as rotas CRUD)
Route::resource('produtos', ProdutoController::class);
// API Resource (sem create e edit)
Route::apiResource('produtos', ProdutoController::class);
// Agrupamento
Route::prefix('admin')->middleware('auth')->group(function () {
Route::get('/dashboard', [AdminController::class, 'index']);
});
// Nome da rota
Route::get('/home', [HomeController::class, 'index'])->name('home');
// Uso: route('home')
```
### 8.2 Controllers
```php
namespace App\Http\Controllers;
use App\Models\Produto;
use Illuminate\Http\Request;
class ProdutoController extends Controller {
public function index() {
$produtos = Produto::paginate(15);
return view('produtos.index', compact('produtos'));
}
public function store(Request $request) {
$dados = $request->validate([
'nome' => 'required|string|max:255',
'preco' => 'required|numeric|min:0',
]);
$produto = Produto::create($dados);
return redirect()->route('produtos.index')->with('sucesso', 'Produto criado!');
}
}
```
### 8.3 Middleware
```php
// Criar middleware
php artisan make:middleware VerificarIdade
// App\Http\Middleware\VerificarIdade
public function handle(Request $request, Closure $next): Response {
if ($request->user()->idade < 18) {
return redirect('acesso-negado');
}
return $next($request);
}
// Registrar em app/Http/Kernel.php
protected $routeMiddleware = [
'idade' => \App\Http\Middleware\VerificarIdade::class,
];
// Uso na rota
Route::get('/adultos', ...)->middleware('idade');
```
### 8.4 Form Request (Validação)
```php
// php artisan make:request StoreProdutoRequest
class StoreProdutoRequest extends FormRequest {
public function authorize(): bool {
return true; // ou lógica de autorização
}
public function rules(): array {
return [
'nome' => 'required|string|max:255',
'preco' => 'required|numeric|min:0',
'email' => 'required|email|unique:usuarios,email',
'status' => 'in:ativo,inativo',
];
}
public function messages(): array {
return [
'nome.required' => 'O nome é obrigatório.',
];
}
}
```
---
## 9. Blade Template Engine
### 9.1 Sintaxe Básica
```blade
{{-- Comentário Blade --}}
{{-- Exibir variável (escapa HTML) --}}
{{ $nome }}
{{-- Exibir sem escape (perigoso!) --}}
{!! $htmlBruto !!}
{{-- Estruturas de controle --}}
@if($logado)
Bem-vindo, {{ $usuario->nome }}!
@elseif($visitante)
Por favor, faça login.
@else
Acesso restrito.
@endif
@foreach($produtos as $produto)
<li>{{ $produto->nome }} - R$ {{ $produto->preco }}</li>
@endforeach
@forelse($itens as $item)
<li>{{ $item->nome }}</li>
@empty
<p>Nenhum item encontrado.</p>
@endforelse
@for($i = 0; $i < 10; $i++)
<p>{{ $i }}</p>
@endfor
@while($condicao)
...
@endwhile
```
### 9.2 Layouts
```blade
{{-- resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html>
<head>
<title>@yield('titulo', 'Padrão')</title>
</head>
<body>
@include('partials.header')
<main>
@yield('conteudo')
</main>
@stack('scripts')
</body>
</html>
{{-- resources/views/produtos/index.blade.php --}}
@extends('layouts.app')
@section('titulo', 'Lista de Produtos')
@section('conteudo')
<h1>Produtos</h1>
@foreach($produtos as $produto)
<p>{{ $produto->nome }}</p>
@endforeach
@endsection
@push('scripts')
<script src="produto.js"></script>
@endpush
```
### 9.3 Componentes Blade (Laravel 7+)
```php
// php artisan make:component Alerta
// App\View\Components\Alerta.php
class Alerta extends Component {
public function __construct(public string $tipo = 'info') {}
public function render(): View { return view('components.alerta'); }
}
```
```blade
{{-- resources/views/components/alerta.blade.php --}}
<div class="alerta alerta-{{ $tipo }}">
{{ $slot }}
</div>
{{-- Uso --}}
<x-alerta tipo="erro">
Ocorreu um erro!
</x-alerta>
```
---
## 10. Migrations, Seeders e Factories
### 10.1 Migrations
```php
// php artisan make:migration create_produtos_table
public function up(): void {
Schema::create('produtos', function (Blueprint $table) {
$table->id(); // bigIncrements('id')
$table->string('nome', 255);
$table->text('descricao')->nullable();
$table->decimal('preco', 8, 2);
$table->boolean('ativo')->default(true);
$table->foreignId('categoria_id')->constrained()->cascadeOnDelete();
$table->timestamps(); // created_at e updated_at
$table->softDeletes(); // deleted_at
});
}
public function down(): void {
Schema::dropIfExists('produtos');
}
```
**Comandos Artisan:**
```bash
php artisan migrate # Executa migrations pendentes
php artisan migrate:rollback # Reverte último batch
php artisan migrate:fresh # Drop + migrate
php artisan migrate:reset # Rollback de todas
php artisan migrate:status # Status das migrations
```
### 10.2 Seeders
```php
// php artisan make:seeder ProdutoSeeder
class ProdutoSeeder extends Seeder {
public function run(): void {
Produto::factory()->count(50)->create();
Produto::create([
'nome' => 'Produto Especial',
'preco' => 99.99,
]);
}
}
// DatabaseSeeder
class DatabaseSeeder extends Seeder {
public function run(): void {
$this->call([
CategoriaSeeder::class,
ProdutoSeeder::class,
]);
}
}
```
```bash
php artisan db:seed
php artisan db:seed --class=ProdutoSeeder
php artisan migrate:fresh --seed
```
### 10.3 Factories
```php
// php artisan make:factory ProdutoFactory
class ProdutoFactory extends Factory {
public function definition(): array {
return [
'nome' => fake()->words(3, true),
'descricao' => fake()->paragraph(),
'preco' => fake()->randomFloat(2, 1, 999),
'ativo' => fake()->boolean(80), // 80% true
'categoria_id' => Categoria::factory(),
];
}
// Estado personalizado
public function inativo(): static {
return $this->state(['ativo' => false]);
}
}
// Uso
Produto::factory()->create();
Produto::factory()->count(10)->create();
Produto::factory()->inativo()->create();
```
---
## 11. Autenticação e Autorização
### 11.1 Autenticação
Laravel oferece pacotes de autenticação prontos:
- **Breeze** — simples, Blade
- **Jetstream** — avançado, Livewire ou Inertia
- **Fortify** — backend headless
```php
// Autenticação manual
if (Auth::attempt(['email' => $email, 'password' => $senha])) {
return redirect('/dashboard');
}
Auth::login($usuario);
Auth::logout();
$usuario = Auth::user();
Auth::id(); // ID do usuário autenticado
Auth::check(); // bool
Auth::guest(); // !check()
```
### 11.2 Autorização — Gates
```php
// AppServiceProvider
Gate::define('editar-produto', function (User $user, Produto $produto) {
return $user->id === $produto->user_id;
});
// Uso
Gate::allows('editar-produto', $produto);
Gate::denies('editar-produto', $produto);
$this->authorize('editar-produto', $produto); // Controller
```
### 11.3 Autorização — Policies
```php
// php artisan make:policy ProdutoPolicy --model=Produto
class ProdutoPolicy {
public function update(User $user, Produto $produto): bool {
return $user->id === $produto->user_id;
}
public function delete(User $user, Produto $produto): bool {
return $user->isAdmin() || $user->id === $produto->user_id;
}
}
// Controller
$this->authorize('update', $produto);
// Blade
@can('update', $produto)
<button>Editar</button>
@endcan
@cannot('delete', $produto)
<p>Sem permissão</p>
@endcannot
```
---
## 12. Artisan CLI
### 12.1 Comandos Mais Cobrados
```bash
# Gerar arquivos
php artisan make:model Produto -mcrf # Model, Migration, Controller, Factory, Resource
php artisan make:controller ProdutoController --resource
php artisan make:middleware Autenticar
php artisan make:request StoreProdutoRequest
php artisan make:seeder ProdutoSeeder
php artisan make:factory ProdutoFactory
php artisan make:policy ProdutoPolicy
php artisan make:command EnviarRelatorio
php artisan make:event PedidoCriado
php artisan make:listener EnviarEmailPedido
php artisan make:job ProcessarPagamento
php artisan make:mail BoasVindas
php artisan make:notification PedidoAprovado
# Manutenção
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
php artisan optimize # Combina cache
php artisan optimize:clear
# Informação
php artisan route:list
php artisan tinker # REPL interativo
php artisan about # Info do ambiente
# Filas
php artisan queue:work
php artisan queue:listen
php artisan queue:failed
php artisan queue:retry all
```
---
## 13. Questões no Estilo IDECAN com Gabarito
---
### 📋 BLOCO 1 — PHP 8 GERAL
---
**Questão 1**
Sobre o PHP 8, assinale a alternativa CORRETA a respeito do operador `?->` (nullsafe operator):
**A)** Lança uma exceção `NullPointerException` quando a variável é nula.
**B)** Permite encadear chamadas de métodos retornando `null` caso algum elemento da cadeia seja nulo.
**C)** Converte automaticamente `null` para `false` antes de avaliar a expressão.
**D)** Funciona apenas em propriedades, não em chamadas de métodos.
**E)** É equivalente ao operador `??` (null coalescing), retornando sempre um valor padrão.
**✅ Gabarito: B**
*Justificativa:* O operador `?->` retorna `null` imediatamente se qualquer elemento da cadeia for nulo, sem lançar exceção.
---
**Questão 2**
Analise o código PHP 8 a seguir:
```php
$valor = 5;
$resultado = match($valor) {
1, 2 => 'Baixo',
3, 4, 5 => 'Médio',
6, 7 => 'Alto',
};
echo $resultado;
```
O código produzirá como saída:
**A)** Baixo
**B)** Alto
**C)** Médio
**D)** Erro de sintaxe
**E)** Null
**✅ Gabarito: C**
---
**Questão 3**
Assinale a alternativa que apresenta uma característica EXCLUSIVA do `match` em relação ao `switch` no PHP 8:
**A)** O `match` permite usar `break` para sair de um caso.
**B)** O `match` realiza comparação estrita (===), enquanto o `switch` usa comparação fraca (==).
**C)** O `match` não precisa de expressão de comparação, funcionando como uma série de `if`.
**D)** O `match` aceita apenas valores inteiros como casos.
**E)** O `match` executa todos os casos correspondentes (fall-through automático).
**✅ Gabarito: B**
---
**Questão 4**
Sobre o Constructor Property Promotion no PHP 8, considere:
```php
class Funcionario {
public function __construct(
public readonly string $nome,
private int $salario,
protected string $cargo = 'Analista'
) {}
}
```
É CORRETO afirmar que:
**A)** O código contém erro de sintaxe pois `readonly` não pode ser usado em constructor promotion.
**B)** A propriedade `$nome` não pode ter seu valor alterado após a criação do objeto.
**C)** O modificador `protected` em `$cargo` causará erro de execução.
**D)** O valor padrão `'Analista'` é ignorado pelo PHP ao usar promotion.
**E)** A propriedade `$salario` será automaticamente declarada como `public`.
**✅ Gabarito: B**
*Justificativa:* `readonly` impede que a propriedade seja modificada após a inicialização.
---
**Questão 5**
Em relação aos **Named Arguments** do PHP 8, qual das seguintes afirmações é INCORRETA?
**A)** Permitem passar argumentos em qualquer ordem, usando o nome do parâmetro.
**B)** Podem ser combinados com argumentos posicionais, desde que os posicionais venham primeiro.
**C)** Permitem omitir parâmetros opcionais intermediários.
**D)** Funcionam com funções nativas do PHP.
**E)** São obrigatórios quando a função possui mais de 3 parâmetros.
**✅ Gabarito: E**
*Justificativa:* Named Arguments são opcionais e podem ser usados em qualquer função, independente do número de parâmetros.
---
### 📋 BLOCO 2 — ORIENTAÇÃO A OBJETOS
---
**Questão 6**
Sobre **Traits** em PHP, assinale a alternativa CORRETA:
**A)** Uma classe pode usar apenas um Trait por vez.
**B)** Traits podem ser instanciados diretamente com `new`.
**C)** Traits permitem reutilização de código em múltiplas classes sem necessidade de herança.
**D)** Traits não podem conter propriedades, apenas métodos.
**E)** O uso de Trait substitui completamente a necessidade de interfaces.
**✅ Gabarito: C**
---
**Questão 7**
Os **Enums** do PHP 8.1 permitem dois tipos: puro e backed. Sobre Backed Enums, é CORRETO afirmar que:
**A)** Só aceitam valores do tipo `int`.
**B)** Aceitam valores `string` ou `int` associados a cada caso.
**C)** Não implementam a interface `UnitEnum`.
**D)** Não podem ter métodos definidos.
**E)** São equivalentes às constantes de classe.
**✅ Gabarito: B**
*Justificativa:* Backed Enums associam `string` ou `int` a cada caso. Ex: `enum Status: string { case Ativo = 'ativo'; }`
---
**Questão 8**
Considere o código:
```php
interface Pagavel {
public function pagar(float $valor): bool;
}
abstract class FormaPagamento implements Pagavel {
abstract public function validar(): bool;
public function processar(float $valor): string {
if ($this->validar()) {
$this->pagar($valor);
return 'Pago';
}
return 'Falhou';
}
}
```
Assinale a alternativa CORRETA sobre o código acima:
**A)** Ocorrerá erro pois classes abstratas não podem implementar interfaces.
**B)** A classe `FormaPagamento` não precisa implementar o método `pagar()` pois é abstrata.
**C)** O método `processar()` não pode chamar `pagar()` pois este não está implementado na classe abstrata.
**D)** Ocorrerá erro pois `abstract` e `implements` não podem ser usados simultaneamente.
**E)** A interface `Pagavel` precisaria ser abstrata para funcionar com `FormaPagamento`.
**✅ Gabarito: B**
*Justificativa:* Classes abstratas podem deixar a implementação dos métodos de interfaces para suas subclasses concretas.
---
### 📋 BLOCO 3 — LARAVEL FUNDAMENTOS
---
**Questão 9**
No Laravel, o padrão arquitetural adotado é o MVC. Sobre os componentes deste padrão no contexto do Laravel, assinale a alternativa CORRETA:
**A)** O Model é responsável por definir as rotas da aplicação.
**B)** A View contém a lógica de negócio e acesso ao banco de dados.
**C)** O Controller recebe as requisições, interage com o Model e retorna a View.
**D)** O Eloquent ORM faz parte exclusivamente da camada View.
**E)** As migrations são componentes da camada Controller.
**✅ Gabarito: C**
---
**Questão 10**
Sobre o **Service Container** do Laravel, analise as afirmações:
I. O Service Container é responsável pelo gerenciamento de dependências e injeção de dependências.
II. `app()->bind()` registra uma binding singleton que retorna sempre a mesma instância.
III. `app()->singleton()` garante que a mesma instância seja retornada a cada resolução.
IV. O Service Container resolve automaticamente dependências tipadas nos construtores dos Controllers.
Estão CORRETAS:
**A)** I e II apenas
**B)** I, III e IV apenas
**C)** II e IV apenas
**D)** Todas estão corretas
**E)** I e IV apenas
**✅ Gabarito: B**
*Justificativa:* `bind()` cria nova instância a cada resolução; `singleton()` retorna sempre a mesma instância. A afirmação II está errada pois descreve `singleton()`, não `bind()`.
---
**Questão 11**
Em relação às **Facades** do Laravel, é CORRETO afirmar que:
**A)** Facades são classes que implementam o padrão Singleton diretamente.
**B)** Facades fornecem uma interface estática para serviços registrados no Service Container.
**C)** O uso de Facades é obrigatório no Laravel, substituindo a injeção de dependências.
**D)** Facades não podem ser testadas unitariamente.
**E)** Facades acessam diretamente o banco de dados sem passar pelo Eloquent.
**✅ Gabarito: B**
---
### 📋 BLOCO 4 — ELOQUENT E BANCO DE DADOS
---
**Questão 12**
Sobre o **problema N+1** no Eloquent ORM, analise o código:
```php
$posts = Post::all();
foreach ($posts as $post) {
echo $post->autor->nome;
}
```
Qual alternativa descreve corretamente o problema e a solução?
**A)** O código é eficiente; não há problema.
**B)** Executa 1 query para `Post::all()` e 1 adicional por post para buscar o autor. A solução é usar `Post::with('autor')->get()`.
**C)** O código executa apenas 2 queries independentemente do número de posts.
**D)** O problema é resolvido usando `Post::join('autores')->get()`.
**E)** O `foreach` causa o problema N+1; a solução é substituí-lo por `each()`.
**✅ Gabarito: B**
---
**Questão 13**
Sobre o **Soft Delete** no Eloquent, assinale a alternativa CORRETA:
**A)** O Soft Delete remove fisicamente o registro, mas mantém um backup em tabela separada.
**B)** Ao usar a trait `SoftDeletes`, o método `delete()` preenche o campo `deleted_at` com a data atual.
**C)** Registros com Soft Delete são sempre incluídos nas consultas normais do Eloquent.
**D)** O método `forceDelete()` restaura um registro previamente deletado.
**E)** Para usar Soft Delete, é necessário substituir o campo `id` por `uuid`.
**✅ Gabarito: B**
---
**Questão 14**
Considere o seguinte relacionamento Eloquent:
```php
class Pedido extends Model {
public function itens() {
return $this->hasMany(ItemPedido::class);
}
}
```
Qual é o tipo de relacionamento definido e qual coluna de chave estrangeira o Eloquent irá procurar **por convenção** na tabela `item_pedidos`?
**A)** `belongsToMany` — procura `pedidos_id`
**B)** `hasOne` — procura `pedido_id`
**C)** `hasMany` — procura `pedido_id`
**D)** `hasMany` — procura `id_pedido`
**E)** `belongsTo` — procura `pedidos_id`
**✅ Gabarito: C**
*Justificativa:* `hasMany` define "um para muitos". Por convenção, o Eloquent busca `{nome_singular_do_model}_id`, ou seja, `pedido_id`.
---
### 📋 BLOCO 5 — ROTAS E CONTROLLERS
---
**Questão 15**
No Laravel, ao utilizar `Route::resource('fotos', FotoController::class)`, quais rotas são criadas automaticamente? Assinale a alternativa COMPLETA e CORRETA:
**A)** GET /fotos, POST /fotos, GET /fotos/{foto}, PUT /fotos/{foto}, DELETE /fotos/{foto}
**B)** GET /fotos, POST /fotos, GET /fotos/create, GET /fotos/{foto}, GET /fotos/{foto}/edit, PUT/PATCH /fotos/{foto}, DELETE /fotos/{foto}
**C)** Apenas GET e POST para /fotos
**D)** GET /fotos, POST /fotos, PUT /fotos, DELETE /fotos
**E)** As mesmas rotas do `apiResource`, porém com suporte a sessões.
**✅ Gabarito: B**
*Justificativa:* `Route::resource` cria 7 rotas: index, create, store, show, edit, update, destroy.
---
**Questão 16**
Sobre **Middleware** no Laravel, qual das seguintes afirmações é CORRETA?
**A)** Middleware só pode ser aplicado globalmente a toda a aplicação.
**B)** Middleware é executado antes e/ou depois da requisição chegar ao Controller.
**C)** Middleware não pode redirecionar o usuário, apenas modificar a requisição.
**D)** O método `handle()` do Middleware deve sempre retornar `true` ou `false`.
**E)** Middleware é registrado exclusivamente no arquivo `routes/web.php`.
**✅ Gabarito: B**
---
**Questão 17**
Sobre validação com **Form Requests** no Laravel, assinale a alternativa CORRETA:
**A)** O método `authorize()` realiza a validação dos campos do formulário.
**B)** O método `rules()` define as regras de validação; retornando `false` em `authorize()`, a requisição é bloqueada com HTTP 403.
**C)** Form Requests não podem personalizar mensagens de erro.
**D)** As regras de validação só funcionam com dados `POST`.
**E)** O Form Request ignora campos não listados em `rules()` e os passa ao Controller normalmente.
**✅ Gabarito: B**
---
### 📋 BLOCO 6 — BLADE E MIGRATIONS
---
**Questão 18**
No **Blade Template Engine** do Laravel, qual é a diferença entre `{{ $variavel }}` e `{!! $variavel !!}`?
**A)** Não há diferença; ambos produzem a mesma saída.
**B)** `{{ }}` executa PHP puro; `{!! !!}` exibe apenas strings.
**C)** `{{ }}` escapa caracteres HTML (XSS-safe); `{!! !!}` exibe o conteúdo sem escapar.
**D)** `{!! !!}` é mais eficiente em termos de desempenho.
**E)** `{{ }}` é usado para comentários; `{!! !!}` para variáveis.
**✅ Gabarito: C**
---
**Questão 19**
Sobre **Migrations** no Laravel, analise as afirmações:
I. O comando `php artisan migrate:rollback` desfaz apenas o último batch de migrations.
II. O comando `php artisan migrate:fresh` executa rollback de todas as migrations e as executa novamente.
III. O método `down()` é obrigatório e deve sempre ser o inverso do `up()`.
IV. Migrations permitem versionamento e controle de alterações no schema do banco de dados.
Estão CORRETAS:
**A)** I, II e IV apenas
**B)** I e III apenas
**C)** Todas estão corretas
**D)** II e IV apenas
**E)** I, II, III e IV
**✅ Gabarito: A**
*Justificativa:* O método `down()` não é tecnicamente obrigatório (a migration funcionará sem ele), embora seja boa prática. `migrate:fresh` dropa todas as tabelas e executa `migrate`, não faz rollback.
---
**Questão 20**
No contexto do Laravel, sobre **Seeders** e **Factories**, é CORRETO afirmar:
**A)** Factories são usadas exclusivamente em produção para popular dados reais.
**B)** Seeders são executados automaticamente em cada migration.
**C)** Factories geram dados falsos e consistentes para testes e desenvolvimento, usando a biblioteca Faker.
**D)** Um Seeder não pode chamar outros Seeders.
**E)** O comando `php artisan db:seed` executa apenas o `DatabaseSeeder` e não aceita a opção `--class`.
**✅ Gabarito: C**
---
### 📋 BLOCO 7 — AUTENTICAÇÃO E ARTISAN
---
**Questão 21**
No sistema de **autorização** do Laravel, qual é a diferença entre **Gates** e **Policies**?
**A)** Gates são usados para autenticação; Policies são usadas para autorização.
**B)** Gates são closures simples para verificar permissões gerais; Policies são classes organizadas por Model para lógica de autorização mais complexa.
**C)** Policies substituem completamente os Gates e devem ser sempre preferidas.
**D)** Gates funcionam apenas em Controllers; Policies funcionam apenas em Views Blade.
**E)** Gates precisam ser registrados em cada rota; Policies são globais.
**✅ Gabarito: B**
---
**Questão 22**
Sobre o **Artisan CLI** do Laravel, assinale a alternativa CORRETA:
**A)** O comando `php artisan tinker` executa todas as migrations pendentes.
**B)** O comando `php artisan make:model Produto -m` cria o Model e a Migration correspondente.
**C)** O comando `php artisan optimize` remove todos os caches da aplicação.
**D)** O `php artisan route:list` cria todas as rotas RESTful para um recurso.
**E)** O comando `php artisan serve` inicia o servidor em produção.
**✅ Gabarito: B**
*Justificativa:* A flag `-m` no `make:model` cria também a migration. `tinker` é um REPL; `optimize` gera cache (não remove); `route:list` lista as rotas (não cria); `serve` é apenas para desenvolvimento local.
---
**Questão 23 — QUESTÃO INTEGRADORA**
Um desenvolvedor precisa criar uma API RESTful no Laravel para gerenciar produtos. Analise as seguintes ações realizadas:
1. `php artisan make:model Produto -mcrf`
2. Definiu `protected $fillable = ['nome', 'preco']` no Model
3. Usou `Route::apiResource('produtos', ProdutoController::class)`
4. No controller, usou `Produto::with('categoria')->paginate(15)`
Sobre as ações acima, assinale a alternativa CORRETA:
**A)** A ação 1 cria Model, Migration, Controller, Factory e Request.
**B)** A ação 2 define quais campos são protegidos contra atribuição em massa (mass assignment).
**C)** A ação 3 cria 7 rotas, incluindo as rotas `create` e `edit`.
**D)** A ação 4 executará N+1 queries ao acessar a categoria de cada produto.
**E)** A ação 2 deveria usar `$guarded` para permitir atribuição em massa.
**✅ Gabarito: B**
*Justificativa:* `$fillable` define campos **permitidos** para mass assignment. A ação 1 cria Model, Migration, Controller, Resource e Factory (não Request). `apiResource` cria 5 rotas (sem create e edit). O `with('categoria')` resolve o N+1.
---
## 📌 RESUMO DAS REGRAS DE OURO — IDECAN
| Tema | Ponto-Chave |
|---|---|
| `match` vs `switch` | `match` usa `===`, retorna valor, sem `break` |
| Nullsafe `?->` | Retorna `null` se qualquer parte for nula |
| Union Types | `int\|string` — aceita múltiplos tipos |
| Readonly | Só pode ser atribuído uma vez (na inicialização) |
| Traits | Reutilização sem herança; classe pode usar vários |
| Enum (PHP 8.1) | Backed: tem valor `string`/`int`; Puro: só nome |
| Facades | Interface estática para o Service Container |
| `hasMany` | Chave estrangeira: `{modelo}_id` na tabela filha |
| Eager Loading | `with()` evita N+1 |
| Soft Delete | `delete()` → preenche `deleted_at`; `forceDelete()` → remove |
| `Route::resource` | 7 rotas (index, create, store, show, edit, update, destroy) |
| `Route::apiResource` | 5 rotas (sem create e edit) |
| Middleware | Intercepta antes/depois do Controller |
| `{{ }}` vs `{!! !!}` | `{{ }}` escapa HTML; `{!! !!}` não escapa |
| `migrate:fresh` | Dropa tudo + executa migrations |
| `migrate:rollback` | Desfaz último batch |
| Gates vs Policies | Gates: closures; Policies: classes por Model |
| `$fillable` | Permite mass assignment nos campos listados |
| Constructor Promotion | Declara e inicializa propriedade no construtor |
---
*Material elaborado com base nos padrões de cobrança da banca IDECAN para concursos públicos envolvendo PHP 8 e Laravel.*