### Module Asset Listing Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/listing.md
This is an example of the output from the `modules:list` command, showing asset counts for enabled modules and indicating disabled modules.
```text
Shared [Enabled | Order: 1]
+---------------------+-------+
| Asset | Count |
+---------------------+-------+
| Helpers | 3 |
| Service Providers | 1 |
| Configs | 2 |
+---------------------+-------+
Blog [Enabled | Order: 2]
+---------------------+-------+
| Asset | Count |
+---------------------+-------+
| Commands | 1 |
| Migrations | 4 |
| Views | 8 |
| Routes | 2 |
| Blade Components | 3 |
+---------------------+-------+
Legacy [Disabled]
No assets discovered
```
--------------------------------
### React Component Import Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Demonstrates importing components and hooks from different modules using the configured Vite alias. Ensure the file extensions match your project setup.
```typescript
// React
import ForumLayout from '@Modules/Forum/Layouts/ForumLayout';
import Button from '@Modules/Shared/Components/Button';
import useReplyActions from '@Modules/Forum/Hooks/useReplyActions';
```
--------------------------------
### Multi-File Component (MFC) Livewire Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/livewire-components.md
A Livewire multi-file component separating PHP logic and Blade markup into distinct files within a shared directory. This example demonstrates a simple toggle functionality.
```php
// Modules/Blog/Resources/views/livewire/toggle/toggle.php
on = ! $this->on;
}
};
```
```blade
{{-- Modules/Blog/Resources/views/livewire/toggle/toggle.blade.php --}}
{{ $on ? 'On' : 'Off' }}
```
--------------------------------
### Vue Component Import Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Demonstrates importing components and composables from different modules using the configured Vite alias. Ensure the file extensions match your project setup.
```typescript
// Vue
import ForumLayout from '@Modules/Forum/Layouts/ForumLayout.vue';
import Button from '@Modules/Shared/Components/Button.vue';
import useReplyActions from '@Modules/Forum/Composable/useReplyActions';
```
--------------------------------
### Module Blog Config File
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/configs.md
Example of a standard module configuration file returning an array of settings.
```php
// Modules/Blog/Config/blog.php
return [
'posts_per_page' => 15,
'allow_comments' => true,
'cache_ttl' => 3600,
];
```
--------------------------------
### Basic Module Service Provider Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/service-providers.md
Implement container bindings by extending Illuminate\Support\ServiceProvider. Use the `register()` method for bindings and `boot()` for application-wide bootstrapping logic.
```php
namespace Modules\Blog\Providers;
use Illuminate\Support\ServiceProvider;
use Modules\Blog\Services\PostRepository;
use Modules\Blog\Contracts\PostRepositoryInterface;
class BlogServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->bind(PostRepositoryInterface::class, PostRepository::class);
}
public function boot(): void
{
// Additional boot logic specific to this module
}
}
```
--------------------------------
### Module Route File Examples
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/routes.md
Standard Laravel route definitions within a module's Routes directory.
```php
// Modules/Blog/Routes/web.php
use Illuminate ung
Route::get('/blog', [PostController::class, 'index']);
Route::get('/blog/{post}', [PostController::class, 'show']);
```
```php
// Modules/Blog/Routes/api.php
use Illuminate ung
Route::get('/posts', [PostApiController::class, 'index']);
Route::post('/posts', [PostApiController::class, 'store']);
```
--------------------------------
### Example Module Structure
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Illustrates a typical directory structure for a module within the main Modules directory, showing common subdirectories for assets like configuration, console commands, database, events, views, and routes.
```directory
project-root/
├── app/
├── Modules/
│ ├── Blog/
│ │ ├── Config/
│ │ │ └── blog.php
│ │ ├── Console/
│ │ │ └── Commands/
│ │ │ └── PublishPosts.php
│ │ ├── Database/
│ │ │ ├── Factories/
│ │ │ │ └── PostFactory.php
│ │ │ ├── Migrations/
│ │ │ │ └── 2024_01_10_create_posts_table.php
│ │ │ └── Seeders/
│ │ │ └── BlogDatabaseSeeder.php
│ │ ├── Events/
│ │ │ └── PostPublished.php
│ │ ├── Filament/
│ │ │ └── Admin/
│ │ │ └── Resources/
│ │ │ └── Posts/
│ │ │ ├── PostResource.php
│ │ │ ├── Pages/
│ │ │ ├── Schemas/
│ │ │ └── Tables/
│ │ ├── Helpers/
│ │ │ └── formatting.php
│ │ ├── Lang/
│ │ │ ├── en/
│ │ │ │ └── messages.php
│ │ │ └── en.json
│ │ ├── Listeners/
│ │ │ └── NotifyFollowers.php
│ │ ├── Livewire/
│ │ │ └── PostEditor.php
│ │ ├── Models/
│ │ │ └── Post.php
│ │ ├── Nova/
│ │ │ └── Post.php
│ │ ├── Policies/
│ │ │ └── PostPolicy.php
│ │ ├── Providers/
│ │ │ └── BlogServiceProvider.php
│ │ ├── Resources/
│ │ │ └── views/
│ │ │ ├── home.blade.php
│ │ │ ├── components/
│ │ │ │ └── alert.blade.php
│ │ │ └── livewire/
│ │ │ └── post-editor.blade.php
│ │ ├── Routes/
│ │ │ ├── web.php
│ │ │ ├── api.php
│ │ │ └── console.php
│ │ └── View/
│ │ └── Components/
│ │ └── Card.php
│ └── Shop/
│ └── ...
└── vendor/
```
--------------------------------
### Install Laravel Modules
Source: https://github.com/mozex/laravel-modules/blob/main/README.md
Install the package using Composer.
```bash
composer require mozex/laravel-modules
```
--------------------------------
### Define a Module View
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Example of a Blade view file within a module.
```blade
{{-- Modules/Blog/Resources/views/index.blade.php --}}
@foreach($posts as $post)
{{ $post->title }}
{{ $post->body }}
@endforeach
```
--------------------------------
### Define a Module Route
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Example of a route file that utilizes the module's namespace for views and models.
```php
use Illuminate\Support\Facades\Route;
use Modules\Blog\Models\Post;
Route::get('/blog', function () {
return view('blog::index', ['posts' => Post::all()]);
});
```
--------------------------------
### Structure module directory layout
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/filament.md
Example directory structure for a module containing assets for multiple Filament panels.
```text
Modules/Blog/
└── Filament/
├── Admin/
│ ├── Resources/
│ │ └── Posts/
│ │ ├── PostResource.php
│ │ ├── Pages/
│ │ │ ├── CreatePost.php
│ │ │ ├── EditPost.php
│ │ │ └── ListPosts.php
│ │ ├── Schemas/
│ │ │ └── PostForm.php
│ │ └── Tables/
│ │ └── PostsTable.php
│ ├── Pages/
│ │ └── BlogSettings.php
│ └── Widgets/
│ └── PostStatsWidget.php
└── Dashboard/
└── Widgets/
└── RecentPostsWidget.php
```
--------------------------------
### Define a Module Model
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Example of a model class using the module-specific namespace.
```php
namespace Modules\Blog\Models;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['title', 'body'];
}
```
--------------------------------
### Create a Module Nova Resource Class
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/nova-resources.md
Example of a standard Nova resource class within a module. Ensure the namespace matches the module structure and the static $model property points to the correct module model.
```php
namespace Modules\Blog\Nova;
use Laravel\Nova\Resource;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Markdown;
use Laravel\Nova\Http\Requests\NovaRequest;
use Modules\Blog\Models\Post;
class Post extends Resource
{
public static $model = Post::class;
public static $title = 'title';
public static $search = ['id', 'title'];
public function fields(NovaRequest $request): array
{
return [
ID::make()->sortable(),
Text::make('Title')->sortable()->rules('required'),
Markdown::make('Body')->rules('required'),
];
}
}
```
--------------------------------
### Single-File Component (SFC) Livewire Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/livewire-components.md
A Livewire single-file component combining PHP logic and Blade markup in one file. It features a simple counter with an increment function.
```blade
{{-- Modules/Blog/Resources/views/livewire/counter.blade.php --}}
count++;
}
};
?>
Count: {{ $count }}
```
--------------------------------
### Example Module Structure
Source: https://github.com/mozex/laravel-modules/blob/main/README.md
A basic structure for a module including routes and views.
```tree
Modules/
└── Blog/
├── Routes/
│ └── web.php
└── Resources/
└── views/
└── index.blade.php
```
--------------------------------
### Identify panel mapping convention
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/filament.md
Example showing how the directory structure determines the Filament panel ID.
```text
Modules/Blog/Filament/Admin/Resources/PostResource.php
^^^^^
Panel ID = "admin"
```
--------------------------------
### Call Helper Functions
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/helpers.md
Once defined and loaded, helper functions can be called directly from anywhere in your application. This example shows calling the previously defined `format_reading_time` and `excerpt` helpers.
```php
$readTime = format_reading_time($post->body);
$summary = excerpt($post->body, 200);
```
--------------------------------
### Class-Based Livewire Component Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/livewire-components.md
A typical class-based Livewire component for managing a blog post. It includes properties for post data, mount lifecycle hook for initialization, a save method, and a render method pointing to its Blade view.
```php
// Modules/Blog/Livewire/PostEditor.php
namespace Modules\Blog\Livewire;
use Livewire\Component;
use Modules\Blog\Models\Post;
class PostEditor extends Component
{
public Post $post;
public string $title = '';
public string $body = '';
public function mount(Post $post): void
{
$this->post = $post;
$this->title = $post->title;
$this->body = $post->body;
}
public function save(): void
{
$this->post->update([
'title' => $this->title,
'body' => $this->body,
]);
session()->flash('saved', true);
}
public function render()
{
return view('blog::livewire.post-editor');
}
}
```
```blade
{{-- Modules/Blog/Resources/views/livewire/post-editor.blade.php --}}
```
--------------------------------
### Example Route Definition
Source: https://github.com/mozex/laravel-modules/blob/main/README.md
Define a route within a module's web.php file.
```php
use Illuminate\Support\Facades\Route;
Route::get('/blog', fn () => view('blog::index'));
```
--------------------------------
### Livewire Component Tag Syntax
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/livewire-components.md
Example of using the Livewire component tag syntax in Blade templates to render a component, passing properties as needed.
```blade
```
--------------------------------
### Pest Test: List Published Posts
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/pest.md
Example Pest test for listing published posts, including factory creation and response assertion.
```php
// Modules/Blog/Tests/Feature/PostTest.php
use Modules\Blog\Models\Post;
it('can list published posts', function () {
Post::factory()->published()->count(3)->create();
Post::factory()->draft()->create();
$response = $this->get('/blog');
$response->assertOk();
$response->assertViewHas('posts', fn ($posts) => $posts->count() === 3);
});
```
--------------------------------
### Blade Component View Template
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/blade-components.md
The Blade view file for a component. This example renders a 'card' component, conditionally displaying an image and then the title and excerpt.
```blade
{{-- Modules/Blog/Resources/views/components/card.blade.php --}}
@if($image)
@endif
{{ $title }}
{{ $excerpt }}
```
--------------------------------
### Vite Configuration for Module Aliasing (React)
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Configure Vite to resolve imports starting with '@Modules/{Name}/' to the respective module's Resources/ts/ directory. This setup is identical for Vue, only the framework plugin differs.
```typescript
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
laravel({
input: ['resources/ts/app.tsx', 'resources/css/app.css'],
refresh: true,
}),
react(),
],
resolve: {
alias: [
{ find: /^@
egex/, replacement: '/resources/ts/' },
{ find: /^@Modules\/([^\/]+)\/(.*)$/, replacement: '/Modules/$1/Resources/ts/$2' },
],
},
});
```
--------------------------------
### Vite Configuration for Module Aliasing (Vue)
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Configure Vite to resolve imports starting with '@Modules/{Name}/' to the respective module's Resources/ts/ directory. This setup is identical for React, only the framework plugin differs.
```typescript
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: ['resources/ts/app.ts', 'resources/css/app.css'],
refresh: true,
}),
vue(),
],
resolve: {
alias: [
{ find: /^@
egex/, replacement: '/resources/ts/' },
{ find: /^@Modules\/([^\/]+)\/(.*)$/, replacement: '/Modules/$1/Resources/ts/$2' },
],
},
});
```
--------------------------------
### List All Modules
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/listing.md
Run this command to see a list of all registered modules, their status (enabled/disabled), load order, and a count of discovered assets.
```bash
php artisan modules:list
```
--------------------------------
### Per-Module Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Settings to control module activation and loading order.
```php
'modules' => [
'Shared' => [
'active' => true,
'order' => 1, // lower numbers load first
],
'Blog' => [
'active' => true,
'order' => 2,
],
'Legacy' => [
'active' => false, // completely ignored during discovery
],
],
```
--------------------------------
### Class-Based Blade Component Example
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/blade-components.md
Define a class-based Blade component by extending Illuminate\View\Component. Accept data via the constructor and return a view from the render() method. This example shows a 'Card' component with title, excerpt, and an optional image.
```php
namespace Modules\Blog\View\Components;
use Illuminate\View\Component;
class Card extends Component
{
public function __construct(
public string $title,
public string $excerpt,
public ?string $image = null,
) {}
public function render()
{
return view('blog::components.card');
}
}
```
--------------------------------
### Module Model Factory Usage
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/models-factories.md
Demonstrates how to create single or multiple model instances using the factory, including applying states and defining relationships. Ensure the model and factory namespaces are correctly configured.
```php
use Modules\Blog\Models\Post;
// Create a single instance
$post = Post::factory()->create();
// Create multiple with state
$posts = Post::factory()
->count(10)
->published()
->create();
// With relationships
$post = Post::factory()
->has(Comment::factory()->count(3))
->create();
```
--------------------------------
### Build Module Discovery Cache
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/caching.md
Run this command to scan active modules and write discovery results to cache files in `bootstrap/cache/`. This should be part of your deployment script.
```bash
php artisan modules:cache
```
--------------------------------
### Install Laravel Modules via Composer
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Use Composer to add the laravel-modules package to your project dependencies.
```bash
composer require mozex/laravel-modules
```
--------------------------------
### Running Seeders via Artisan
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/seeders.md
Command line instructions for executing database seeds for the application and specific modules.
```bash
# Run all seeders (app + modules)
php artisan db:seed
# Run a specific module seeder
php artisan db:seed --class="Modules\Blog\Database\Seeders\BlogDatabaseSeeder"
# Fresh migrate + seed
php artisan migrate:fresh --seed
```
--------------------------------
### Global Module Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Settings for the modules directory and namespace prefix.
```php
'modules_directory' => 'Modules', // where modules live (relative to project root)
'modules_namespace' => 'Modules\\', // PSR-4 namespace prefix
```
--------------------------------
### Accessing Module Config
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/configs.md
Demonstrates how to access merged module configuration values using the global `config()` helper.
```php
config('blog.posts_per_page'); // 15
config('blog.allow_comments'); // true
```
--------------------------------
### Configure listener discovery
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/events-listeners.md
Define the listener discovery settings in the module configuration file.
```php
'listeners' => [
'active' => true,
'patterns' => [
'*/Listeners',
],
],
```
--------------------------------
### Pest Test: View Single Post
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/pest.md
Example Pest test for viewing a single post, asserting the response and content.
```php
it('can view a single post', function () {
$post = Post::factory()->published()->create();
$response = $this->get("/blog/{$post->slug}");
$response->assertOk();
$response->assertSee($post->title);
});
```
--------------------------------
### Configure module migration patterns
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/migrations.md
Define the active status and directory patterns for module migrations in the configuration file.
```php
'migrations' => [
'active' => true,
'patterns' => [
'*/Database/Migrations',
],
],
```
--------------------------------
### Default View Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/views.md
Configure the view system's active status and directory patterns. Ensure 'active' is true to enable module view registration.
```php
'views' => [
'active' => true,
'patterns' => [
'*/Resources/views',
],
],
```
--------------------------------
### Return module pages from controllers
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Demonstrates returning an Inertia response using the @Modules/ prefix to resolve module-specific components.
```php
namespace Modules\Blog\Http\Controllers;
use Inertia\Response;
use Modules\Blog\Data\PostShowResource;
use Modules\Blog\Models\Post;
class PostsController
{
public function show(Post $post): Response
{
return inertia(
component: '@Modules/Blog/Post/Show',
props: PostShowResource::from($post),
);
}
}
```
--------------------------------
### Directory Layout for Views
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/views.md
Illustrates the standard directory structure for views within a module, including home, pages, partials, and components.
```tree
Modules/Blog/
└── Resources/
└── views/
├── home.blade.php
├── pages/
│ ├── index.blade.php
│ └── show.blade.php
├── partials/
│ └── sidebar.blade.php
└── components/
├── alert.blade.php
└── form/
└── input.blade.php
```
--------------------------------
### Custom Model and Factory Namespaces
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/models-factories.md
Update these settings if your modules use different directory structures for models or factories. For example, if models are in 'Entities\' instead of 'Models\'.
```php
// If models live in Modules/Blog/Entities/ instead of Modules/Blog/Models/
'models' => [
'active' => true,
'namespace' => 'Entities\\',
],
// If factories live in Modules/Blog/Tests/Factories/
'factories' => [
'active' => true,
'namespace' => 'Tests\\Factories\\',
],
```
--------------------------------
### Configure Pest.php for Module Tests
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/pest.md
Set up the tests/Pest.php file to include module test paths and apply base TestCase and traits. The path is relative to the tests/Pest.php file.
```php
in('Feature', 'Unit');
// Module tests (path is relative to tests/Pest.php)
uses(TestCase::class, RefreshDatabase::class)->in('../Modules/*/Tests/*');
```
--------------------------------
### Define inline Inertia routes for modules
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Shows how to use the @Modules/ prefix directly within route definitions.
```php
Route::inertia('/coming-soon', '@Modules/Shared/ComingSoon')->name('coming-soon');
```
--------------------------------
### Custom Glob Pattern for Modules Directory
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/phpstan.md
If your modules are located in a directory other than 'Modules/', update the glob patterns in your `phpstan.php` configuration to match the custom path. This example shows how to adjust the pattern if modules are in 'src/Domains/'.
```php
// If modules live in src/Domains/
...glob(__DIR__ . '/src/Domains/*', GLOB_ONLYDIR),
```
--------------------------------
### Run migrations for a specific module
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/migrations.md
Target a specific module's migration directory using the --path option.
```bash
php artisan migrate --path=Modules/Blog/Database/Migrations
```
--------------------------------
### Module Config Default (Priority: False)
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/configs.md
Shows how application configuration values override module configuration values when `priority` is false. Application values take precedence.
```php
// With priority: false, same files as above:
config('app.feature.enabled'); // false (app wins)
config('app.feature.limit'); // 10 (app wins)
```
--------------------------------
### Execute standard migration commands
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/migrations.md
Run standard artisan commands to manage migrations across the application and all active modules.
```bash
# Run all pending migrations (app + all modules)
php artisan migrate
# Roll back the last batch
php artisan migrate:rollback
# Reset and re-run all migrations
php artisan migrate:fresh
```
--------------------------------
### Configure module command discovery
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/commands.md
Define the active status and directory patterns for command discovery in the module configuration.
```php
'commands' => [
'active' => true,
'patterns' => [
'*/Console/Commands',
],
],
```
--------------------------------
### Import module CSS
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Import module-specific stylesheets into the main application CSS file using the configured alias.
```css
@import '@Modules/Forum/css/forum.css';
@import '@Modules/Blog/css/blog.css';
```
--------------------------------
### Run module tests via CLI
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/phpunit.md
Execute tests using the vendor/bin/phpunit binary with various filtering options.
```bash
# Run everything (app tests + module tests)
./vendor/bin/phpunit
# Run only module tests
./vendor/bin/phpunit --testsuite Modules
# Run tests for a specific module
./vendor/bin/phpunit Modules/Blog/Tests
```
--------------------------------
### Livewire Components Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/livewire-components.md
Default configuration for enabling and defining patterns for Livewire components within modules. Adjust 'patterns' to control class-based component discovery and 'view_path' for SFC/MFC locations.
```php
'livewire-components' => [
'active' => true,
'patterns' => [
'*/Livewire',
],
'view_path' => 'Resources/views/livewire',
]
```
--------------------------------
### Define Global Helper Functions
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/helpers.md
Write helper files as plain PHP files. Always wrap function definitions in a `function_exists()` check to prevent redeclaration errors, especially when multiple modules might define the same helper.
```php
// Modules/Blog/Helpers/formatting.php
if (! function_exists('format_reading_time')) {
function format_reading_time(string $text): string
{
$words = str_word_count(strip_tags($text));
$minutes = max(1, (int) ceil($words / 200));
return "{$minutes} min read";
}
}
if (! function_exists('excerpt')) {
function excerpt(string $text, int $limit = 150): string
{
return Str::limit(strip_tags($text), $limit);
}
}
```
--------------------------------
### Cache Module Discovery in Deployment
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/caching.md
Integrate `modules:cache` into your deployment script alongside other caching commands for optimal production performance.
```bash
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan modules:cache
```
--------------------------------
### Configure PHPUnit test suites and source
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/phpunit.md
Update the phpunit.xml file to include module test directories and source paths for coverage analysis.
```xml
./tests/Unit./tests/Feature./Modules/*/Tests./app./Modules
```
--------------------------------
### Modules Facade Path Helpers
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Utility methods for resolving paths relative to the modules directory or project base.
```php
use Mozex\Modules\Facades\Modules;
// Absolute path to the modules directory
Modules::modulesPath();
// e.g., /var/www/app/Modules
// Path to a specific location within modules
Modules::modulesPath('Blog/Config');
// e.g., /var/www/app/Modules/Blog/Config
// Project base path with optional suffix
Modules::basePath('storage');
// e.g., /var/www/app/storage
```
--------------------------------
### Publish Laravel Modules Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
If you need to customize default settings like disabling features or adjusting discovery patterns, publish the configuration file.
```bash
php artisan vendor:publish --tag=laravel-modules-config
```
--------------------------------
### Per-Feature Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Settings to enable or disable specific features like views across all modules.
```php
'views' => [
'active' => true,
'patterns' => [
'*/Resources/views',
],
],
```
--------------------------------
### Default Seeder Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/seeders.md
Configuration settings for enabling seeder discovery and defining the directory patterns.
```php
'seeders' => [
'active' => true,
'patterns' => [
'*/Database/Seeders',
],
],
```
--------------------------------
### Configure Nova Resource Discovery
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/nova-resources.md
Defines the configuration for discovering Nova resources within modules. Set 'active' to false to disable discovery and adjust 'patterns' to match your Nova resource directory layout.
```php
'nova-resources' => [
'active' => true,
'patterns' => [
'*/Nova',
],
],
```
--------------------------------
### Configure Filament asset discovery
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/filament.md
Default configuration settings for enabling and defining patterns for Filament resources, pages, widgets, and clusters.
```php
'filament-resources' => [
'active' => true,
'patterns' => ['*/Filament/*/Resources'],
],
'filament-pages' => [
'active' => true,
'patterns' => ['*/Filament/*/Pages'],
],
'filament-widgets' => [
'active' => true,
'patterns' => ['*/Filament/*/Widgets'],
],
'filament-clusters' => [
'active' => true,
'patterns' => ['*/Filament/*/Clusters'],
],
```
--------------------------------
### Configure Inertia page resolution for React
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Uses import.meta.glob to locate React components in both the main application and module directories.
```tsx
// resources/ts/app.tsx
import type { ResolvedComponent } from '@inertiajs/react';
import { createInertiaApp } from '@inertiajs/react';
import { createRoot } from 'react-dom/client';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
type Glob = Record Promise>;
const appPages = import.meta.glob('./Pages/**/*.tsx');
const modulePages = import.meta.glob('../../Modules/**/Resources/ts/Pages/**/*.tsx');
function resolveInertiaPage(name: string): [string, Glob] {
if (name.startsWith('@Modules/')) {
const withoutPrefix = name.replace('@Modules/', '');
const module = withoutPrefix.substring(0, withoutPrefix.indexOf('/'));
const pagePath = withoutPrefix.slice(module.length + 1);
return [
`../../Modules/${module}/Resources/ts/Pages/${pagePath}.tsx`,
modulePages,
];
}
return [`./Pages/${name}.tsx`, appPages];
}
createInertiaApp({
resolve: (name) => resolvePageComponent(...resolveInertiaPage(name)),
setup({ el, App, props }) {
createRoot(el).render();
},
});
```
--------------------------------
### Define a module Artisan command class
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/commands.md
Create a command class by extending Illuminate\Console\Command, defining a signature, description, and handle method.
```php
namespace Modules\Blog\Console\Commands;
use Illuminate\Console\Command;
class PublishPosts extends Command
{
protected $signature = 'blog:publish-posts
{--dry-run : Show what would be published without making changes}';
protected $description = 'Publish all scheduled posts that are past their publish date';
public function handle(): int
{
$query = Post::where('publish_at', '<=', now())
->where('status', 'draft');
if ($this->option('dry-run')) {
$this->info("Would publish {$query->count()} posts.");
return self::SUCCESS;
}
$count = $query->update(['status' => 'published']);
$this->info("Published {$count} posts.");
return self::SUCCESS;
}
}
```
--------------------------------
### Configure Policy and Model Namespaces
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/policies.md
Define the active status and namespace structure for models and policies in the configuration file.
```php
'policies' => [
'active' => true,
'namespace' => 'Policies\\',
],
'models' => [
'active' => true,
'namespace' => 'Models\\',
],
```
--------------------------------
### Publish Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/README.md
Optionally publish the configuration file to customize defaults.
```bash
php artisan vendor:publish --tag=laravel-modules-config
```
--------------------------------
### Enable and Configure Helpers
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/helpers.md
Configure the 'helpers' section in your Laravel configuration to enable helper files and define patterns for their discovery. Ensure 'active' is set to true to load helpers.
```php
'helpers' => [
'active' => true,
'patterns' => [
'*/Helpers/*.php',
],
],
```
--------------------------------
### Default Route Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/routes.md
The default configuration for route discovery, including active status and file patterns.
```php
'routes' => [
'active' => true,
'patterns' => [
'*/Routes/*.php',
],
'commands_filenames' => [
'console',
],
'channels_filenames' => [
'channels',
],
],
```
--------------------------------
### Rendering Module Views in Controllers
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/views.md
Render module-specific views using the 'namespace::view' syntax within controller methods. The namespace corresponds to the kebab-cased module name.
```php
// In a controller
return view('blog::home');
return view('blog::pages.show', ['post' => $post]);
```
--------------------------------
### Implementing Custom Route Registrars
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/routes.md
Using custom registrars to wrap routes in specific logic, such as localization.
```php
use Mozex\Modules\Facades\Modules;
use Illuminate\Support\Facades\Route;
Modules::registerRoutesUsing('localized', function (array $attributes, $routes) {
Route::localized(function () use ($attributes, $routes): void {
Route::group($attributes, $routes);
});
});
Modules::routeGroup('localized', middleware: ['web'], as: 'localized.');
```
--------------------------------
### Configure Custom Cache Driver Factory
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/caching.md
Swap the default file-backed cache driver with a custom implementation, such as a Redis-backed cache, by providing a factory closure. This should be called from a service provider's `register()` method.
```php
use Mozex\Modules\Contracts\BaseScout;
use Spatie\StructureDiscoverer\Cache\DiscoverCacheDriver;
BaseScout::useCacheDriverFactory(
fn (BaseScout $scout): DiscoverCacheDriver => new YourDriver($scout->cacheFile())
);
```
--------------------------------
### Default Module Configs
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/configs.md
Defines the default settings for module configuration discovery and merging.
```php
'configs' => [
'active' => true,
'patterns' => [
'*/Config/*.php',
],
'priority' => true,
],
```
--------------------------------
### Module Config Override (Priority: True)
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/configs.md
Illustrates how module configuration values override application configuration values when `priority` is true (default). Module values take precedence.
```php
// config/app.php
return ['feature' => ['enabled' => false, 'limit' => 10]];
// Modules/Shop/Config/app.php
return ['feature' => ['enabled' => true]];
// Result:
config('app.feature.enabled'); // true (module wins)
config('app.feature.limit'); // 10 (app value preserved, module didn't set it)
```
--------------------------------
### Execute module Artisan commands
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/commands.md
Run the registered module command via the Artisan CLI.
```bash
php artisan blog:publish-posts
php artisan blog:publish-posts --dry-run
```
--------------------------------
### Configure translation settings
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/translations.md
Define the active status and directory patterns for module translations in the configuration file.
```php
'translations' => [
'active' => true,
'patterns' => [
'*/Lang',
],
],
```
--------------------------------
### Implement a listener
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/events-listeners.md
Listeners require a handle method that type-hints the event to enable automatic discovery.
```php
namespace Modules\Blog\Listeners;
use Modules\Blog\Events\PostPublished;
class NotifyFollowers
{
public function handle(PostPublished $event): void
{
// Send notifications to the post author's followers
$event->post->author->followers->each(function ($follower) use ($event) {
$follower->notify(new NewPostNotification($event->post));
});
}
}
```
--------------------------------
### Define a module migration file
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/migrations.md
Create migration files within the module's Database/Migrations directory using standard Laravel migration syntax.
```php
// Modules/Blog/Database/Migrations/2024_01_10_100000_create_posts_table.php
use Illuminate emplatesase emplate;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('posts');
}
};
```
--------------------------------
### Customize Namespace Settings
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/policies.md
Override default directory structures by updating the models and policies namespace configuration.
```php
// Models in Modules/Blog/Entities/
'models' => [
'active' => true,
'namespace' => 'Entities\\',
],
// Policies in Modules/Blog/Auth/Policies/
'policies' => [
'active' => true,
'namespace' => 'Auth\\Policies\\',
],
```
--------------------------------
### Register routes using custom logic
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Use this method to take full control over how route files are registered, such as wrapping them in custom route groups.
```php
// Every module's Routes/localized.php file will be wrapped in Route::localized()
Modules::registerRoutesUsing('localized', function (array $attributes, $routes) {
Route::localized(fn () => Route::group($attributes, $routes));
});
```
--------------------------------
### Defining Broadcasting Channels
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/routes.md
Use channels.php files to define authorization callbacks for broadcast channels.
```php
// Modules/Blog/Routes/channels.php
use Illuminate"=>"Support\\Facades\\Broadcast;
Broadcast::channel('blog.post.{postId}', function ($user, $postId) {
return $user->can('view', Post::find($postId));
});
```
--------------------------------
### Module Directory Structure
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
The standard directory layout for a module within the application.
```text
Modules/
└── Blog/
├── Models/
│ └── Post.php
├── Resources/
│ └── views/
│ └── index.blade.php
└── Routes/
└── web.php
```
--------------------------------
### Run Tests for a Specific Module
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/pest.md
Execute tests for a particular module by specifying its path.
```bash
./vendor/bin/pest Modules/Blog/Tests
```
--------------------------------
### Defining Console Commands and Schedules
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/routes.md
Use console.php files to register Artisan commands and scheduled tasks specific to a module.
```php
// Modules/Blog/Routes/console.php
use Illuminate"=>"Support\\Facades\\Artisan;
use Illuminate"=>"Support\\Facades\\Schedule;
Artisan::command('blog:cleanup', function () {
// Clean up old draft posts
});
Schedule::command('blog:cleanup')->daily();
```
--------------------------------
### Define module test directory structure
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/phpunit.md
Standard directory layout for tests within a module.
```text
Modules/Blog/
└── Tests/
├── Feature/
│ └── PostControllerTest.php
└── Unit/
└── PostServiceTest.php
```
--------------------------------
### Configure Inertia page resolution for Vue
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/inertia.md
Uses import.meta.glob to locate Vue components in both the main application and module directories.
```ts
// resources/ts/app.ts
import type { DefineComponent } from 'vue';
import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
type Glob = Record Promise>;
const appPages = import.meta.glob('./Pages/**/*.vue');
const modulePages = import.meta.glob('../../Modules/**/Resources/ts/Pages/**/*.vue');
function resolveInertiaPage(name: string): [string, Glob] {
if (name.startsWith('@Modules/')) {
const withoutPrefix = name.replace('@Modules/', '');
const module = withoutPrefix.substring(0, withoutPrefix.indexOf('/'));
const pagePath = withoutPrefix.slice(module.length + 1);
return [
`../../Modules/${module}/Resources/ts/Pages/${pagePath}.vue`,
modulePages,
];
}
return [`./Pages/${name}.vue`, appPages];
}
createInertiaApp({
resolve: (name) => resolvePageComponent(...resolveInertiaPage(name)),
setup({ el, App, props, plugin }) {
createApp({ render: () => h(App, props) }).use(plugin).mount(el);
},
});
```
--------------------------------
### Table Schema Configuration
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/filament.md
Configures the table schema for displaying blog posts, including columns for title and creation date. This class should be placed under the `Tables/` directory within your resource.
```php
namespace Modules\Blog\Filament\Admin\Resources\Posts\Tables;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
class PostsTable
{
public static function configure(Table $table): Table
{
return $table->columns([
TextColumn::make('title'),
TextColumn::make('created_at')->dateTime(),
]);
}
}
```
--------------------------------
### Run All Pest Tests
Source: https://github.com/mozex/laravel-modules/blob/main/docs/integrations/pest.md
Execute all tests using the Pest runner.
```bash
./vendor/bin/pest
```
--------------------------------
### Advanced Module Service Provider for Third-Party Integrations
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/service-providers.md
Register morph map entries and policies for third-party models. This provider demonstrates how to integrate with packages like Spatie Permission and enforce polymorphic relations.
```php
namespace Modules\User\Providers;
use Illuminate\Database\Eloquent\Relations\Relation;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
use Modules\User\Models\EmployeeTeam;
use Modules\User\Models\User;
use Modules\User\Policies\PermissionPolicy;
use Modules\User\Policies\RolePolicy;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
class UserServiceProvider extends ServiceProvider
{
public function boot(): void
{
Relation::enforceMorphMap([
'user' => User::class,
'employee-team' => EmployeeTeam::class,
'role' => Role::class,
'permission' => Permission::class,
]);
Gate::policy(Role::class, RolePolicy::class);
Gate::policy(Permission::class, PermissionPolicy::class);
}
}
```
--------------------------------
### Reset to Default Cache Driver
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/caching.md
Revert to the default file-backed cache driver by passing `null` to `useCacheDriverFactory`. Ensure `BaseScout::clearInstances()` is called if the factory was swapped after the package booted.
```php
BaseScout::useCacheDriverFactory(null);
```
--------------------------------
### Handle cross-module events
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/events-listeners.md
Listeners can handle events from any module by type-hinting the appropriate event class.
```php
namespace Modules\Shop\Listeners;
use Modules\Blog\Events\PostPublished;
class IndexPostForSearch
{
public function handle(PostPublished $event): void
{
SearchIndex::update($event->post);
}
}
```
--------------------------------
### Define a custom route group
Source: https://github.com/mozex/laravel-modules/blob/main/docs/introduction.md
Use this to register custom route files like admin.php with specific middleware and prefixes.
```php
// Now every module's Routes/admin.php file loads with these attributes
Modules::routeGroup('admin',
prefix: 'admin',
middleware: ['web', 'auth', 'is-admin'],
as: 'admin.',
);
```
--------------------------------
### Rendering Module Views in Routes
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/views.md
Use the 'namespace::view' syntax to render module views directly within route definitions. This allows for quick view rendering without a controller.
```php
// In a route closure
Route::get('/blog', fn () => view('blog::pages.index'));
```
--------------------------------
### Clear and Cache Configs
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/configs.md
Commands to clear the existing configuration cache and then re-cache the merged configurations, essential after deploying module config changes.
```bash
php artisan config:clear
php artisan config:cache
```
--------------------------------
### Using Blade Directives with Namespaced Views
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/views.md
Demonstrates the use of standard Blade directives like @include, @extends, and @each with namespaced module views. Ensure the correct 'namespace::view' syntax is used.
```blade
@include('blog::partials.sidebar')
@extends('blog::layouts.app')
@each('blog::partials.post-card', $posts, 'post')
```
--------------------------------
### Resource Class for Blog Posts
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/filament.md
Defines a Filament resource for blog posts, delegating form and table configurations to separate classes. Ensure the namespace and file location are correct within your module.
```php
namespace Modules\Blog\Filament\Admin\Resources\Posts;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Table;
use Modules\Blog\Filament\Admin\Resources\Posts\Pages\CreatePost;
use Modules\Blog\Filament\Admin\Resources\Posts\Pages\EditPost;
use Modules\Blog\Filament\Admin\Resources\Posts\Pages\ListPosts;
use Modules\Blog\Filament\Admin\Resources\Posts\Schemas\PostForm;
use Modules\Blog\Filament\Admin\Resources\Posts\Tables\PostsTable;
use Modules\Blog\Models\Post;
class PostResource extends Resource
{
protected static ?string $model = Post::class;
protected static ?string $navigationIcon = 'heroicon-o-document-text';
public static function form(Schema $schema): Schema
{
return PostForm::configure($schema);
}
public static function table(Table $table): Table
{
return PostsTable::configure($table);
}
public static function getPages(): array
{
return [
'index' => ListPosts::route('/'),
'create' => CreatePost::route('/create'),
'edit' => EditPost::route('/{record}/edit'),
];
}
}
```
--------------------------------
### Define a Module Policy Class
Source: https://github.com/mozex/laravel-modules/blob/main/docs/features/policies.md
Create a policy class within a module's namespace, following standard Laravel authorization patterns.
```php
namespace Modules\Blog\Policies;
use Modules\Blog\Models\Post;
use App\Models\User;
class PostPolicy
{
public function view(User $user, Post $post): bool
{
return true;
}
public function update(User $user, Post $post): bool
{
return $user->id === $post->author_id;
}
public function delete(User $user, Post $post): bool
{
return $user->id === $post->author_id;
}
}
```