In a Laravel job I have:
use Spatie\Valuestore\Valuestore;
and
public function __construct()
{
$this->settings = Valuestore::make(storage_path('app/settings.json'));
}
and
public function handle()
{
if($this->settings->get('foo') == 'test') {
etc...
and on this I get an error Undefined property App\Jobs\MyJobName::$settings. What is going wrong?
Even if I do this:
public function handle()
{
$this->settings = Valuestore::make(storage_path('app/settings.json'));
if($this->settings->get('foo') == 'test') {
etc...
I get the same error.
Update based on the comments
MyJobName is called in a custom artisan command, that happens to also use Valuestore but I assume that would unrelated.
In the class CustomCommand:
use Spatie\Valuestore\Valuestore;
and
public function __construct()
{
parent::__construct();
$this->settings = Valuestore::make(storage_path('app/settings.json'));
}
and
public function handle()
{
if($this->settings->get('foo') == 'test') // This works in this custom command!
{
$controller = new MyController;
MyJobName::dispatch($controller);
}
}
So in CustomCommand I use Valuestore in exactly the same way as in MyJobName but in the latter it doesn't work.
As per one of the comments: I do not make $this->settings global as I don't do that in CustomCommand either and it works fine there.
Update 2
If I add protected $settings; above the __construct() function as per the comments it still doesn't work, same error.
Just declare the settings property as public in your Job Class.
public $settings;
public function __construct()
{
$this->settings = Valuestore::make(storage_path('app/settings.json'));
}
I recently had this error. I've tried to make the variables public, delete all the variable inside the Jobs class and even rename and delete the class itself. But it didn't work.
Shortly, I run this artisan command php artisan optimize:clear to clear all the caches, views, routes, etc. And it somehow solve the problem about variable in my problem. For anyone who is still have this OP's problem, give a try to my solution above.
If you use JOB by QUEUE, you need all the requests or SQL queries to do by the method handle
public function handle()
{
$this->settings = Valuestore::make(storage_path('app/settings.json'));
....
}
Because the constructor works when you make the object of class, and this object is serialized and stored in the database and after the unserialization and the handle is triggered.
You may need to restart your queue worker
From Laravel documentation
Remember, queue workers are long-lived processes and store the booted application state in memory. As a result, they will not notice changes in your code base after they have been started. So, during your deployment process, be sure to restart your queue workers.
If you use a daemon php artisan queue:restart
If you use queue:work on your bash hit Ctrl+C then again php artisan queue:work should be enough
Related
I have registered a Paypal service provider:
App\Providers\PaypalHelperServiceProvider::class,
and, when I type hint it in my controller it properly resolves:
public function refund(Request $request, PaypalHelper $paypal) {...
Here is my provider class:
class PaypalHelperServiceProvider extends ServiceProvider
{
protected $defer = true;
public function register()
{
$this->app->bind('App\Helpers\PaypalHelper', function() {
$test = 'test';
return new PaypalHelper();
});
}
public function provides()
{
$test = 'test';
return [App\Helpers\PaypalHelper::class];
}
}
Everything works as expected. Now I wanted to be able to modify controller to take a PayPal interface. I would then update my service provider to conditionally pass in either the real class or a mock one for testing, using the APP_ENV variable to determine which one to use. I put some debuggers into the service provider class and could not get it to ever go in. I thought perhaps that it only loads them on need, so I put a breakpoint inside my controller. The class did resolve, but it still never went into the service provider class! Can someone explain to me why this is the case? Even when I modified the code to pass in a different class type it did not pick up.
EDIT:
Here is the code flow I see when I debug this:
ControllerDispatcher -> resolveClassMethodDependencies -> resolveMethodDependencies -> transformDependency. At this point we have the following laravel code in the RouteDependencyResolveerTrait:
protected function transformDependency(ReflectionParameter $parameter, $parameters, $originalParameters)
{
$class = $parameter->getClass();
// If the parameter has a type-hinted class, we will check to see if it is already in
// the list of parameters. If it is we will just skip it as it is probably a model
// binding and we do not want to mess with those; otherwise, we resolve it here.
if ($class && ! $this->alreadyInParameters($class->name, $parameters)) {
return $this->container->make($class->name);
}
}
Since getClass() always resolves to the interface name, when we call container->make(), it always fails with
Target [App\Helpers\PaypalHelperInterface] is not instantiable.
Change
$this->app->bind('App\Helpers\PaypalHelper', function() {
$test = 'test';
return new PaypalHelper();
});
To
if (app()->environment('testing')) {
$this->app->bind(
PaypalHelperInterface::class,
FakePaypalHelper::class
)
} else {
$this->app->bind(
PaypalHelperInterface::class,
PaypalHelper::class
);
}
I finally found out the issue. My problem was that my provider wasn't being picked up at all. Here was the solution
composer dumpautoload
php artisan cache:clear
https://laravel.io/forum/02-08-2015-laravel-5-service-provider-not-working
currently I have the following set up, a route that is calling a function in my controller that is in turn queuing a job.
//My Route
Route::get('/testJob', 'Controller#testJob');
//My Controller
public function testJob()
{
$job = (new testJob())->delay(5);
$this->dispatch($job);
}
//My job
public function handle()
{
require 'testAPICall.php';
// echo $response;
return $response;
}
//testAPICall.php
$response = 'this is the response';
//Queue After
Queue::after(function (JobProcessed $event) {
echo var_dump($event->data);
});
What I would like to be able to do, is access the response returned by the job in Queue::after, or alternatively, pass a callback into the queue to be execute after the job, again with access to the response from the job.
Is this something that is possible with Laravel Queues, and if so how would I go about this?
Cheers, Jack.
Queue::after() is a global callback, that will run after each job. So this might not what you want.
In your case, I would depend on Events/Listeners to be triggered after finishing the job.
public function handle(Mailer $mailer)
{
//Your code
event(new JobDone($data));
}
Please let me know if you need more details for implementation.
I have done something like yours that log a message "queue.txt" in laravel 5 "app" folder
This code I've got from a youtube video and not my code , but I have tested it successfully
First thing you have to code in "Routes.php" as below
Route::get('/',function()
{
//$queue = Queue::push('LogMessage',array('message'=>'Time: '.time()));
$queue = Queue::later(20,'LogMessage',array('message'=>'Time: '.time()));
return $queue;
});
class LogMessage{
public function fire($job,$data){
File::append(app_path().'/queue.txt',$data['message'].PHP_EOL);
$job->delete();
}
}
Then you can run your project folder using "php -S localhost:8888 -t public"
at the same time you must open a another terminal window in windows or linux environment and pointed to same folder and issue the command "php artisan queue:listen"
I think this will be helpful for you!
I am just learning Laravel 5.1 framework, I find a puzzling problem.
First, I create a model named 'Page', then I create a controller named 'HomeController', the method code is following:
public function index()
{
return view('home')->withPages(Page::all());
}
I cannot find 'withPages()' function, so I find helper function view() return \Illuminate\View\View, so I find 'vendor/laravel/framework/src/Illuminate/View/View.php', there is a "__call()", so I get it.
But I try to delete this function, my site is still normal.
did I find the wrong place? I am very puzzled.
... there is a "__call()", so I get it. But I try to delete this function, my site is still normal. did I find the wrong place? I am very puzzled.
Probably.
Laravel 'compiles' all it's core classes into a single file as a performance optimisation.
Try running php artisan clear-compiled and your site should start failing.
This is how I would do it -
public function index()
{
return view()->with('pages', Page::all());
}
If you want to use withPages method, you need to have a variable $pages set in the method.
So your method would look like:
public function index()
{
pages = Page::all();
return view('home')->withPages($pages);
}
Other two options:
public function index()
{
return view('home')->with('pages', Page::all());
}
or
public function index()
{
pages = Page::all();
return view('home')->with(compact('pages));
}
You can use any of these methods.
I am trying to send emails in laravel 5.1 by using queues. When running queue listen command on terminal,
php artisan queue:listen
Displays below error on terminal,
[Illuminate\Contracts\Queue\EntityNotFoundException]
Queueable entity [App\Setting] not found for ID [].
Values of jobs table is not process. Any idea ?
How can I process my queue ?
I know this question is a few months old, but I'd like to add an observation of mine while encountering this very same error message. It is due to the EventListener (interface of ShouldQueue in this example for asynchronous) not being able to resolve a dependant variable correctly (out of scope or not included in scope of Event object passed through the handle(Event $event) method of EventListener).
For me, this error was fired when I put my code within the __construct block within the EventListener:
public function __construct(Event $event)
{
$localProperty = $event->property
Mail::queue(etc...);
}
public function handle()
{
// Yeah I left this blank... whoops
}
Instead, the handle() method of the EventListener takes an Event interface and when called processes the job in the queue:
In the Event:
public function __construct(Object $ticket, AnotherObject $user)
{
$this->ticket = $ticket;
$this->user = $user;
}
And in Event Listener
class SomeEventListener implements ShouldQueue
{
use InteractsWithQueue;
use SerializesModels;
public function __construct()
{
// Leave me blank!
}
public function handle(Event $event)
{
$someArray = [
'ticket' = $event->ticket,
'user' = $event->user,
];
Mail::queue('some.view', $someArray, function($email) use ($someArray) {
// Do your code here
});
}
}
Although a tad late, I hope this helps someone. Queues are similar to Events (with the exception of Jobs being the main driving force behind Queues), so most of this should be relevant.
Turned out that it was because a model was added to the queue, that has since been deleted.
I am creating a command for my package.
My constructor is:
public function __construct(\Artisan $artisan)
{
parent::__construct();
$this->artisan = $artisan;
}
Protected $artisan property, of course, is present.
In my service provider register() method I have tried several methods for registering the command.
First:
$this->app['custom.command'] = $this->app->share(function ($app)
{
return new CustomCommand(new \Artisan);
});
$this->commands('custom.command');
Second:
$this->app['custom.command'] = $this->app->share(function ($app)
{
return $app->make('CustomCommand');
});
$this->commands('custom.command');
Normally, it is supposed to work. But when I run the command I always get Call to undefined method Illuminate\Support\Facades\Artisan::call() error message as soon as I run $this->artisan->call('migrate') in my fire() method.
However when I write \Artisan::call('migrate') instead of the $this->artisan->call('migrate') everything works fine.
Does someone have an idea what I did wrong?
Thanks in advance.
I think the problem is that you inject the facade of Artisan and not Artisan itself.
Try
public function __construct(Illuminate\Foundation\Artisan $artisan)
and in your service provider:
return new CustomCommand($app['artisan']);