Laravel 8 queue batch callback funktions crash on calling $this Object - laravel

I want to do some specific tasks in the callback functions like logging via print_r() method or calling object methods via $this object. But all that fails so i wonder what the scope of these callback functions is. Its somewhat mysterious. I didnt find anything regarding this via google, i think this feature is too new and hasnt been explored widely.
What works though is calling static class methods like
self::doSomething();
Here is the basic structure from the official doc, added my methods in then and finally callback branches:
$batch = Bus::batch(
$batchedObjects
)->then(function (Batch $batch) {
// All jobs completed successfully...
// this method call does not work
$this->doSomething();
})->catch(function (Batch $batch, Throwable $e) {
// First batch job failure detected...
})->finally(function (Batch $batch) {
// The batch has finished executing...
// this method call works
self::doSomething();
})->onQueue('myQueue')->dispatch();

Related

Calling of afterSave method in application.php file slowing down complete platform and showing memory_limit exceed error

I am calling afterSave method in application.php to perform action on all models saving event. Issue is whenever I using SAVE method inside afterSave method application showing fatal error:
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away
Point is same method working fine in specific model, without any memory exhausted error, I think there is something that need to be fixed over database connection. Below is the code which one I am trying.
//Application.php file
namespace App;
...
...
\Cake\Event\EventManager::instance()->on(
'Model.afterSave',
function (
\Cake\Event\EventInterface $event,
\Cake\Datasource\EntityInterface $entity,
\ArrayObject $options
) {
$auth_data = isset($_SESSION['Auth'])?$_SESSION['Auth']:[];
$ActionLogs = TableRegistry::get('ActionLogs');
$ActionLogsEntity = $ActionLogs->newEmptyEntity();
$ActionLogsEntity->change_log = $change_log;
$ActionLogsEntity->action_taken_by = $auth_data->username;
$ActionLogs->save($ActionLogsEntity); //This statement working fine in specific modelTable
class Application extends BaseApplication
implements AuthenticationServiceProviderInterface
{
...
...
}
Aside from the fact that the code should go into the Application class' bootstrap() method as mentioned in the comments, when you save inside of an afterSave event that listens to all models, then you naturally create a recursion, as saving the log will trigger an afterSave event too.
You have to put a safeguard in place that prevents the logging logic from running when the afterSave event belongs to the logging model, for example:
if ($event->getSubject() instanceof \App\Model\Table\ActionLogsTable) {
return;
}
// ...

SpriteKit: run code or block when action removed?

The run function for SKNode lets you run a block when the action completes, but what if the action is cancelled/removed via removeAllActions?
Cancelling an action doesn't invoke the completion block from the run function.
Is there a callback or way to run code when the action is cancelled/removed?
Yes, if you remove an action before it has completed, the completion block will not run. Per Docs:
The run(:completion:) method is identical to the run(:) method, but after the action completes, your block is called. This callback is only called if the action runs to completion. If the action is removed before it completes, the completion handler is never called.
A work around could be:
class YourSpriteNode: SKNode {
func doSometingAtCompletionAction() {
//all your stuff
}
override removeAllActions() {
super.removeAllActions()
doSometingAtCompletionAction()
}
}

How to send a response from a method that is not the controller method?

I've got a Controller.php whose show($id) method is hit by a route.
public function show($id)
{
// fetch a couple attributes from the request ...
$this->checkEverythingIsOk($attributes);
// ... return the requested resource.
return $response;
}
Now, in checkEverythingIsOk(), I perform some validation and authorization stuff. These checks are common to several routes within the same controller, so I'd like to extract these checks and call the method everytime I need to perform the same operations.
The problem is, I'm unable to send some responses from this method:
private function checkEverythingIsOk($attributes)
{
if (checkSomething()) {
return response()->json('Something went wrong'); // this does not work - it will return, but the response won't be sent.
}
// more checks...
return response()->callAResponseMacro('Something else went wrong'); // does not work either.
dd($attributes); // this works.
abort(422); // this works too.
}
Note: Yes, I know in general one can use middleware or validation services to perform the checks before the request hits the controller, but I don't want to. I need to do it this way.
As of Laravel 5.6 you can now use for example response()->json([1])->send();.
There is no need for it to be the return value of a controller method.
Note that calling send() will not terminate the output. You may want to call exit; manually after send().
You are probably looking for this:
function checkEverythingIsOk() {
if (checkSomething()) {
return Response::json('Something went wrong');
}
if(checkSomethingElse()) {
return Response::someMacro('Something else is wrong')
}
return null; // all is fine
}
And in the controller method:
$response = $this->checkEverythingIsOk();
if($response !== null) { // $response instanceof Response
return $response;
}
It's probably overkill, but I will throw it in anyway. You might want to look into internal requests. Also this is just pseudoish code, I have not actually done this, so take this bit of information with caution.
// build a new request
$returnEarly = Request::create('/returnearly');
// dispatch the new request
app()->handle($newRequest);
// have a route set up to catch those
Route::get('/returnearly', ...);
Now you can have a Controller sitting at the end of that route and interpret the parameters, or you use multiple routes answered by multiple Controllers/Methods ... up to you, but the approach stays the same.
UPDATE
Ok I just tried that myself, creating a new request and dispatching that, it works this way. Problem is, the execution does not stop after the child-request has exited. It goes on in the parent request. Which makes this whole approach kind of useless.
But I was thinking about another way, why not throw an Exception and catch it in an appropriate place to return a specified response?
Turns out, thats already built into Laravel:
// create intended Response
$response = Response::create(''); // or use the response() helper
// throw it, it is a Illuminate\Http\Exception\HttpResponseException
$response->throwResponse();
Now usually an Exception would be logged and you if you are in Debug mode, you would see it on screen etc. etc. But if you take a look into \Illuminate\Foundation\Exceptions\Handler within the render method you can see that it inspects the thrown Exception if it is an instance of HttpResponseException. If it is then the Response will be returned immediately.
To me the most simple and elegant way is:
response()->json($messages_array, $status_code)->throwResponse();
(you don`t need return)
It can be called from a private function or another class...
I use this in a helper class to check for permissions, and if the user doesn`t have it I throw with the above code.

How To Get Data From A Custom Event In Magento

I have an observer module that I have written for Magento. It simply monitors an event called mgd_order_prep which is triggered by a custom dispatcher like this:
Mage::dispatchEvent("mgd_order_prep", array('orderdata' => $order));
$order is simply a magento sales/order object.
My event fires and my function in the proper class executes:
function updateOrderPrepPDF($observer)
{
Mage::log("Update Order Prep",null,'orderprep.log');
Mage::log($observer->getOrderdata(),null,'orderprep.log');
}
I see what I should after the first log event, but I dont see ANYTHING for when I try to output the order data (it outputs blank - or null).
How do I get the data I pass in at the dispatch event out at the execution point?
You can directly get Data using getData() method :
function updateOrderPrepPDF($observer)
{
Mage::log(print_r($observer->getData(),true),null,'orderprep.log');
}
Check this log inside var/log directory.
Try this code and let me know if you still have any query.

symfony2 my own event

I made the authorization and authentication via facebook like here:
http://symfony.com/doc/current/cookbook/security/custom_authentication_provider.html
and it works
Now I want to make my own event, this event will do something when the user authenticates using facebook. For example-will redirect the user to the home page.
I did it like this
http://symfony.com/doc/current/components/event_dispatcher/introduction.html
So I have this class
http://pastebin.com/2FTndtL4
I do not know how to implement it, what am I supposed to pass as an argument to the constructor
It's really simple. Symfony 2 event system is powerful, and service tags will do the job.
Inject the dispatcher into the class where you want to fire the event. The service id is event_dispatcher;
Fire the event with $this->dispatcher->dispatch('facebook.post_auth', new FilterFacebookEvent($args)) when needed;
Make a service that implements EventSubscriberInterface, defining a static getSubscribedEvents() method. Of course you want to listen to facebook.post_auth event.
So your static method will look like:
static public function getSubscribedEvents()
{
return array(
'facebook.post_auth' => 'onPostAuthentication'
);
}
public function onPostAuthentication(FilterFacebookEvent $event)
{
// Do something, get the event args, etc
}
Finally register this service as a subscriber for the dispatcher: give it a tag (eg. facebook.event_subscriber), then make a RegisterFacebookEventsSubscribersPass (see this tutorial). You compiler pass should retrieve all tagged services and inside the loop should call:
$dispatcher = $container->getDefinition('event_dispatcher');
$subscribers = $container->findTaggedServiceIds('facebook.event_subscriber');
foreach($subscribers as $id => $attributes) {
$definition->addMethodCall('addSubscriber', array(new Reference($id)));
}
This way you can quick make a subscriber (for logging, for example) simply tagging your service.
Event object is just some kind of state/data storage. It keeps data that can be useful for dispatching some kind of events via Subscribers and/or Listeners. So, for example, if you wanna pass facebook id to your Listener(s) - Event is the right way of storing it. Also event is the return value of dispatcher. If you want to return some data from your Listener/Subscriber - you can also store it in Event object.

Resources