-
-
Notifications
You must be signed in to change notification settings - Fork 213
[RTM] Improve model registry #7725
[RTM] Improve model registry #7725
Conversation
…r eval definition)
…f the findOneBy() method
@@ -146,7 +146,8 @@ | |||
), | |||
'path' => array | |||
( | |||
'sql' => "varchar(1022) NOT NULL default ''" | |||
'eval' => array('unique'=>true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is wrong, the path must not be unique.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
??? That's what the whole PR and discussion today was about?? 20x FilesModel::findByPath('path.jpg')
should return the same instance because it's unique? If not, what combination of columns does make it unique then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only the UUID is unique. If you e.g. use SyncCto it may happen that you have two or more entries of the same file with different UUIDs, therefore we decided not to make the path unique.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"unique" in terms of "unique for this installation". Everywhere we use findByPath()
we expect a model, not a collection (if it was not unique it would return a collection, right?).
See e.g.
https://github.com/contao/core/blob/develop/system/modules/core/controllers/BackendPopup.php#L96
https://github.com/contao/core/blob/develop/system/modules/core/forms/FormFileUpload.php#L253
https://github.com/contao/core/blob/develop/system/modules/core/library/Contao/Picture.php#L123
https://github.com/contao/core/blob/develop/system/modules/core/modules/ModuleRegistration.php#L431
I have added the |
I really cannot merge it because of the |
After having read #5556 again, I'm no longer sure if the column is not unique after all. It seems we just weren't able to set a unique index on DB level. |
My changes do NOT set any keys :) It's just our |
Ok, so we must never set a unique index on This means that we can actually merge the PR, because the column is meant to be unique (we just cannot set an index on DB level). |
Okay, but please do not merge it yet. I would like to improve some naming things and try if can support arbitrary aliases that do not necessarily have to match 1 column only (so in theory it would be possible to alias multiple columns). |
I won't. The title still says |
@@ -479,6 +512,11 @@ protected function createExtract() | |||
foreach ($sql['keys'] as $field=>$type) | |||
{ | |||
$this->arrKeys[$field] = $type; | |||
|
|||
if ($type === 'unique') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are only using ==
in the legacy code.
…does not necessarily have to be a column name)
…self so every model can control registering and unregistering aliases itself
So there's some more work done here but leaving on public static function findOneByExpensiveFilterQueryMethod(array $criteria)
{
// Build complex query
return static::findOneBy($queryParts);
} Now you still have the issue that you might call this method with the exact same You can now optimize like this: public static function findOneByExpensiveFilterQueryMethod(array $criteria)
{
$alias = 'my_superb_alias';
// Of course you may need to order the criteria here or so etc.
$aliasValue = md5($criteria);
$model = \Model\Registry::getInstance()->fetch(static::getTable(), $aliasValue, $alias);
if ($model !== null) {
return $model;
}
// Build complex query
$model = static::findOneBy($queryParts);
if ($model !== null) {
\Model\Registry::getInstance()->registerAlias($model, $alias, $aliasValue);
return $model;
}
return null;
} Or use the |
foreach (static::getUniqueFields() as $strColumn) | ||
{ | ||
$varAliasValue = $this->{$strColumn}; | ||
if (!$registry->isAliasRegistered($this, $strColumn, $varAliasValue)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please rename this method to isRegisteredAlias()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it. Can I merge it now? |
If none of the @contao/developers has any objections, yes :) |
I am in the process of releasing the beta version of Contao 3.5. How long shall I wait? |
Okay for me if this gets a bit more time to be reviewed by the other devs and makes it into the RC later in April :) |
👍 |
{ | ||
$objDca = \DcaExtractor::getInstance(static::getTable()); | ||
|
||
if ($objDca->hasUniqueFields()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be omitted as \DcaExtractor
is initializing to empty array.
Simply always return the value of $objDca->getUniqueFields()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, „fixed“ in 2337fa6.
@@ -891,13 +937,22 @@ public static function findOneBy($strColumn, $varValue, array $arrOptions=array( | |||
*/ | |||
public static function findBy($strColumn, $varValue, array $arrOptions=array()) | |||
{ | |||
$blnModel = false; | |||
|
|||
$arrColumn = (array) $strColumn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming of $strColumn
is now misleading, so is the phpDoc.
This should be changed to reflect the new behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? I did not change this afaik?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may be a string or an array in your implementation but was only a string before.
Otherwise the check on count($arrColumn) == 1
is not needed as it will always be 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it could always be an array.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then the description was misleading from the beginning. :)
{ | ||
if (isset($this->arrRegistry[$strTable][$intPk])) | ||
// Default is searching by PK and is the most common case |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know we are in legacy code here and not in Contao 4 but please please please let's not increase the complexity of the old classes if we can use methods for new code even if it is in legacy classes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added all of my remarks. |
@Toflar Is this RTM now? |
Yes. :) |
Great! |
Can you please take a look at the following two FIXMEs? core/system/modules/core/library/Contao/Model.php Line 1041 in ce8e824
core/system/modules/core/library/Contao/Model.php Line 1053 in ce8e824
|
To be honest, I don't know why we're using core/system/modules/core/library/Contao/Model.php Line 1046 in ce8e824
mergeRow() call there still looks wrong to me as this would modify a model in the registry.
|
What about line 1048? Is |
|
Merged in 9da066c then :) |
This is my PR to solve #7724 and even more!
Currently, our model registry only allows to register models by their PK which in general is
id
. This causes useless DB queries in a lot of circumstances. The one mentioned in #7724 wastl_files.path
which is actually unique as well and currently when executingFilesModel::findByPath('path')
20 times, there will be 20 queries to the database even though it's always the same.Note that this happens quite often since Contao 3.4, because our
Image
class does that for every image to check if an important part is set.Now instead of just solving this issue I tried to find a general solution for those cases :-)
The model registry can now handle aliases that internally point to the ID again.
Let's say we have this in
tl_files
:In Contao 3.4 AND my PR (= so it's fully backwards compatible) you can fetch the model from the registry via its ID:
With this PR you can now also do this:
And thanks to the modifications on the
DcaExtractor
this automatically works for all fields that are unique either because of the SQL key definition:or the
eval
section of the field itself:Every developer can either do that or override the
getUniqueFields()
method in their model class for full flexibility.🎉