### 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 --}}
@if(session('saved')) Saved! @endif
``` -------------------------------- ### 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) {{ $title }} @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; } } ```