laravel observers are not working - php

I am trying to listen to model events using laravel observers .The problem is when i submit my form (update or creating new records), nothing happened at all .Do i miss something ?
app.php
'providers' => [
...
App\Providers\CasesManagerServiceProvider::class,
]
CasesManagerServiceProvider.php
class CasesManagerServiceProvider extends ServiceProvider
{
public function boot( )
{
Cases::observe(CasesObserver::class);
}
public function register()
{
}
}
CasesObserver.php
class CasesObserver
{
private $cases;
public function __construct(Cases $cases){
$this->cases = $cases;
}
public function creating(Cases $case)
{
dd('creating');
}
public function saved(Cases $case)
{
dd('saved');
}
public function updating($case)
{
dd('updating');
}
public function updated($case)
{
dd('updated');
}
}
Cases.php
class Cases extends Model
{
const UPDATED_AT = 'modified_at';
protected $dispatchesEvents = [
'updating' => CasesObserver::class,
'updated' => CasesObserver::class,
'creating' => CasesObserver::class,
'saved' => CasesObserver::class,
];
}

for me, the problem was registering observer in the register() method!
so when I put it in the boot() method every thing worked well! the reason is the order of running methods in service providers which are mentioned hear
hope be useful

Ok i have found my answer . All the problem was when I added
use app\Observers\CasesObserver; in CasesManagerServiceProvider.php instead of use App\Observers\CasesObserver; .
Yes the Camel case of App was the problem, so i changed to App and all things are working fine now.

It seems to be a misuse of Composer and Laravel themselves.
You should inform them that you have added some files and configurations:
To autoload the files:
composer dump
To reconfigure the cache:
php artisan config:cache
Hope this help you too!

You do not need to use $dispatchesEvents in your case. You should try to remove $dispatchesEvents from model, and remove __constructor() from CasesObserver.

The reason is that you have to add a HasEvents trait to your model
<?php
use Illuminate\Database\Eloquent\Concerns\HasEvents;
class MyModel extends Model
{
use HasEvents;
//your code goes here
}

Not possible according to the documentation. When issuing a mass update or delete query via Eloquent.

Related

Why isn't the event listener firing off in Lumen?

So I have event and listener classes defined as well as having them registered in the $listen array in EventServiceProvider.php. Here is the code:
use App\Events\EpisodeCreated;
use App\Listeners\NewEpisodeListener;
use Event;
class EventServiceProvider extends ServiceProvider {
protected $listen = [
EpisodeCreated::class => [
NewEpisodeListener::class
]
];
}
and then in EventServiceProvider's boot method I have the following:
public function boot() {
Episode::created(function($episode) {
Event::fire(new EpisodeCreated($episode));
});
}
here is the EpisodeCreated event class:
namespace App\Events;
use App\Models\Episode;
class EpisodeCreated extends Event {
public $episode;
public function __construct(Episode $episode) {
$this->episode = $episode;
}
}
and finally the listener:
namespace App\Listeners;
use App\Events\EpisodeCreated;
use App\Facades\EventHandler;
use App\Http\Resources\ShowResource;
class NewEpisodeListener {
public function __construct() {
}
public function handle(EpisodeCreated $event) {
EventHandler::sendNewEpisode((new ShowResource($event->episode->show))->toArray());
}
}
Lastly, I wrote the following unit test to make sure that the event is firing. It doesn't seem to be:
public function testNewEpisodeEventFiredOff() {
Event::fake();
$show = factory(Show::class)->create();
$episode = factory(Episode::class)->create(['show_id' => $show->id]);
Event::assertDispatched(EpisodeCreated::class);
}
I get an error saying that the event never got dispatched when I run phpunit. Also I added echo debug statements and while the EpisodeCreated object is being created, the NewEpisodeListener is not being fired off. Any help you guys can give would be greatly appreciated.
Well, my problem seems to be that I defined the boot method in EventServiceProvider without calling parent::boot(). Since I refactored my code to not use the boot method at all, I removed it and it seems to be working better now.
I had the issue and could solve this. You should add below code to your EventServiceProvider class:
public function register()
{
$this->boot();
}
It seems boot method is not called when it is run by UnitTest or Command-line command I don't know why.

Laravel service container - registering an object shared to all services

I have tried to register to the container an Uuid and i have tried to retrive it from a route controller more than once, but the uuid value is not the first registered.
Can anyone help me to understand?
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
if(App::bound('conf')==NULL)
App::instance('conf', Uuid::generate()->string);
}
}
class InstanceController extends Controller
{
public function getUuid()
{
return App::make('conf');
}
}
I need to register an unique value or object that will be accessible to all.
I have also tried to put this code:
config(['uuid' => Uuid::generate()->string]);
in Laravel command handle method:
class RegisteredInstances extends Command
{
public function handle()
{
config(['uuid' => Uuid::generate()->string]);
}
}
and execute it, but when i try to retrive the uuid from a service, the response is null.
Now i have registered a laravel command that do this:
class RegisteredInstances extends Command
{
.
.
.
public function handle()
{
if(App::bound('conf')==NULL)
App::instance('conf', Uuid::generate()->string);
if(config('uuid2')==NULL)
config(['uuid2' => Uuid::generate()->string]);
}
}
A task every minute execute this command and i try to retrive the uuid from a service controller like this:
class InstanceController extends Controller
{
public function getUuid()
{
return App::make('conf');
}
public function getUuid()
{
return config('uuid2');
}
}
The problem, in this case, is that the controller return NULL:
You need to use laravel Configuration (accessing-configuration-values) with AppServiceProvider
Example:
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
config([ 'theconfig.uuid' => $class_here->UUID ]);
}
}
Then to use it, call
config('theconfig.uuid');
anywhere in the program
Is this in Laravel 4? I haven't seen the App::instance markup before, but I found it in Laravel 4.2 docs for the IoC Container.
This looks like a case for using a singleton. You can use this to ensure that conf is only resolved once. Looking at 4.2 docs, you could define your singleton as follows.
App::singleton('conf', function()
{
return Uuid::generate()->string;
});

Laravel VentureCraft revisionable not working on Laravel 5.5 when updating model

I used this package called revisionable so I tried to add it to my package.json and run the migration and everything worked fine.
But when I try to create a record and then update them it doesn't fill out the revisions table?
I am using "venturecraft/revisionable": "^1.28", and Laravel 5.5
Here is my code in my model
So here is what I have done in my model
use Venturecraft\Revisionable\Revisionable;
use Venturecraft\Revisionable\RevisionableTrait;
class AnalysisRequest extends Revisionable
{
use SoftDeletes;
use RevisionableTrait;
protected $revisionEnabled = true;
protected $revisionCleanup = true;
protected $historyLimit = 100; //Stop tracking revisions after 500 changes have been made.
protected $dontKeepRevisionOf = array(
'client_id', 'service_id', 'categories_id', 'methodologies_id', 'current_version', 'due_date'
);
protected $keepRevisionOf = array(
'sample_description',
'special_instruction',
'status',
'rushable'
);
When did I did wrong?
Can someone shed some light for me.
Thanks in advance.
For those who uses this package out there. There is no problem with the new versions of Laravel.
The problem is by using the eloquent methods of laravel especially with the update method.
So instead of updating a model like this example below.
$analysis_request = AnalysisRequest::where('id', $input['id'])->update([
'client_id' => $input['client_id'],
'sample_description' => $input['sample_description'],
'special_instruction' => $input['special_instruction'],
'rushable' => $input['rushable'],
'status' => 'for_testing'
]);
You have to do it this way in order to make revisions of the model. See below
$analysis_request = AnalysisRequest::where('id', $input['id'])->first();
$analysis_request->client_id = $input['client_id'];
$analysis_request->sample_description = $input['sample_description'];
$analysis_request->special_instruction = $input['special_instruction'];
$analysis_request->status = 'for_testing';
$analysis_request->save();
As you can see I used the first() method to fetch my model and update it using save() You can't use the save() method if you don't use the first().
Reference link of the issue in github.
I know it's hard to do it like that way. But for now you will be forced to if you want to make your life easier when creating revisions instead of manually doing it on your own. But hey it still depends on your case.
I hope the author makes a fix on this soon in the next release.
Okay, I did some digging on this, and it looks like it's a limitation of the package (it doesn't include the updating event - ref: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasEvents.php).
You can try to "override" the trait function and add the event yourself though:
class AnalysisRequest extends Model {
use RevisionableTrait {
bootRevisionableTrait as protected unused;
}
....
//Override trait function
public static function bootRevisionableTrait() {
static::saving(function ($model) {
$model->preSave();
});
static::saved(function ($model) {
$model->postSave();
});
static::created(function($model){
$model->postCreate();
});
static::deleted(function ($model) {
$model->preSave();
$model->postDelete();
});
//Add in the update events
static::updating(function ($model) {
$model->preSave();
});
static::updated(function ($model) {
$model->postSave();
});
}
}

Extending Collection in Laravel

I'm trying to extend my model collections in Laravel. I'm following these two tutorials here that say I just need to override the newCollection method. Seems pretty straight forward enough, but it seems the newCollection method is not firing.
I'm using Laravel 4.2.
link1
link2
My Model:
class City extends Eloquent {
public function newCollection(array $models = Array())
{
echo 'here';
return new Extensions\CityCollection($models);
}
}
Custom Collection:
<?php namespace Extensions;
echo 'here';
class CityCollection extends \Illuminate\Database\Eloquent\Collection {
public function findInList($name)
{
foreach ($this as $city)
{
if (strtolower($city->name) === strtolower($name))
{
return $city;
}
}
return false;
}
}
None of the echo statements are firing. Am I doing something wrong? I've also run a dump-autoload and have added the containing folder to my composer.json.
I was about to delete, but maybe this will help someone in the future. It turns out I just needed to flush my models cache.

How can I extend class Confide in Laravel 4?

I want to extend/overwrite the method logAttempt in class Confide (Confide on GitHub) in order to execute some extra code whenever someone logs in successfully. This would be cleaner than copying the same code to all controllers where logAttempt is called.
I read through the Laravel documentation and several answers here on stackoverflow, but I just can't get it working.
I created a new folder app/extensions with a file named Confide.php:
<?php
namespace Extensions;
class Confide extends \Zizaco\Confide\Confide {
public function __construct(ConfideRepository $repo) {
die('no way!');
$this->repo = $repo;
$this->app = app();
}
public function logAttempt($credentials, $confirmed_only = false, $identity_columns = array()) {
die('yeah man!');
}
}
I added the directory to my app/start/global.php:
ClassLoader::addDirectories(array(
// ...
app_path().'/extensions',
));
I also added it to composer.json and ran composer dump-autoload:
"autoload": {
"classmap": [
...,
"app/extensions"
]
},
My own Confide class seems not to be loaded at all, because Confide works as normal – without ever die()-ing.
And if I use \Extensions\Confide::logAttempt($input, true); in my controller including the namespace, I get this ErrorException:
Non-static method Extensions\Confide::logAttempt() should not be called statically, assuming $this from incompatible context
Do I really need my own ConfideServiceProvider class as well? I tried that, too, but I'm not sure at all what to put in there to make Confide use my extended class.
Is there no simple way to extend a tiny bit of a class? There must be, I'm just missing something here.
If you are looking to execute some code when a user logs in, you should just listen for that event. In this case, I believe Confide uses the Auth class to login, so you should be able to listen for that event.
Event::listen('auth.login', function($user)
{
$user->last_login = new DateTime;
$user->save();
});
I find this much easier and cleaner than worrying about extending classes.
EDIT: Made a mistake
I think you need to call the method like this:
\Extensions\Confide->logAttempt($input, true);
because you are using:
\Extensions\Confide::logAttempt($input, true);
Which is how you call static methods.
I think I finally figured it out.
I had to extend ConfideServiceProvider as well like so:
<?php
namespace Extensions;
class ConfideServiceProvider extends \Zizaco\Confide\ConfideServiceProvider {
/**
* Bootstrap the service provider.
*
* #return void
*/
public function boot() {
$this->package('extensions/confide');
}
/**
* Register the application bindings.
*
* #return void
*/
protected function registerConfide() {
$this->app->bind('confide', function($app) {
return new Confide($app->make('confide.repository'));
});
}
}
The code above goes into app/extensions/ConfideServiceProvider.php. Note: In boot() I replaced "zizaco" with "extensions" and in registerConfide() I made no changes at all, but if this method is not present in the extended class, the original class will be used. I've got no idea why.
Then in app/config/app.php I replaced Zizaco\Confide\ConfideServiceProvider with Extensions\ConfideServiceProvider.
My own extended Confide class looks like this now:
<?php
namespace Extensions;
class Confide extends \Zizaco\Confide\Confide {
public function logAttempt($credentials, $confirmed_only = false, $identity_columns = array()) {
$result = parent::logAttempt($credentials, $confirmed_only, $identity_columns);
if ($result) {
// Login successful. Do some additional stuff.
\Log::info('User ' . \Auth::user()->username . ' logged in.');
}
return $result;
}
}
Note: If you want to use any other standard Laravel class like Log, Session etc., prefix it with one backslash as shown in the example above, or add a use operator for each class you use (e.g. use \Log;).

Categories