Always save User ID with a model


#1

Hi there,

what I want to do:
nearly every Model that I have has a “created_by” column. In this, I want to store the ID of the currently logged in user when the record is created.

Ok, this is not a super-hard task, but I want to do it nicely.
How would ATK experts do this?

  • create an abstract class which is just there to set “created_by” value and extend all the other relevant classes from it.
  • can I use a Trait for this? Would save 1 inheritance level.

However, I am stuck at a very basic point: I wanted to use the App in one of my models just to play around like:

      public function save() {
		//if model is created (no id set yet)
		if(!$this->get('id') && isset($this->app->adminuser)) {
			$this->set('created_by', $this->app->adminuser->get('id'));
		}
		parent::save();
     }

This class extends atk4\data\Model. I thought App was available via $this->app as Model uses the AppScopeTrait, but it does not seem to be the case: $this->app is not set…

Thanks & best regards
Philipp


#2

In large projects we tend to create a “MyModel” class (you can name it differently) from which all other models are extended.

Another option is to use hook inside persistence. See examples here: http://agile-data.readthedocs.io/en/develop/advanced.html#audit-fields

Persistence has a hook ‘afterAdd’ (https://github.com/atk4/data/blob/develop/src/Persistence.php#L108), It may not be mentioned in the documentation (but it should!)

Finally, in order to have “app” available through the model, you need to make sure persistence is linked with your application:

$app->add($app->db = Persistence::connect());

Adding non-ui object into $app should not do anything, but it will respect AppScopeTrait (http://agile-core.readthedocs.io/en/develop/appscope.html) and set $db->app, which will continue to set $model->app for all models you create.


#3

Hi Romans,

again thanks fot the help!

For the others: This is the code that works:
In my app class, I used $this->add():

class TourManagement extends \atk4\ui\App {
	
	...
	
	function __construct() {  
		parent::__construct();

		//Database Connection
		$this->add($this->db = new \atk4\data\Persistence_SQL(PMG_DB_STRING,PMG_DB_USER,PMG_DB_PASSWORD));

In the new Model I created which all other “real” model classes inherit from, I changed the save() function:

<?php

namespace Pmg;

class PmgModel extends \atk4\data\Model {

	/*
	 * Saves $app->adminuser into created_by field if it exists
	 * on creation (!$this->get('id'))
	 */
	public function save() {
		if(!$this->get('id') && $this->hasElement('created_by') && isset($this->app->adminuser)) {
			$this->set('created_by', $this->app->adminuser->get('id'));
		}
		parent::save();
	}
}

Hope these code examples help some
Best regards
Philipp


#4

@philipp - Actually what you might also consider is adding client-specific condition, if your data is client-specific. For instance if certain models can be accessible only by one user, use addCondition('user_id', $app->user->id);, this will restrict access and also set default value for new records.