├── .gitignore
├── README.md
├── composer.json
├── composer.lock
├── config
└── artisan-maker.php
├── phpunit.xml
├── phpunit.xml.bak
├── src
├── Console
│ ├── ActionMakeCommand.php
│ ├── FacadeMakeCommand.php
│ ├── FileGenerable.php
│ ├── InterfaceMakeCommand.php
│ ├── ServiceMakeCommand.php
│ └── stubs
│ │ ├── class-implement-interface.stub
│ │ ├── class.stub
│ │ ├── facade.stub
│ │ └── interface.stub
└── LaravelArtisanMakerServiceProvider.php
├── testbench.yaml
└── tests
└── Feature
├── ActionMakeTest.php
├── FacadeMakeTest.php
├── InterfaceMakeTest.php
└── ServiceMakeTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor
2 | .phpunit.cache
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel Artisan Maker
2 | A simple package that can help you create a boilerplate of a service, action, interface and facade class with artisan command.
3 |
4 | Example usage:
5 | ```
6 | php artisan make:action UserStoreAction
7 | php artisan make:service UserService
8 | php artisan make:interface UserServiceInterface
9 | php artisan make:facade UserFacade
10 | ```
11 |
12 | ## Installation
13 | ```bash
14 | composer require silverhand7/laravel-artisan-maker
15 | ```
16 |
17 | ## Usage
18 | ### Create a service class:
19 | Run the following command:
20 | ```
21 | php artisan make:service {YourService}
22 | ```
23 | The service will be created and can be found at app/Services/{YourService}.php \
24 | For example: `php artisan make:service UserService`
25 | #### Additionally, you can create a service that implements an interface class
26 | ```
27 | php artisan make:service {YourService} --interface={YourInterface}
28 | ```
29 | or
30 | ```
31 | php artisan make:service {YourService} -i {YourInterface}
32 | ```
33 |
34 | ### Create an action class:
35 | Run the following command:
36 | ```
37 | php artisan make:action {YourAction}
38 | ```
39 | The action will be created and can be found at app/Actions/{YourAction}.php \
40 | For example: `php artisan make:action UserStoreAction`
41 |
42 | ### Create an interface class:
43 | Run the following command:
44 | ```
45 | php artisan make:interface {YourInterface}
46 | ```
47 | The interface will be created and can be found at app/Contracts/{YourInterface}.php \
48 | For example: `php artisan make:interface UserServiceInterface`
49 |
50 | ### Create a facade class:
51 | Run the following command:
52 | ```
53 | php artisan make:facade {YourFacade}
54 | ```
55 | The facade will be created and can be found at app/Facades/{YourFacade}.php \
56 | For example: `php artisan make:facade UserFacade`
57 |
58 | ## Custom your namespace and generated file location
59 | You can easily customize where you want to locate your Service, Action, Interface or Facade class. You can do that by publishing the config file using the following command:
60 | ```
61 | php artisan vendor:publish --tag=artisan-maker-config
62 | ```
63 | You can customize it in `config/artisan-maker.php`, for example:
64 | ```
65 | 'service_interface' => 'App\MyOwnServices'
66 | 'service_directory' => 'app/MyOwnServices'
67 | ```
68 | Your next generated service will be in the `app/MyOwnServices` folder and your namespace for service will be `App\MyOwnServices`.
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "silverhand7/laravel-artisan-maker",
3 | "description": "A simple package that can help you to create a boilerplate of a service or action class.",
4 | "keywords": [
5 | "laravel",
6 | "silverhand7",
7 | "laravel-artisan-maker"
8 | ],
9 | "autoload": {
10 | "psr-4": {
11 | "Silverhand7\\LaravelArtisanMaker\\": "src/"
12 | }
13 | },
14 | "authors": [
15 | {
16 | "name": "silverhand7",
17 | "email": "refojunior5@gmail.com"
18 | }
19 | ],
20 | "license": "MIT",
21 | "require": {
22 | "php": "^8.1",
23 | "spatie/laravel-package-tools": "^1.9.2"
24 | },
25 | "extra": {
26 | "laravel": {
27 | "providers": [
28 | "Silverhand7\\LaravelArtisanMaker\\LaravelArtisanMakerServiceProvider"
29 | ]
30 | }
31 | },
32 | "require-dev": {
33 | "orchestra/testbench": "^8.19"
34 | },
35 | "scripts": {
36 | "post-autoload-dump": [
37 | "@clear",
38 | "@prepare"
39 | ],
40 | "clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
41 | "prepare": "@php vendor/bin/testbench package:discover --ansi",
42 | "serve": [
43 | "Composer\\Config::disableProcessTimeout",
44 | "@build",
45 | "@php vendor/bin/testbench serve"
46 | ],
47 | "test": [
48 | "@php vendor/bin/phpunit"
49 | ]
50 | }
51 | }
--------------------------------------------------------------------------------
/config/artisan-maker.php:
--------------------------------------------------------------------------------
1 | 'App\Services',
8 |
9 | /**
10 | * Set the default directory for your service class location.
11 | */
12 | 'service_directory' => 'app/Services',
13 |
14 | /**
15 | * Set your default namespace for Action class
16 | */
17 | 'action_namespace' => 'App\Actions',
18 |
19 | /**
20 | * Set the default directory for your action class location.
21 | */
22 | 'action_directory' => 'app/Actions',
23 |
24 | /**
25 | * Set your default namespace for Interface class
26 | */
27 | 'interface_namespace' => 'App\Contracts',
28 |
29 | /**
30 | * Set the default directory for your interface class location.
31 | */
32 | 'interface_directory' => 'app/Contracts',
33 |
34 | /**
35 | * Set your default namespace for Facade class
36 | */
37 | 'facade_namespace' => 'App\Facades',
38 | /**
39 | * Set the default directory for your facade class location.
40 | */
41 | 'facade_directory' => 'app/Facades',
42 |
43 | ];
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | ./tests/
9 |
10 |
11 | ./tests/
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/phpunit.xml.bak:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
12 |
13 |
14 | ./tests/
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/Console/ActionMakeCommand.php:
--------------------------------------------------------------------------------
1 | files->get($this->getStub());
16 |
17 | return $this
18 | ->replaceNamespace($stub, $name)
19 | ->replaceClass($stub, $name);
20 | }
21 |
22 | protected function replaceClass($stub, $name): string
23 | {
24 | $className = Str::replace($this->getNamespace($name).'\\', '', $name);
25 |
26 | $replace = [
27 | '{{ className }}' => $className,
28 | ];
29 |
30 | return Str::replace(array_keys($replace), array_values($replace), $stub);
31 | }
32 |
33 | protected function getDefaultNamespace($rootNamespace): string
34 | {
35 | $type = Str::lower($this->type);
36 | $nameSpace = config("artisan-maker.{$type}_namespace");
37 |
38 | return $nameSpace;
39 | }
40 |
41 | protected function getPath($name)
42 | {
43 | $type = Str::lower($this->type);
44 | return $this->laravel->basePath() . '/' . config("artisan-maker.{$type}_directory") . '/' . $this->getNameInput() .'.php';
45 | }
46 | }
--------------------------------------------------------------------------------
/src/Console/InterfaceMakeCommand.php:
--------------------------------------------------------------------------------
1 | option('interface')) {
27 | $interfaceUseNamespace = config('artisan-maker.interface_namespace') . '\\' . $interfaceName;
28 |
29 | if (!$this->checkInterfaceExists($interfaceUseNamespace)) {
30 | if ($this->confirm("The {$interfaceName} does not exist in " . config('artisan-maker.interface_namespace') . ", do you want to create one?", true)) {
31 | Artisan::call('make:interface', [
32 | 'name' => $interfaceName
33 | ]);
34 | }
35 | }
36 |
37 | $stub = $this->files->get($this->getClassImplementInterfaceStub());
38 |
39 | return $this
40 | ->replaceInterfaceUseNamespace($stub, $interfaceUseNamespace)
41 | ->replaceInterfaceClass($stub, $interfaceName)
42 | ->replaceNamespace($stub, $name)
43 | ->replaceClass($stub, $name);
44 | }
45 |
46 | $stub = $this->files->get($this->getStub());
47 |
48 | return $this
49 | ->replaceNamespace($stub, $name)
50 | ->replaceClass($stub, $name);
51 | }
52 |
53 | protected function replaceInterfaceClass(&$stub, $interfaceName)
54 | {
55 | $stub = Str::replace("{{ interfaceName }}", $interfaceName, $stub);
56 | return $this;
57 | }
58 |
59 | protected function replaceInterfaceUseNamespace(&$stub, $interfaceUseNamespace)
60 | {
61 | $stub = Str::replace("{{ interfaceUseNamespace }}", $interfaceUseNamespace, $stub);
62 | return $this;
63 | }
64 |
65 | protected function checkInterfaceExists($interfaceUseNamespace): bool
66 | {
67 | $paths = explode('\\', $interfaceUseNamespace);
68 | array_shift($paths);
69 | return file_exists($this->laravel['path'] . '/' . implode('/', $paths) . '.php');
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/Console/stubs/class-implement-interface.stub:
--------------------------------------------------------------------------------
1 | name('laravel-artisan-maker')
18 | ->hasConfigFile()
19 | ->hasCommand(ServiceMakeCommand::class)
20 | ->hasCommand(ActionMakeCommand::class)
21 | ->hasCommand(InterfaceMakeCommand::class)
22 | ->hasCommand(FacadeMakeCommand::class);
23 | }
24 | }
--------------------------------------------------------------------------------
/testbench.yaml:
--------------------------------------------------------------------------------
1 | providers:
2 | # - Workbench\App\Providers\WorkbenchServiceProvider
3 |
4 | migrations:
5 | - workbench/database/migrations
6 |
7 | seeders:
8 | - Workbench\Database\Seeders\DatabaseSeeder
9 |
10 | workbench:
11 | start: '/'
12 | install: true
13 | discovers:
14 | web: true
15 | api: false
16 | commands: false
17 | components: false
18 | views: false
19 | build: []
20 | assets: []
21 | sync: []
22 |
--------------------------------------------------------------------------------
/tests/Feature/ActionMakeTest.php:
--------------------------------------------------------------------------------
1 | >
13 | */
14 | protected function getPackageProviders($app)
15 | {
16 | return [
17 | LaravelArtisanMakerServiceProvider::class,
18 | ];
19 | }
20 |
21 | public function test_make_action_command()
22 | {
23 | $this->artisan('make:action HelloAction');
24 | $this->assertTrue(true);
25 | $this->assertFileExists(app_path('Actions/HelloAction.php'));
26 | }
27 |
28 | public function test_make_action_command_customized_directory()
29 | {
30 | $this->app['config']['artisan-maker.action_directory'] = 'app/CustomActionDirectory';
31 | $this->artisan('make:action HelloAction');
32 | $this->assertTrue(true);
33 | $this->assertFileExists(app_path('CustomActionDirectory/HelloAction.php'));
34 | }
35 | }
--------------------------------------------------------------------------------
/tests/Feature/FacadeMakeTest.php:
--------------------------------------------------------------------------------
1 | >
13 | */
14 | protected function getPackageProviders($app)
15 | {
16 | return [
17 | LaravelArtisanMakerServiceProvider::class,
18 | ];
19 | }
20 |
21 | public function test_make_facade_command()
22 | {
23 | $this->artisan('make:facade HelloFacade');
24 | $this->assertTrue(true);
25 | $this->assertFileExists(app_path('Facades/HelloFacade.php'));
26 | }
27 |
28 | public function test_make_facade_command_customized_directory()
29 | {
30 | $this->app['config']['artisan-maker.facade_directory'] = 'app/CustomFacadesDirectory';
31 | $this->artisan('make:facade HelloFacade');
32 | $this->assertTrue(true);
33 | $this->assertFileExists(app_path('CustomFacadesDirectory/HelloFacade.php'));
34 | }
35 | }
--------------------------------------------------------------------------------
/tests/Feature/InterfaceMakeTest.php:
--------------------------------------------------------------------------------
1 | >
13 | */
14 | protected function getPackageProviders($app)
15 | {
16 | return [
17 | LaravelArtisanMakerServiceProvider::class,
18 | ];
19 | }
20 |
21 | public function test_make_interface_command()
22 | {
23 | $this->artisan('make:interface HelloInterface');
24 | $this->assertTrue(true);
25 | $this->assertFileExists(app_path('Contracts/HelloInterface.php'));
26 | }
27 |
28 | public function test_make_interface_command_customized_directory()
29 | {
30 | $this->app['config']['artisan-maker.interface_directory'] = 'app/CustonInterfaceDirectory';
31 | $this->artisan('make:interface HelloInterface');
32 | $this->assertTrue(true);
33 | $this->assertFileExists(app_path('CustonInterfaceDirectory/HelloInterface.php'));
34 | }
35 | }
--------------------------------------------------------------------------------
/tests/Feature/ServiceMakeTest.php:
--------------------------------------------------------------------------------
1 | >
13 | */
14 | protected function getPackageProviders($app)
15 | {
16 | return [
17 | LaravelArtisanMakerServiceProvider::class,
18 | ];
19 | }
20 |
21 | public function test_make_service_command()
22 | {
23 | $this->artisan('make:service HelloService');
24 | $this->assertTrue(true);
25 | $this->assertFileExists(app_path('Services/HelloService.php'));
26 | }
27 |
28 | public function test_make_service_command_customized_directory()
29 | {
30 | $this->app['config']['artisan-maker.service_directory'] = 'app/CustomServiceDirectory';
31 | $this->artisan('make:service HelloService');
32 | $this->assertTrue(true);
33 | $this->assertFileExists(app_path('CustomServiceDirectory/HelloService.php'));
34 | }
35 | }
--------------------------------------------------------------------------------