3

Want to log each save activity of all model table. I used afterSave method in a single model i.e. working fine.

Now in place of adding same in all modelTable one by one, I want to write below method in a single file from where all modelTable by default can run this method/function.

I tried it with behaviour as well but not exactally know how behaviour will work for this.

public function afterSave($event, $entity, $options)
{
     $ActionLogs = TableRegistry::get('ActionLogs');
     -------
     -------  
     $ActionLogs->save($ActionLogsEntity);
}
ndm
  • 59,784
  • 9
  • 71
  • 110
priti narang
  • 258
  • 4
  • 18

1 Answers1

3

There is no AppModel base class anymore as of CakePHP 3.

Events

If you want to run "after save" logic for all models, then you can now use events, specifically the Model.afterSave and Model.afterSaveCommit events.

So for afterSave you can register an event like this:

\Cake\Event\EventManager::instance()->on(
    'Model.afterSave',
    function (
        \Cake\Event\EventInterface $event,
        \Cake\Datasource\EntityInterface $entity,
        \ArrayObject $options
    ) {
        // run your action logging logic here
    }
);

To cover the whole application you'd usually register such an event in your application's bootstrap, specifically in the Application::bootstrap() method in the src/Application.php file, not in the config/bootstrap.php file (this matters very much for the test environment!).

See also

Behaviors

If you wanted to apply this to only specific models, then a behavior would be the tool of choice. You'd really only need to define the callback just like you would in your table class:

// in src/Model/Behavior/ActionLogBehavior.php

namespace App\Model\Behavior;

use ArrayObject;
use Cake\Datasource\EntityInterface;
use Cake\Event\EventInterface;
use Cake\ORM\Behavior;

class ActionLogBehavior extends Behavior
{
    public function afterSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
    {
        // run your action logging logic here
    }
}

Then you can add the behavior to the respective table classes via their initialize() method, like:

public function initialize(array $config): void
{
    // ...

    $this->addBehavior('ActionLog');
}

See also

ndm
  • 59,784
  • 9
  • 71
  • 110
  • Can you let me know how can I get TableName of current afterSave method (may be by using $event object)? – priti narang Aug 12 '22 at 17:34
  • 1
    @pritinarang Depends on what exactly you mean by "table name", that could be the database table name, or the table object class name or the alias used for loading it? In any case the subject of the event is the respective table object, you can get it via `$event->getSubject()`. – ndm Aug 12 '22 at 17:51
  • Thanks @ndm - Actually I was looking for database table name and used `$event->getSubject()->getTable()` statement to get that. – priti narang Aug 13 '22 at 00:15
  • I am trying to save data in a DB table (on afterSave method) in Application.php file, now getting database error `SQLSTATE[HY000]: General error: 2006 MySQL server has gone away` looks like it is related with `wait_timeout` but I didn't get any error when calling same method in a specific modelTable. – priti narang Aug 13 '22 at 00:41
  • I posted new question for the upcoming issue after implementing afterSave method, please check if you can help in that as well [link](https://stackoverflow.com/questions/73342529) – priti narang Aug 13 '22 at 08:00
  • Also everything working fine with Behaviour as well but in application.php memory reached max level. – priti narang Aug 13 '22 at 11:04