-
Notifications
You must be signed in to change notification settings - Fork 5
Fixing n+1 relations problem #27
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
Conversation
Huh... I need to test it on my test data for all kinds of relations... PHPUnits passes now, but I still want to test it on my own |
Most failed builds in Travis for my last commit (fix errors) are actually not errors at all... composer just can't handle dependencies.... |
I just figured out, how I can verify my code with unit test. I'll try to write tests this week and I want to extend test data a little (to test all different relations in laravel) |
Hi ! Thanks for your PR ! I really understand your issue, but the implement seems wrong to me. I think the best way to fix it is to create a Can you do that ? |
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.
Oh yeah, your approach sounds much better =) Yes, I will try to do it this week. |
- added some new entities - added all possible relations - added definitions for new entities - updated usage of extended structure in tests - move registration of definitions to function
Heh, as I expected, I messed up =( Currently working on better solution (found already one). I also write UnitTests for all possible relations. |
- each type of relation is tested separately - at the end one test that uses deep relation (3 levels)
- also fixing problem "$relationNameToStore might not be defined" - overlooked...
Sooooo I made some changes:
What do you think? Is it good now? If you have any improvements - just tell me. |
|
||
// check, if Paginable interface was implemented by given Transformer | ||
// Paginable interface has an extra wrapper for data-fields | ||
$isPaginable = $this instanceof Paginable; |
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.
Paginable
doesn't seem to be imported with use
?
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.
As I know there is no need to import classes with use, if they are in the same Namespace. PhpStorm don't show any errors, and the code is also executable.
If I add use StudioNet\GraphQL\Support\Transformer\Paginable;
on top, PhpStorm adds notice: "Import is not necessary"
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.
Yeah, I didn't notice that ;)
array_push($relations, $key); | ||
if (is_array($field) && method_exists($model, $key)) { | ||
// verify, that given method returns relation | ||
$relation = call_user_func([$model, $key]); |
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.
What happened is the $key
is delete
, update
, or whatever that does not relied to relationships ?
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.
Can you do some concrete example?
Method gets called, only if field is an array. Currently even if delete
is the key, nothing will happen. $model
is just an empty model-object instance, so delete()
or update()
make no changes. After call, $relation
will be boolean
or null
or whatever these functions return, but definitely not an instance of Illuminate\Database\Eloquent\Relations\Relation
, so that code will continue executing and let this field as not a relation.
May be we should add some filter, so that key should not be equal delete
or update
or what else method of Model are 'critical'? I mean even if you want to have delete
to be relation, it is not possible to implement it with Laravel... Also you can't damage the DB somehow with those fields, as model-objects, which gets created in this relation guessing, are empty, and have no connection to any rows in DB. Or am I wrong?
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.
You're true. The $model
isn't loaded from database (you've used $this->app->make
). My bad.
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.
Just an idea:
If you wish, I could get all methods of Eloquent-Model class, cache them, and when relation is guessed, those keys that equal the method-names will be just ignored. But I don't really think it is necessary...
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's not necessary. Don't worry, I'm just tired :D
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.
ok :D
then I am gonna wait till new release with my PR ^_^
- getResolver() of custom field is now called not directly from webonyx, but from this library with some additional infos (similar to transformers) - getResolver() gets now just one argument - an array with arguments from original webonyx caller, and additional `fields` and `with` - with-relations will be guessed only, if field defines a class name of source in new `getSource()` method. Otherwise with will be empty (as before)
Hi again =) I am using your library more and more in my new project. As I wanted to create a custom query, I noticed directly, that in custom queries there is also no possibility to do eager loading depending on query. So I moved some code around and extended Anyway, with all my changes under the hood, there is no breaking changes. Just an extra feature, that can be used. Let me know, if there is something wrong in code. I would be happy, if PR will be merged ^_^ |
this test was implemented, as I found a bug in my last implementation. So I decided to create a test for this case
tests/GraphQL/Query/Unauthorized.php
Outdated
@@ -6,7 +6,7 @@ | |||
use StudioNet\GraphQL\Support\Definition\Query; | |||
|
|||
class Unauthorized extends Query { | |||
protected function authorize() { | |||
protected function authorize(array $args) { |
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.
You should use commentary here to pass unit tests, such as
/**
* @params array $args
* @returns bool
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
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.
Ahhhh thanks! gonna fix it
I've merged #24 , so a conflict was created. I tried to solve it, if you can re-test your code in order to merge this PR, thanks 😉 |
# Conflicts: # .travis.yml # src/Support/Transformer/Eloquent/ListTransformer.php # src/Support/Transformer/Transformer.php
# Conflicts: # .travis.yml # src/Support/Transformer/Eloquent/ListTransformer.php # src/Support/Transformer/Transformer.php
Hi. It is my first collab in github in open-source... sorry, I didn't notice, you already merged new master in this branch, so I merged it again... 😅 I tried to understand, how pipes works and what happens there... I understood it for about 80%... anyway, it seems like your There are some mutation test, that fail, when
Generally it concerns all types of graphql mutations - create and update of deep relations, that get created/updated step by step. We have definitely to refactor For now, I simply ignore adding What do you think? |
@@ -69,19 +70,25 @@ public function transform(Definition $definition) { | |||
* @return callable | |||
*/ | |||
public function getResolverCallable(Definition $definition) { | |||
$app = $this->app; | |||
return function ($root, array $args, $context, ResolveInfo $info) use ($definition) { | |||
$reflect = new \ReflectionClass($this); |
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.
$reflect
does not seem to be used ?
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.
Ouch, you are right! I removed it.
This was a part of your old code, that you removed in your branch. That was there:
$reflect = new \ReflectionClass($this);
$definition->assertAcl(
str_replace("transformer", "", strtolower($reflect->getShortName())),
[
"fields" => $fields,
"context" => $context,
"args" => $args,
'info' => $info,
]
);
Dunno, what Definition::accertAcl()
was doing, but currently this method is not used at all. May be delete this method completely?
So ! I don't really understand your problematic with the I'll merge this branch when units will pass. We'll manage your problematic in a ticket ;) |
Ok... I will create an example for you, and create an issue for it later, so you can see, what am I talking about ;) |
Fix for #26
As you can see, I increased fields depth, if it is a ListTransformer, because one extra depth-level goes for
items {...}
. Moreover I pick fields fromitems
, and pass them then to guessing relations.guessWithRelations()
is now recursive and takes 3 paramsWhat do you think? As Transformers are currently used just by the lib, it has no breaking changes.