-
-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suboptimal behaviour when using Result::fetchAssoc
in conjunction with Result::setRowFactory
#357
Comments
This issue most probably plagues the |
I was wondering if I could come up with my own solution to the problem, however, as many times before, I hit the wall called "private" or "final". First, I could post a PR where one could set the result class created by the However, since both I would like to make Dibi support entities that use magic getters, which is quite common use case. |
I think that fetchAssoc is not suitable for entities. Better way is to create new |
Consider this case. Really simple and useful. I want to fetch users and then have them automatically sorted into groups by company and account type. $allUsers = $connection->query('SLEECT * FROM `users` WHERE ... ')
->setRowFactory(function($row){ return new UserEntity($row); })
->fetchAssoc('company|accountType|id'); Then somewhere else in the application where I only work with entities, there might be code to access users or iterate over them To support this, I have to make a 3-levels nested foreach cycle to convert the result to entities, and what is worse, the level of nesting changes depending on how the argument to $result = [];
foreach($allUsers as $companyId => $group){
foreach($group as $type => $users){
foreach($usersas $userId => $row){
$result[$companyId][$type][$userId] = new UserEntity($row);
}
}
}
return $result; Why would not this be a supported case for fetchAssoc? |
I forgot to point out that the the suggested And I consider parsing the argument to fetchAssoc a hack 🙂 |
The solution would be to modify fetchAssoc to
|
WIP 6b34262 |
So bascally you modify the order to do the transformations first, then apply the row factory. Well at a point in time I found it strange that the row factory was invoked before fetchAssoc transformed the result, but it slipped of my mind. If this is not a BCB, then it seems more elegant to me. Since |
In fact, it is BC break :-/ See #284 In my opinion, this cannot be solved without BC. And I don't really want to deal with it :-) |
I wonder ... it's quite common to have an entity class put all the "row data" into one attribute and use magic accessors. So you had the very same idea of soluton here #284, if i understand it correctly, which trned out to be a BCB. Would making the result class configurable in Furthermore, if there was an interface introduced that would be used along with the Something like the following. // check columns
foreach ($assoc as $as) {
// offsetExists ignores null in PHP 5.2.1, isset() surprisingly null accepts
if (
$as !== '[]' && $as !== '=' && $as !== '->' && $as !== '|' && !property_exists($row, $as) &&
(!$row instanceof ExposesProperties || !$row->hasProperty($as))
) {
throw new \InvalidArgumentException("Unknown column '$as' in associative descriptor.");
}
} interface ExposesProperties {
public function hasProperty(string $name): bool;
} The interface could then be implemented by the entity classes. |
Yes, I'm afraid any change can be a BC break. New interface seems like a ways how to solve. I have to think about it more and unfortunately I don't have time for it now. |
Related probem is with |
Version: current 4.1
Bug Description
When using
Result::fetchAssoc
in conjunction withResult::setRowFactory
, fetchAssoc may throw exceptionUnknown column 'foo' in associative descriptor.
even though the property is accessible when accessing$row->foo
via magic getters.Steps To Reproduce
Unfortunatelly, this is quite a common pattern with many ORMs. 😥
The culprit
the problem is in
Result
class, where usingproperty_exists
with magic props will fail, quoted:Possible Solution
I'm not yet sure what a backward compatible solution should look like.
The text was updated successfully, but these errors were encountered: