stibiumz / phalcon.eager-loading Goto Github PK
View Code? Open in Web Editor NEWSolves N+1 query problem in Phalcon Model
License: The Unlicense
Solves N+1 query problem in Phalcon Model
License: The Unlicense
On a hasManytoMany relationship it fails when one of the parent element does not have relationship:
On a model:
$this->hasManyToMany(
"id",
'App\Tag\Models\ElementTag',
"element_id", "tag_id",
'App\Tag\Models\Tag',
"id", array('alias' => 'tags')
);
When that parent model does not have TagsElements it does fail to fetch the relationship.
$parentModelResults = Loader::fromResultset($parentModelResults, [
'tags' => function (QueryBuilder $builder) {
$builder->where('App\Tag\Models\ElementTag.element_type = "parentModelType"');
},
Phalcon\Mvc\Model\Exception: Unknown model or alias 'App\Tag\Models\ElementTag' (1), when preparing: SELECT [App\Tag\Models\Tag].* FROM [App\Tag\Models\Tag] WHERE ([id] IN (:phi0:, :phi1:)) AND (App\Tag\Models\ElementTag.element_type = "playingfield")
@stibiumz In our development, I got an error ---- " [ERROR] Syntax error, unexpected EOF". I used xdebug to track what happened and found that the query builder try to execute with empty bind values in "inWhere" method. This Error is located at line 203 in EagerLoading\EagerLoad.php.
In our case, the "$subjectSize" is equal 0.
We have follow three models: "Invoice","Payment","Method". Each invoice have many payments, and each payment have one method. In my code:
$inv=Invoice::findFirstById("1");
then I tried to load payment and method using: $inv->load("Payment.Method");
For invoice 1, there are not any payment yet in database.
So I expected the result of $inv->payment should be null when I called $inv->load("Payment.Method").
Could anyone fix this?
Hey I'm trying to implement this extension on Phalcon 3 and PHP 7 and as soon as I use "with" I get:
Maximum function nesting level of '256' reached, aborting!
Fatal error: Maximum function nesting level of '256' reached, aborting! in /var/www/vivre-feed/vivre/library/eager-loading/EagerLoading/QueryBuilder.php on line 16
Any ideas?
Hi, @stibiumz
with any kind of relationships I can see the eager loading executing. But when I try to access to the property with the alias of the related model it still query the database as always. Using last phalcon 2.0.2
// on the model I define "sports" relationship
$this->hasManyToMany(
"id",
'App\Sport\Models\SportUser',
"user_id", "sport_id",
'App\Sport\Models\Sport',
"id", array('alias' => 'sports')
);
// after... on a controller I use it this way:
$user = User::findFirst(1)->load('sports');
var_dump($user->sports);
SELECT `user`.`id`, `user`.`name`, `user`.`email`, `user`.`telephone`, `user`.`password`, `user`.`avatar`, `user`.`gender`, `user`.`birth`, `user`.`role`, `user`.`active`, `user`.`date_created`, `user`.`date_updated`, `user`.`deleted` FROM `user` WHERE `user`.`id` = 1 LIMIT 1
SELECT `sport`.`id`, `sport`.`name` FROM `sport` INNER JOIN `sport_user` ON `sport_user`.`sport_id` = `sport`.`id` WHERE `sport_user`.`user_id` IN (:phi0)
// executed on the var_dump
SELECT `sport`.`id`, `sport`.`name` FROM `sport` INNER JOIN `sport_user` ON `sport_user`.`sport_id` = `sport`.`id` WHERE `sport_user`.`user_id` = :0
Why not allow this method in query builder?
Hi everyone!
I'm new in phalcon and php. I'm using phalcon version 1.3. Can someone help how to setup and use this package on existing project please?!
Thanks!
Since Phalcon 2.0.4 it's possible to write conditions on relationships 2.0.4 changes, under Relationships with conditionals
But it seems to fail when using the Loader
$users = Loader::fromResultset($users, ['favouriteImage']);
been favouriteImage
a relationship with conditional it does not ask for the condition, only the relationship.
Of course, actually the loader allows to override the relationship with the Querybuilder, but I will like to avoid this since my domain logic and data providers become a mess.
Again, thank you very much @stibiumz for your library, it does the phalcon orm more useful.
@stibiumz have you more ideas for the library? I would like to drop some so I created this "issue" post. Feel free to delete it thought, this is your space.
It depends on phalcon framework but would be great to have Relationships returned as ResultSets (and phalcon resultsets need more functionality)
Hi, I was taking a look at
https://github.com/stibiumz/phalcon.eager-loading/blob/master/src/EagerLoading/EagerLoad.php#L157
the property _related
where the relationships are stored is not filled.
This is causing me a problem. When I want to check if a relationship is already loaded, (by any way) if not, then I check caché or fetch db.
On pseudocode:
$instances = Loader::from($instances, ['relationshipAlias']);
foreach($instances as $instance) {
print_r($instance->getRelationshipAlias());
}
// on the model for $instance I have
public function getRelationshipAlias() {
if(!isset($this->_related['relationshipAlias']) || $this->_related['relationshipAlias'] === null) {
// get from cache or fetch from db using getRelated('relationshipAlias');
}
}
The problem here is that on that case, the eagerloaded relationships are wasted. Of course, if I try to check if the relationship is loaded using the property relationshipAlias
, in case that the relationship is not loaded it will make a lazy loading "automatically", runining my chance to insert the caché.
Is it possible to use this extension without incubator?
It's because we have less performance when we use incubator.
If not, is it possible to make a zephir version of this library? So we can use this as a dll without incubator and fast performance.
Would be nice if you would create a wrapper for toArray()
, making the following output:
/* Entry belongsTo Channel, Entry hasMany Files */
$result = Entries::with('Channel', 'Files');
print_r($result->toArray());
[
0 => [
'id' => 1,
'channel_id' => 1,
'Channel' => [
'id' => 1,
'name' => 'My Chanel'
],
'Files' => [
0 => [
'id' => 1,
'entry_id' => 1,
'name' => 'foo.jpg'
]
]
]
]
What I do currently:
$data = [];
$i = 0;
foreach ($result as $row) {
$data[$i] = $row->toArray();
$data[$i]['Channel'] = $row->channel->toArray();
foreach ($row->files as $file) {
$data[$i]['Files'][] = $file->toArray();
}
$i++;
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.