I'm not sure why __call doesn't work in this scenario. Does it have to do with how Command is implemented or am I doing something wrong?
class MyCommand extends Command
{
protected $reports = [];
/**
* The console command name.
*
* #var string
*/
protected $name = 'test';
/**
* The console command description.
*
* #var string
*/
protected $description = '';
public function __call($methodName, $args) {
return call_user_func_array($methodName, $args);
}
}
You can override the execute method if you are trying to extend the base Command class. This will essentially
/**
* Execute the console command.
*
* #param \Symfony\Component\Console\Input\InputInterface $input
* #param \Symfony\Component\Console\Output\OutputInterface $output
* #return int
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
// your custom logic here to be ran before all handlers, e.g.
// setting up env variables, prompting user, ...
$method = method_exists($this, 'handle') ? 'handle' : '__invoke';
return (int) $this->laravel->call([$this, $method]);
}
Related
could you help me with a problem that I have? I have created a command with php artisan make:command to generate repository type classes from existing models. The problem is that I need that instead of generating a single file from a stub, I need to generate 2 or more files. I can't find documentation regarding the subject. Currently what I have achieved is that I only generate a single file from a template.
<?php
namespace App\Console\Commands;
use Illuminate\Console\GeneratorCommand;
use Symfony\Component\Console\Input\InputArgument;
class MakeRepository extends GeneratorCommand
{
/**
* The console command name.
*
* #var string
*/
protected $name = 'make:repository';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Create a new repository';
/**
* The type of class being generated.
*
* #var string
*/
protected $type = 'Repository';
/**
* #inheritDoc
*/
protected function getStub()
{
return __DIR__ . '/stubs/MakeRepository/ModelRepositoryInterface.stub';
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the model to which the repository will be generated'],
];
}
/**
* Get the default namespace for the class.
*
* #param string $rootNamespace
* #return string
*/
protected function getDefaultNamespace($rootNamespace)
{
return $rootNamespace.'\Repositories';
}
}
EDIT #1
I have 2 stub files inside the directory:
app/Console/Commands/stubs/MakeRepository
ModelRepository.stub
ModelRepositoryInterface.stub
I want that when you execute the command...ex: php artisan make:repository Blog, these 2 files are created in the following directory:
/app/Repositories/Blog/BlogRepository.php
/app/Repositories/Blog/BlogRepositoryInterface.php
You can write a new command to create repository interface, and then call it in MakeRepository.
I think this method is in line with SRP.
// In MakeRepository.php
// Override handle method
public function handle()
{
if (parent::handle() === false && ! $this->option('force')) {
return false;
}
if ($this->option('interface')) {
$this->call('make:repository-interface', ['name' => $this->getNameInput() . 'Interface']);
}
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return [
['name', InputArgument::REQUIRED, 'The name of the model to which the repository will be generated'],
['interface', 'i', InputOption::VALUE_NONE, 'Create a new interface for the repository'],
];
}
You can also refer to the code of make model of official.
https://github.com/laravel/framework/blob/6.x/src/Illuminate/Foundation/Console/ModelMakeCommand.php
you can use glob to get your stubs in array then loop over them to create the multiple files
foreach(glob(stubs_path('stubs/Repository/*.stub') as $stub){
copy(stubs_path('stubs/Repository/'.$stub), $repositoryLocation . 'Repository.php');
}
i have created following command in laravel using command php artisan make:command RedisDataListener
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class RedisDataListener extends Command {
/**
* The name and signature of the console command.
*
* #var string
*/
protected $signature = 'listen:subscribe';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Subscribe to redis channel for listening events';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct() {
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function handle() {
$value = cache()->has('tracking_application:mykey') ? cache()->get('tracking_application:mykey') : 'no';
print_r(array(
$value
));
}
}
but when i'm using cache()->get('key') it is not working. Same function works fine when i use in controller.
i'm using redis as the cache server.
also tried with cache::get() but nothing happen.
i set up a cronjob in cpanel, i'm using laravel 4.2. i also set to send the cronjob to my email and below yellow part is the error i received in email.
[InvalidArgumentException]
There are no commands defined in the "user" namespace.
//laravel command.php
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class CronDelFilesCommand extends Command {
/**
* The console command name.
*
* #var string
*/
protected $name = 'user:active';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Command description.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function fire()
{
echo "aaa";
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return array(
);
}
/**
* Get the console command options.
*
* #return array
*/
protected function getOptions()
{
return array(
array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
);
}
}
//command in cpanel
* * * * * /usr/bin/php /home/project/public_html/artisan user:active > /home/project/public_html/log.txt
what's wrong? what's the error mean?
UPDATED
thanks to #KristianHareland i use wget. :)
I think you forget to add this command to artisan app/start/artisan.php.
You shoud wright:
Artisan::add(new CronDelFilesCommand());
And don't forget about composer dump-autoload
More info you can find here.
I need a custom command in my php artisan.
I have created the command file via artisan shell.
But when I execute it via php artisan it throws it as undefined.
It is also confusing for me how to add arguments to my command.
Here is my whole command file:
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class createLibrarySet extends Command
{
/**
* The console command name.
*
* #var string
*/
protected $name = 'createLibrarySet';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Creates a Library Set.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function fire()
{
$dir = mkdir(app_path()."/".library."/".$this->library_name);
$coreName = $this->library_name;
$serivceProvider = $coreName."."."ServiceProvider.php";
$library = $coreName."."."Library.php";
$facade = $coreName."."."Facade.php";
$interface = $coreName."."."Interface.php";
fopen($dir."/".$library, "w");
fopen($dir."/".$facade, "w");
fopen($dir."/".$serivceProvider, "w");
fopen($dir."/".$interface, "w");
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return array(
array('example', InputArgument::REQUIRED, 'An example argument.'),
);
}
/**
* Get the console command options.
*
* #return array
*/
protected function getOptions()
{
return array(
array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
);
}
}
You have to add the command to your app/start/artisan.php:
Artisan::resolve('createLibrarySet');
Now you should be able to see in the
php artisan
listing.
To get your arguments, you just have to:
$email = $this->argument('email');
And options
$force = $this->option('force');
My IDE warns me that $this is not allowed within a closure before PHP 5.4. Is there a workaround for this without upgrading PHP from 5.3.10 ? See fire() method below:
<?php
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
class UpdateItemImageSizes extends Command {
/**
* The console command name.
*
* #var string
*/
protected $name = 'namespace:updateimagesizes';
/**
* The console command description.
*
* #var string
*/
protected $description = 'Updates image size information in the items table.';
/**
* Create a new command instance.
*
* #return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* #return mixed
*/
public function fire()
{
$this->info('Starting chunk');
Item::chunk(1000, function($items)
{
foreach ($items as $item)
{
$this->info($item->img);
}
}
);
}
/**
* Get the console command arguments.
*
* #return array
*/
protected function getArguments()
{
return array(
//array('example', InputArgument::REQUIRED, 'An example argument.'),
);
}
/**
* Get the console command options.
*
* #return array
*/
protected function getOptions()
{
return array(
array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null),
);
}
}
If info method is public you can do:
//...
public function fire()
{
$self = $this;
$self->info('Starting chunk');
Item::chunk(1000, function($items) use ($self)
{
foreach ($items as $item)
{
$self->info($item->img);
}
}
);
}
//...
If info is private you can't and you need to upgrade to php 5.4, because in PHP 5.3 the context in the closure is not the same of the object context.