ComponentMakeCommand.php
TLDR
The ComponentMakeCommand.php
file in Illuminate\Foundation\Console
namespace is a class that creates a new view component class. It extends the GeneratorCommand
class and uses the CreatesMatchingTest
trait. The class handles the console command execution, writes the view for the component, builds the component class, resolves the stub path, sets the default namespace, and provides console command options.
Methods
handle
This method executes the console command. If the view
option is provided, it calls the writeView
method. If the parent::handle
method returns false
and the force
option is not provided, it returns false
. Otherwise, it calls the writeView
method.
writeView($onSuccess = null)
This method writes the view for the component. It generates the file path based on the view
option, creates the necessary directory if it does not exist, checks if the view file already exists, and writes the view content. If an onSuccess
callback is provided, it is called after writing the view.
buildClass($name)
This method builds the class with the given name. If the inline
option is provided, it replaces the DummyView
and {{ view }}
placeholders with the inline view content. Otherwise, it replaces the placeholders with the view reference. It then calls the parent buildClass
method and returns the result.
getView()
This method returns the view name relative to the components directory. It replaces the backslashes in the argument name with forward slashes, converts each part to kebab case, and joins them with dots.
getStub()
This method returns the stub file path for the generator. It resolves the path using the resolveStubPath
method.
resolveStubPath($stub)
This method resolves the fully-qualified path to the stub. If the stub file exists at a custom path in the application, it returns the custom path. Otherwise, it returns the default stub path relative to the current file.
getDefaultNamespace($rootNamespace)
This method returns the default namespace for the generated class. It appends the View\Components
namespace to the root namespace.
getOptions()
This method returns an array of console command options. It includes options for creating the class even if it already exists (force
), creating an inline view component (inline
), and creating an anonymous component with only a view (view
).
<?php
namespace Illuminate\Foundation\Console;
use Illuminate\Console\Concerns\CreatesMatchingTest;
use Illuminate\Console\GeneratorCommand;
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Str;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputOption;
#[AsCommand(name: 'make:component')]
class ComponentMakeCommand extends GeneratorCommand
{
use CreatesMatchingTest;
/**
* The console command name.
*
* @var string
*/
protected $name = 'make:component';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Create a new view component class';
/**
* The type of class being generated.
*
* @var string
*/
protected $type = 'Component';
/**
* Execute the console command.
*
* @return void
*/
public function handle()
{
if ($this->option('view')) {
$this->writeView(function () {
$this->components->info($this->type.' created successfully.');
});
return;
}
if (parent::handle() === false && ! $this->option('force')) {
return false;
}
if (! $this->option('inline')) {
$this->writeView();
}
}
/**
* Write the view for the component.
*
* @param callable|null $onSuccess
* @return void
*/
protected function writeView($onSuccess = null)
{
$path = $this->viewPath(
str_replace('.', '/', 'components.'.$this->getView()).'.blade.php'
);
if (! $this->files->isDirectory(dirname($path))) {
$this->files->makeDirectory(dirname($path), 0777, true, true);
}
if ($this->files->exists($path) && ! $this->option('force')) {
$this->components->error('View already exists.');
return;
}
file_put_contents(
$path,
'<div>
<!-- '.Inspiring::quotes()->random().' -->
</div>'
);
if ($onSuccess) {
$onSuccess();
}
}
/**
* Build the class with the given name.
*
* @param string $name
* @return string
*/
protected function buildClass($name)
{
if ($this->option('inline')) {
return str_replace(
['DummyView', '{{ view }}'],
"<<<'blade'\n<div>\n <!-- ".Inspiring::quotes()->random()." -->\n</div>\nblade",
parent::buildClass($name)
);
}
return str_replace(
['DummyView', '{{ view }}'],
'view(\'components.'.$this->getView().'\')',
parent::buildClass($name)
);
}
/**
* Get the view name relative to the components directory.
*
* @return string view
*/
protected function getView()
{
$name = str_replace('\\', '/', $this->argument('name'));
return collect(explode('/', $name))
->map(function ($part) {
return Str::kebab($part);
})
->implode('.');
}
/**
* Get the stub file for the generator.
*
* @return string
*/
protected function getStub()
{
return $this->resolveStubPath('/stubs/view-component.stub');
}
/**
* Resolve the fully-qualified path to the stub.
*
* @param string $stub
* @return string
*/
protected function resolveStubPath($stub)
{
return file_exists($customPath = $this->laravel->basePath(trim($stub, '/')))
? $customPath
: __DIR__.$stub;
}
/**
* Get the default namespace for the class.
*
* @param string $rootNamespace
* @return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\View\Components';
}
/**
* Get the console command options.
*
* @return array
*/
protected function getOptions()
{
return [
['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the component already exists'],
['inline', null, InputOption::VALUE_NONE, 'Create a component that renders an inline view'],
['view', null, InputOption::VALUE_NONE, 'Create an anonymous component with only a view'],
];
}
}