Laravel Not able to dispatch job from crontab - php

if i use this code in a controller queuing works well
$job=(new ReProcessShipment($single_data->request_data))->delay(2);
$this->dispatch($job);
but using same code in crontab error throws
Method App\Console\Commands\AddPreProcess::dispatch does not exist. {"exception":"[object] (BadMethodCallException(code: 0):
Method App\Console\Commands\AddPreProcess::dispatch does not exist.
tried to use it like
$job=(new ReProcessShipment($single_data->request_data))->delay(2);
ReProcessShipment::dispatch($job);
then get error
Object of class App\Jobs\ReProcessShipment could not be converted to string {"exception":"[object] (ErrorException(code: 0): Object of class App\Jobs\ReProcessShipment could not be converted to string at
am not able to process job queue from a cronjob any suggestion would be great.

You can dispatch a job by calling static dispatch method on the job class and passing the job's constructor arguments to the dispatch method, like this:
ReProcessShipment::dispatch($single_data->request_data)->delay(2);
Ensure that you are using the Illuminate\Foundation\Bus\Dispatchable trait to be able to call dispatch on the job class, e.g.:
use Illuminate\Foundation\Bus\Dispatchable;
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, ...
If you have a look at the source you'll see that the static dispatch function creates the job for you using the job's parameters, so you don't need to create the job before you dispatch it. This is the source of the dispatch function:
public static function dispatch()
{
return new PendingDispatch(new static(...func_get_args()));
}
So it essentially transforms this:
ReProcessShipment::dispatch($single_data->request_data);
into this:
new PendingDispatch(new ReProcessShipment($single_data->request_data));

Related

How do I inject a request into a facade class in Laravel?

So I have the following class that's a facade:
namespace App\Helpers;
use App\Http\Requests\HomepageRequest;
class Params {
public function __construct(HomepageRequest $request) {
}
Then I have the ParamsServiceProvider class which instantiates the facade class on script startup:
public function register()
{
//
App::bind('params', function() {
return new Params();
});
}
edit: here is the actual facade for the Params class
use Illuminate\Support\Facades\Facade;
class Params extends Facade {
protected static function getFacadeAccessor() {
return 'params';
}
}
This all works fine, the class is instantiated properly, however, it doesn't seem to inject the request object in the constructor like it would in a controller class. Is there a way to inject the request into a facade class like you would in a controller? With the current code, I get the following error:
Too few arguments to function App\Helpers\Params::__construct(), 0
passed in /var/www/v4api/html/app/Providers/ParamsServiceProvider.php
on line 21 and exactly 1 expected
I want to avoid having to manually pass the request input into the class and just have it automatically be injected in the constructor. Any help that you guys can give would be appreciated!
Looks like this worked out:
In the ParamsServiceProvider, instead of using App::bind to instantiate the Params class, do this instead:
public function register()
{
App::alias(Params::class, 'params');
}
then the request object will be injected properly into the facade.
The class you've posted isn't actually a Facade - it's just a regular class.
Because you've type-hinted it's dependencies you don't need to tell Laravel how to create an instance of it - it can work it out all by itself.
You can either inject that class into a controller method (where Laravel will new it up for you), or you can call app(App\Helpers\Params::class) and it will return a new instance of the class for you.
Read more on creating facade classes if you want to create an actual facade. Alternatively you can create a realtime facade - where you instead reference Facades\App\Helpers\Params::foo() and Laravel will let you use the method as if you had an instance of that class.
You have a number options here - point the facade straight to the underlying class and let Laravel work out how to build it, explicitly bind it to the container, or use a realtime facade. Let's go through each.
class Params extends Facade
{
protected static function getFacadeAccessor()
{
return \App\Helpers\Params::class;
}
}
This option points the facade straight to the class you intend it to be a facade for and Laravel will work out the rest.
Alternatively, you can keep it as params and instead fix the binding in the container.
The first example use's Laravel's container to make an instance of the class and return it. Laravel can automatically reflect the class and inject it's dependencies.
App::bind('params', function ($app) {
return $app->make(Params::class);
});
The second example explicitly builds the instance the way you desire, which is just additional code for you to maintain.
App::bind('params', function() {
return new Params(new HomepageRequest);
});
The final option - as mentioned in the earlier answer - is to use a realtime facade and skip the manual binding entirely. You can learn more about realtime facades in the docs.

Extending the class with an interface AkeneoPimClientInterface?

How to extend generated command in Symfony with use Akeneo\Pim\AkeneoPimClientInterface ?
I have generated a command using php app/console generate:command and I got this class:
class AppTriggerBuildCommand extends ContainerAwareCommand
Then developed it to the point when I need all the categories from the API. Seamlessly it is really an easy question, how can I use AkeneoPimClientInterface in the command.
I want to use it something like this.
$categories = $this->apiClient->getCategoryApi()->all();
And the apiClient in here comes inside the _contruct metod
public function __construct(AkeneoPimClient $apiClient, AkeneoLocaleMapper $mapper) {
$this->apiClient = $apiClient;
$this->mapper = $mapper;
}
And in use
use Akeneo\Pim\AkeneoPimClientInterface as AkeneoPimClient;
But when I tried to put it inside the _construct method in a command it want to use the parent _construct and it just can't see the generated command.
Could anyone help me ?
php app/console trigger build -vvv
[Symfony\Component\Console\Exception\CommandNotFoundException]
Command "trigger" is not defined.
Exception trace:
() at /var/www/html/iclei/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:526
Symfony\Component\Console\Application->find() at /var/www/html/iclei/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:94
Symfony\Bundle\FrameworkBundle\Console\Application->find() at /var/www/html/iclei/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:190
Symfony\Component\Console\Application->doRun() at /var/www/html/iclei/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:84
Symfony\Bundle\FrameworkBundle\Console\Application->doRun() at /var/www/html/iclei/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:117
Symfony\Component\Console\Application->run() at /var/www/html/iclei/app/console:27
Since you extend the ContainerAwareCommand you have access to Symfony's Service Container to fetch the client like this (you might have to replace the fully qualified class name with a service id, I'm not 100% sure):
$this->container->get('Akeneo\Pim\AkeneoPimClientInterface');
If you want to use the constructor (which I encourage you to do), you are almost there. You just have to also call the parent constructor as well:
public function __construct(AkeneoPimClient $apiClient, AkeneoLocaleMapper $mapper)
{
parent::__construct();
$this->apiClient = $apiClient;
$this->mapper = $mapper;
}
Both ways should work, but the latter allows you to move away from the ContainerAwareCommand to the more generic ContainerCommand, which will help you with Symfony 4 where services in the container will be private by default and therefore you can not just simply get them from the container like in the first version.
edit regarding the command name: You can specify the name of your command as argument to parent::__construct() and also set it via the configure() method, you need to override. In there you can just call, e.g. $this->setName('trigger-build');. Be careful not to use spaces, as Symfony will treat those as separate arguments. So trigger is the name of the command and build is the first argument you "feed" to the command.

How to run a method of a class as a cron task in laravel 5.1

Look I have a class that looks like this, i want to cache some info every day in a cron job with this method cacheTopFilters in laravel 5.1
<?php
namespace namescape/of/the/class;
class FilterTypeCacheService extends BaseService implements IFilterTypeCacheService
{
private $searchFilterService;
private $filterCacheHandler;
function __construct(SearchFilterService $searchFilterService, IFilterTypeCacheHandler $filterCacheHandler){
$this->searchFilterService = $searchFilterService;
$this->filterCacheHandler = $filterCacheHandler;
}
public function cacheTopFilters($type,$keyValuePair,$limit){
$filters = $this->searchFilterService->getAllFilters($type,$keyValuePair);
$this->filterCacheHandler->deleteFiltersBulkFromCache();
$this->filterCacheHandler->SaveFiltersBulk($filters,$type);
}
public function getTopFilters(){
$topFilters = $this->filterCacheHandler->getCachedTopFilters();
return $topFilters;
}
}
As they have dependency injection how can i accomplished to called that method on the app/console/kernel on the schedule method?
You want to take a look at Task Scheduling:
https://laravel.com/docs/5.1/scheduling#defining-schedules
In the App\Console\Kernel class, inside the schedule function, you can schedule anything at all like this:
$schedule->call(function () {
doSomething();
})->daily();
Assuming you have the scheduler setup (system cron job every minute) you should be all set.
If you have a class you need to instantiate, with dependencies injected, you can always use the global app() helper function that Laravel gives you:
$schedule->call(function () {
app(\namespace\of\the\class::class)->cacheTopFilters(...);
})->daily();
That's assuming that Laravel knows how to handle your dependencies. I see that one of your dependencies is a contract (interface) so I'm assuming you've already bound the concrete instance in the Laravel IoC.

Laravel implements Shouldqueue different queue

In laravel you can call the ShouldQueue interface like so
class ProfileWasCreated extends Event implements ShouldQueue
By default this will queue the event on the default queue, but I can't seem to figure out how to queue this event on a different queue with the name email.
$this->onQueue('emails');
Add the line above in your constructor for the email class. It would set the queue name. Then you can just use the Mail::send() function and it would queue on the "emails" queue.
You can specify the queue where a job should be sent by calling onQueue() on the job object, e.g.:
$job = new MyJob();
$job->onQueue('queue_name');
$this->dispatch($job);
onQueue method is provided by Queueable trait - it should be already included in your base App\Jobs\Job class by default.
dispatch() method is provided by ** DispatchesJobs** trait that you should include in the class that you want to dispatch jobs.
Have a look here for more details on how to use jobs and queues: http://laravel.com/docs/5.1/queues#dispatching-jobs-from-requests

Specify queue to push on in an Event Class

I'm working with multiple queues and want to push an event to another queue than the default one.
I have a standard event class that implements ShouldQueue, but how can I specify the queue this event will be pushed to?
I have tried with
class NewMessageArrived extends Event implements ShouldQueue
{
use SerializesModels;
protected $queue = 'redis';
....
but that doesn't do what I want. Is there a way to do this?
On Listener:
public $queue = 'notifications'; //Queue Name
public function queue(QueueManager $handler, $method, $arguments)
{
$handler->push($method, $arguments, $this->queue);
}
be happy =)
After spending some quality time with the Laravel source code, I'm fairly sure this isn't possible.
Events/Dispatcher.php's createClassCallable checks if your class has implements ShouldQueue, and if so, calls Dispatcher's createQueuedHandlerCallable() method, when in turn queues your event with a call to $this->resolveQueue()->push().
The problem is that push's third argument is what queue to push onto, and that argument is not passed. So it will always use the default queue, so you have no way of specifying an alternate default one.
I recommend queueing the event yourself with something like:
Queue::push(
function() {
event(new NewMessageArrived());
},
'',
'my-queue'
);
public function __construct()
{
$this->queue = 'high';
}
I tried to override $queue because it public but, laravel 5.6 return errors.
So, set the queue in the class construct is the shortest working solution i found.

Categories