Salve, tudo bem com você?
Então, este conteúdo é basicamente composto pelas minhas anotações feitas enquanto eu estudava sobre arquitetura modular no Laravel. Meu objetivo durante o estudo era entender quais configurações necessárias no Laravel que me permitiriam utilizar esse tipo de estratégia na arquitetura. Acabou que encontrei informações sobre essas configurações, mas, além disso, também descobri ferramentas que agilizam esse processo.
Além do conteúdo sobre modularização, aqui você vai encontrar informações sobre padrões de design e um pouco de boas práticas. Como isso aqui é um subproduto dos meus estudos, tem muita coisa sobre o Laravel que acabei aprendendo durante o processo. Pode parecer óbvio para você, mas não para o “eu” do passado.
Já adianto: meu objetivo aqui é trazer pontos que considerei relevantes durante os estudos. Para você, talvez pareçam “informações jogadas”, mas eu geralmente estudo a partir de palavras-chave ou tópicos, usando-os como ponto de partida para outras pesquisas (Google, YouTube e artigos). Então, não tenho a pretensão de ensinar algo neste conteúdo.
Disclaimer
Foi utilizada IA para organizar as minhas anotações em tópicos e gerar o table of contents. Você provavelmente não entenderia a sopa de letrinhas e inúmeros bullet points que produzi durante meus estudos, então utilizei essa famosa ferramenta para auxiliar na organização de tudo por aqui.
Table of contents
-
- 1.1. Autoloading (PSR-4)
- 1.2. Service Providers
- 1.3. Testes Modulares
-
- 2.1. Conectando Factories a Models
- 2.2. Actions
- 2.3. Definindo Status de Modelos
- 2.4. Data Transfer Objects (DTOs)
-
- 3.1. Instalação e Uso
- 3.2. Scripts para Composer
-
- 4.1. Vistas Normais
- 4.2. Componentes Anônimos
- 4.3. Componentes de Classe
-
- 5.1. Laravel IDEA
- 5.2. Pacote Laravel Modules
-
6. Organização de Código: Abordagens
- 6.1. Vertical Slice
- 6.2. Agrupamento por Tipo (Grouping by Type)
-
7. Padrões de Design e Boas Práticas
- 7.1. Acoplamento Temporal vs. Eventos
-
- 8.1. Sequences em Factories
1. Configuração de Módulos
1.1. Autoloading (PSR-4)
Para usar o Laravel de forma modular, é necessário informar o novo módulo no arquivo composer.json
. Isso permite que o autoload funcione, garantindo que as classes do seu módulo sejam encontradas.
Se quiser saber mais: Link
1.2. Service Providers
O Service Provider
é o coração de um módulo. Cada provider herda de uma classe base chamada ServiceProvider
e possui dois métodos principais:
-
register()
: Chamado primeiro, para registrar serviços e bindings. -
boot()
: Chamado após todos os métodosregister()
dos providers, para inicializar serviços e configurar funcionalidades (como rotas e views).
Para registrar um novo provider, ele deve ser informado no arquivo config/app.php
(ou configurado para ser descoberto automaticamente).
A doc do Laravel é uma mãe, se quiser mais informação sobre o tópico, recomendo!
1.3. Testes Modulares
Para usar testes de forma modular, é necessário registrar o módulo no arquivo phpunit.xml
.
2. Modelos, Factories e DTOs
2.1. Conectando Factories a Models
- Por padrão, as factories procuram pelas models no namespace
App\Models
. - Para conectar uma factory a uma model, defina a model no atributo
$model
da factory. - Quando o caminho padrão da factory é alterado, é preciso informar ao Laravel onde ela está. Use o método estático
newFactory()
na model:
use Modules\Product\Database\Factories\ProductFactory;
class Product extends Model
{
protected static function newFactory()
{
return ProductFactory::new();
}
}
Saiba mais em:
2.2. Actions
No Laravel, é uma convenção usar a pasta Actions
para agrupar comportamentos e ações, similar aos conceitos de usecase
ou service
.
2.3. Definindo Status de Modelos
É possível definir um status em uma instância de model sem persistir no banco de dados. Exemplo:
public const STATUS_PENDING = 'pending';
public static function startForUser(int $userId): self
{
return self::make([
'user_id' => $userId,
'status' => self::STATUS_PENDING,
]);
}
2.4. Data Transfer Objects (DTOs)
Os DTOs são úteis para reduzir o acoplamento e melhorar a clareza. Eles podem ser usados para:
- Comunicação entre diferentes camadas do código.
- Reduzir o número de parâmetros em métodos.
- Representar coleções de dados (Collections).
- Usar métodos estáticos (
fromEloquentModel
oufromEloquentCollection
) para instanciar DTOs a partir de models ou collections do Eloquent.
class ProductDTO
{
public function __construct(
public readonly int $id,
public readonly string $name,
public readonly string $sku,
public readonly float $price,
) {}
public static function fromEloquentModel(Product $product): self
{
return new self(
id: $product->id,
name: $product->name,
sku: $product->sku,
price: $product->price,
);
}
public static function fromEloquentCollection(Collection $products): Collection
{
return $products->map(fn (Product $product) => self::fromEloquentModel($product));
}
}
Saiba mais em:
- DTO (Data Transfer Objects) in PHP (Laravel)
- How to Use DTOs for Cleaner Code in Laravel, Best Practices and Implementation Guide
3. IDE Helper
3.1. Instalação e Uso
O IDE Helper Generator for Laravel gera PHPDocs que ajudam a IDE a entender as models.
Instalação:
composer require --dev barryvdh/laravel-ide-helper
Gerando PHPDocs:
- Para o caminho padrão das models:
php artisan ide-helper:models
- Para um caminho personalizado (ex: na pasta
modules
):
php artisan ide-helper:models --dir=modules
3.2. Scripts para Composer
É possível encurtar o comando adicionando um script no composer.json
:
"scripts": {
"ide": "php artisan ide-helper:models --dir=modules"
}
Uso na CLI:
composer run ide
4. Views Modulares
Para trabalhar com views modulares fora de resources/views
, use o método boot()
do Service Provider
para registrar os novos caminhos.
class OrderServiceProvider extends ServiceProvider
{
public function boot(): void
{
$this->loadViewsFrom(__DIR__ . '/../../Ui/Views', 'order');
Blade::anonymousComponentPath(__DIR__ . '/../../Ui/Views/components', 'order');
Blade::componentNamespace('Modules\\Order\\Ui\\ViewComponents', 'order');
}
}
4.1. Views Normais
Use loadViewsFrom()
para registrar pastas de views com um namespace, evitando conflitos entre módulos.
-
Exemplo:
view('order::checkout')
buscará a view emModules/Order/Ui/Views/checkout.blade.php
.
4.2. Componentes Anônimos
Use Blade::anonymousComponentPath()
para registrar uma pasta de componentes Blade anônimos.
- Eles não têm classe PHP associada, apenas arquivos
.blade.php
. -
Exemplo:
<x-order::alert />
renderizaModules/Order/Ui/Views/components/alert.blade.php
.
4.3. Componentes de Classe
Use Blade::componentNamespace()
para registrar um namespace PHP de componentes de classe.
- São componentes criados com
php artisan make:component
. -
Exemplo:
<x-order::checkout-summary />
renderiza o componente de classeCheckoutSummary
no namespaceModules\Order\Ui\ViewComponents
.
O básico sobre views no Laravel:
5. Ferramentas e Plugins
5.1. Laravel IDEA
- É um plugin do PHPStorm que oferece suporte ao Laravel.
- Na seção Module System, permite definir a estrutura modular do projeto (ex.: diretório
modules
com namespaceModules
). - Funciona bem quando a estrutura interna de cada módulo segue o padrão do Laravel.
Se não me engano o Laravel IDEA agora tá de graça no PHPStorm, é uma ótima ferramenta, recomendo
5.2. Pacote Laravel Modules
- O pacote Laravel Modules é uma ferramenta popular para modularizar projetos.
- Fornece uma estrutura organizada para criar e gerenciar módulos.
- O Laravel IDEA possui suporte nativo para este pacote.
6. Organização de Código: Abordagens
6.1. Vertical Slice
- Organiza o código agrupando por funcionalidade (ex.:
Order > Checkout
), e não por tipo de arquivo. - Todos os arquivos relacionados a uma funcionalidade ficam juntos.
- Facilita a visualização e manutenção de cada funcionalidade como uma unidade coesa.
Mais sobre esse tópico em:
6.2. Agrupamento por Tipo (Grouping by Type)
- Organiza o código por tipo de arquivo (ex.: models, controllers).
- É possível combinar esta abordagem com a modularização criando uma pasta
src
dentro do módulo para agrupar arquivos como Models, Events, etc., seguindo o padrão padrão do Laravel.
7. Padrões de Design e Boas Práticas
7.1. Acoplamento Temporal vs. Eventos
- Problema: Acoplamento Temporal: Ocorre quando uma ação depende estritamente de outra para ser executada, criando uma ordem rígida e dificultando a manutenção.
- Solução: Usar Eventos: Em vez de executar tudo em um único método, separe as responsabilidades. O fluxo principal dispara um evento e outras partes do sistema podem "escutar" e reagir de forma independente (ex.: enviar um e-mail de confirmação ou atualizar o estoque).
8. Outros Tópicos
8.1. Sequences em Factories
- O
Sequences
do Laravel permite variar valores de atributos ao criar várias instâncias de uma factory. - É útil para criar dados de teste com pequenas variações.
use Illuminate\Database\Eloquent\Factories\Sequence;
User::factory()
->count(3)
->state(new Sequence(
['name' => 'Alice'],
['name' => 'Bob'],
['name' => 'Carol'],
))
->create();
Referencia: Laravel: sequences
Top comments (2)
Ótimo estudo! Em breve a gente arruma um projetinho pra aplicar essas features.
Hi, you can try veltophp it is modular with HMVC pattern. Your feedback is welcome 🔥
veltophp.com
Some comments may only be visible to logged-in visitors. Sign in to view all comments.