Skip to content

Commit a7cbec3

Browse files
init
0 parents  commit a7cbec3

18 files changed

+814
-0
lines changed

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.DS_Store
2+
.idea
3+
.vscode
4+
/vendor
5+
composer.lock
6+
/phpunit.xml
7+
.phpunit.result.cache
8+
*.log
9+
_notes.txt
10+
_notes.md
11+
bak__*

README.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Laravel Extended Commands
2+
3+
Extends the Laravel artisan commands for developers.
4+
5+
With all of the helpful commands that Laravel comes out of the box with, there are a few that are missing. Hopefully one day Laravel will add them officially. Until then, let's fill the gap.
6+
7+
## Installation
8+
9+
Install as a dev dependency:
10+
11+
```bash
12+
composer require cyberpunkcodes/laravel-extended-commands --dev
13+
```
14+
15+
## Usage
16+
17+
This package is only usable via the command line. Refer to the commands list below for supported commands and how to use them.
18+
19+
## Commands
20+
21+
The make commands will generate files in the corresponding directories within the `app` directory and the `App` namespace.
22+
23+
**For example:** Actions will be generated in the `app/Actions` directory and will be within the `App\Actions` namespace. Enums will be generated in `app/Enums` with the `App\Enums` namespace. Contracts will be generated in `app/Contracts` with the `App\Contracts` namespace. And so on.
24+
25+
Using double backslashes in the name will generate sub-directories. ie, running `php artisan make:action User\\AddBlogComment` will create `app/Actions/User/AddBlogComment.php` with the namespace of `App\Actions\User`.
26+
27+
All of the "make" commands follow this convention.
28+
29+
This does not force any naming conventions on you. What you enter is what you get. If you want your contracts to end with `Contract` then you must enter it as the name, ie: `CreatesNewBlogPostContract`. If you want Enums to end with "Enum", name it like `BlogPostStatusEnum`. Personally, I don't think it's necessary to add "Contract" or "Enum" or anything to the end of most of these, as they are already included in the path and namespace and Laravel doesn't seem to do it themselves. I do like to add "Service" to the end of my services, but to each their own :)
30+
31+
The following list of actions/commands are supported:
32+
33+
### Clear Logs
34+
35+
Delete all of the `*.log` files found in the `storage/logs` directory:
36+
37+
`php artisan clear:logs`
38+
39+
### Make Action
40+
41+
`php artisan make:action SomeAction`
42+
43+
**Example:** `php artisan make:action AddBlogPost`
44+
45+
By default, this will generate "invokable actions", which allows you to typhint the action in your method and use it's parameter as a function/method. I find this the best use-case for actions and Laravel Fortify uses them mostly like this as well, which is why it's the default.
46+
47+
```php
48+
public function store(Request $request, AddBlogPost $addBlogPostAction)
49+
{
50+
$blogPost = $addBlogPostAction($request, $user);
51+
52+
// ...
53+
}
54+
```
55+
56+
If you don't want invokable actions, you can pass a `--handle` option which creates a `handle()` method instead of the `__invoke()` magic method. This is ideal for when your actions are being used within Pipelines, which is why it automatically has the `$request` and `$next` params.
57+
58+
### Make Contract
59+
60+
`php artisan make:contract SomeContract`
61+
62+
**Example:** `php artisan make:contract BlogSystem`
63+
64+
### Make Enum
65+
66+
`php artisan make:enum SomeEnum`
67+
68+
**Example:** `php artisan make:enum BlogPostStatus`
69+
70+
**Enums require PHP version 8.1 or higher.**
71+
72+
**Note:** The generated enum is just an example of a basic active/inactive status using an integer. It will cast the status as 1 or 0 in/out of the database and includes a label method for converting it to a string representation (ie: for a dropdown in your view). It can be any valid enum type, integer is just provided as a starting example.
73+
74+
### Make Service
75+
76+
`php artisan make:service SomeService`
77+
78+
**Example:** `php artisan make:service BlogPostService`
79+
80+
**What is a service?** Services are basically a fancy name for a specialized helper class. This isn't to be confused with a Service Provider. It allows you to get a lot of your code out of the controller, improving readability, and allows you to write more fine-grained tests without repeating code. If an Action or Job isn't applicable, you may want to use a Service.
81+
82+
### Make Trait
83+
84+
`php artisan make:trait SomeTrait`
85+
86+
**Example:** `php artisan make:trait BlogPost`
87+
88+
### Make View
89+
90+
`php artisan make:view some-name`
91+
92+
The name can be nested in sub-directories relative to the views directory.
93+
94+
`php artisan make:view user/settings` will generate `/resources/views/user/settings.blade.php`
95+
96+
The name will be converted to kebab case. So a name of `someName` will be generate `some-name.blade.php`. It will not convert the path (if passed), just the name. ie: `somePath/someName` will generate `somePath/some-name.blade.php`.
97+
98+
#### View Layouts
99+
100+
The `make:view` command does, in a way, support layouts. Since there are a few ways to use layouts in Laravel (ie: the old `@extend` method and new components), I thought it would be better to rely on stubs for your various needs. This way it not only handles layouts, but any number of alternate view file variations.
101+
102+
Passing the `--stub` option allows you to define the stub to use:
103+
104+
```bash
105+
php artisan make:view some-name --stub=some-stub
106+
```
107+
108+
The stub option supports nested paths, relative to the `app/Console/stubs` directory. So passing `--stub=views/admin-layout` will use the `app/Console/stubs/views/admin-layout.stub` stub file. This allows you to keep the view stubs separate from the other make command stubs that you will read about in the "Custom Stubs" section below.
109+
110+
**Note:** If you don't pass the `--stub` option, the default `make-stub.stub` file is used. To override it, you must create your own `make-view.stub` file in `app/Console/stubs`. If you want all of your view stubs organized separately in `app/Console/stubs/views` but it drives you mad that the default stub is outside of that in the `stubs` directory, you could create `default.stub` in the `stubs/views` directory. However, you would always have to pass `--stub=default`. If you don't, it uses the default `make-view.stub`, whether it be the one included in this package or an overrode one.
111+
112+
## Custom Stubs
113+
114+
You can override the stubs and use your own for file generation. Refer to the stubs included in this project's source code.
115+
116+
It will first look in `/app/Console/stubs/` to see if the stub exists. If not, it will use the default ones provided by this package. So simply copy the stub from this package to `/app/Console/stubs/` and modify it to your liking.
117+
118+
## Requirements
119+
120+
This package requires Laravel 8 or higher. It should work with whatever PHP version you are running that satisfies your Laravel version, which is most likely PHP v7.3 or higher.
121+
122+
Enums, however, require PHP 8.1 or higher.
123+
124+
## Contributing
125+
126+
Contributions are welcome. Keep in mind, the goal of this package is to add additional commands that Laravel should come out of the box with, but for some reason, doesn't. I don't want to over complicate this and add all kinds of extra features.
127+
128+
Laravel has many "make" commands already... but why does it still not make traits, actions, or contracts? They are all used in their official packages.

composer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "cyberpunkcodes/laravel-extended-commands",
3+
"description": "Extends the Laravel commands for developers",
4+
"keywords": ["laravel", "extended", "commands", "artisan", "make"],
5+
"license": "MIT",
6+
"authors": [
7+
{
8+
"name": "CyberPunkCodes"
9+
}
10+
],
11+
"minimum-stability": "dev",
12+
"require": {
13+
"php": "^7.3|^8.0",
14+
"laravel/framework": "^8.0|^9.0"
15+
},
16+
"autoload": {
17+
"psr-4": {
18+
"CyberPunkCodes\\ExtendedCommands\\": "src"
19+
}
20+
},
21+
"config": {
22+
"sort-packages": true
23+
},
24+
"extra": {
25+
"laravel": {
26+
"providers": [
27+
"CyberPunkCodes\\ExtendedCommands\\Providers\\ExtendedCommandsServiceProvider"
28+
]
29+
}
30+
}
31+
}

src/Console/Commands/ClearLogs.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace CyberPunkCodes\ExtendedCommands\Console\Commands;
4+
5+
use Illuminate\Console\Command;
6+
use Illuminate\Support\Facades\File;
7+
8+
class ClearLogs extends Command
9+
{
10+
/**
11+
* The console command name.
12+
*
13+
* @var string
14+
*/
15+
protected $name = 'clear:logs';
16+
17+
/**
18+
* The console command description.
19+
*
20+
* @var string
21+
*/
22+
protected $description = 'Delete all log files in the storage/logs directory';
23+
24+
/**
25+
* Create a new command instance.
26+
*
27+
* @return void
28+
*/
29+
public function __construct()
30+
{
31+
parent::__construct();
32+
}
33+
34+
public function handle()
35+
{
36+
if (! File::delete(File::glob(storage_path(('logs/*.log'))))) {
37+
$this->error("Error deleting one or more log files!");
38+
}
39+
40+
$this->info("Log files have been deleted!");
41+
}
42+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
namespace CyberPunkCodes\ExtendedCommands\Console\Commands;
4+
5+
use Illuminate\Console\GeneratorCommand;
6+
use Symfony\Component\Console\Input\InputOption;
7+
8+
class MakeAction extends GeneratorCommand
9+
{
10+
/**
11+
* The console command name.
12+
*
13+
* @var string
14+
*/
15+
protected $name = 'make:action';
16+
17+
/**
18+
* The name and signature of the console command.
19+
*
20+
* @var string
21+
*/
22+
protected $signature = 'make:action {name} {--handle : Use a handle method instead of an invokable action}';
23+
24+
/**
25+
* The console command description.
26+
*
27+
* @var string
28+
*/
29+
protected $description = 'Create a new action class';
30+
31+
/**
32+
* The type of class being generated.
33+
*
34+
* @var string
35+
*/
36+
protected $type = 'Action';
37+
38+
/**
39+
* Get the stub file for the generator.
40+
*
41+
* @return string
42+
*/
43+
protected function getStub()
44+
{
45+
return $this->option('handle')
46+
? $this->resolveStubPath('make-action-handle.stub')
47+
: $this->resolveStubPath('make-action.stub');
48+
}
49+
50+
/**
51+
* Resolve the fully-qualified path to the stub.
52+
*
53+
* @param string $stub
54+
* @return string
55+
*/
56+
protected function resolveStubPath($stub)
57+
{
58+
return file_exists($customPath = $this->laravel->basePath(trim('/app/Console/stubs/' . $stub, '/')))
59+
? $customPath
60+
: __DIR__ . '/../../../stubs/' . $stub;
61+
}
62+
63+
/**
64+
* Get the default namespace for the class.
65+
*
66+
* @param string $rootNamespace
67+
* @return string
68+
*/
69+
protected function getDefaultNamespace($rootNamespace)
70+
{
71+
return $rootNamespace . '\Actions';
72+
}
73+
74+
/**
75+
* Get the console command options.
76+
*
77+
* @return array
78+
*/
79+
protected function getOptions()
80+
{
81+
return [
82+
['handle', null, InputOption::VALUE_NONE, 'Create an action with a handle method instead'],
83+
];
84+
}
85+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
namespace CyberPunkCodes\ExtendedCommands\Console\Commands;
4+
5+
use Illuminate\Console\GeneratorCommand;
6+
7+
class MakeContract extends GeneratorCommand
8+
{
9+
/**
10+
* The console command name.
11+
*
12+
* @var string
13+
*/
14+
protected $name = 'make:contract';
15+
16+
/**
17+
* The console command description.
18+
*
19+
* @var string
20+
*/
21+
protected $description = 'Create a new contract class';
22+
23+
/**
24+
* The type of class being generated.
25+
*
26+
* @var string
27+
*/
28+
protected $type = 'Contract';
29+
30+
/**
31+
* Get the stub file for the generator.
32+
*
33+
* @return string
34+
*/
35+
protected function getStub()
36+
{
37+
return $this->resolveStubPath('make-contract.stub');
38+
}
39+
40+
/**
41+
* Resolve the fully-qualified path to the stub.
42+
*
43+
* @param string $stub
44+
* @return string
45+
*/
46+
protected function resolveStubPath($stub)
47+
{
48+
return file_exists($customPath = $this->laravel->basePath(trim('/app/Console/stubs/' . $stub, '/')))
49+
? $customPath
50+
: __DIR__ . '/../../../stubs/' . $stub;
51+
}
52+
53+
/**
54+
* Get the default namespace for the class.
55+
*
56+
* @param string $rootNamespace
57+
* @return string
58+
*/
59+
protected function getDefaultNamespace($rootNamespace)
60+
{
61+
return $rootNamespace . '\Contracts';
62+
}
63+
}

0 commit comments

Comments
 (0)