Closed RomainLanz closed 9 years ago
Let's merge this PR for UserStamping, please revert your changes for src/ExistingAttributesPersistence.php
, there are only whitespace changes which is a no-op.
Concerning the log, we should first investigate where the second query is triggered, maybe this is a dev environment only situation.
All changes made in src/ExistingAttributesPersistence.php
are reverted.
What do you think of changing the bootExistingAttributesPersistence()
method with something like this:
public static function bootExistingAttributesPersistence()
{
// Listen to the 'saving' event but with a low priority so that any validation is performed before purging the attributes
$name = get_called_class();
static::getEventDispatcher()->listen("eloquent.saving: {$name}", function($model)
{
// Keep only the attributes that exists in the table
$model->setRawAttributes(
array_only(
$model->getAttributes(),
\DB::connection()->getSchemaBuilder()->getColumnListing($model->getTable())
)
);
}, -100);
}
With that, the query is executed only when you save the model and not at every load.
Or maybe better to create another Trait named StoreColumnsTrait
that store all columns in a static property. And all other Trait will depend on this. With that you have only one request per model for all your Trait.
<?php namespace Mortimer\Poignant;
trait ExistingAttributesPersistence {
use StoreColumnsTrait;
/**
* Boot the trait for a model.
*
* @return void
*/
public static function bootExistingAttributesPersistence()
{
// Listen to the 'saving' event but with a low priority so that any validation is performed before purging the attributes
$name = get_called_class();
static::getEventDispatcher()->listen("eloquent.saving: {$name}", function($model)
{
// Keep only the attributes that exists in the table
$model->setRawAttributes(
array_only(
$model->getAttributes(),
self::getDatabaseColumns()
)
);
}, -100);
}
}
<?php namespace Mortimer\Poignant;
trait StoreColumnsTrait {
/**
* All columns for the related model.
*
* @var array
*/
private static $databaseColumns = [];
/**
* Gets columns name of the related model.
*
* @return array
*/
public static function getDatabaseColumns()
{
if (!self::$databaseColumns) {
self::$databaseColumns = \DB::connection()->getSchemaBuilder()->getColumnListing((new static)->getTable())
}
return self::$databaseColumns;
}
}
tablecolumns
should be memoized when they are used, not before. Your proposal doesn't memoize though. (Maybe in reference to 2.)use
'd once in a class. So multiple traits using another one (StoreColumnsTrait
) in the same class will fail at compile time. This limitation certainly has to do with method precedence in the trait system.You are true. Maybe better to add theses functions on the Core of Laravel.
Change done.
Concerning the
bootExistingAttributesPersistence()
method. As you can see bellow we win some queries.Without condition:
With condition: