-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
ActiveRelation: support custom Scopes #2146
Comments
Looks like showstopper for beta release. @yiisoft/core-developers any idea how to solve it? |
I would say bring back the previous support for declaring scopes in AR classes. |
And make it the only way to declare scopes? |
The methods declared in |
What the case of creating method in |
@nizsheanez forcing users to create method in |
@samdark, if don't talk about scopes, if user want to create/redeclare method in A bit abstract question, but hard to say clearly. |
@nizsheanez yes. |
@qiangxue I don't like the idea of reverting the change. Scope methods are definitely query-related and not instance ones. |
@samdark, ok |
Hm, @samdark but i would like to have this feature, extremely flexible, especially when user dont want to specify each time scopes in
Not starting long discussion about should/should not we bring this feature back, just notice. |
True theoretically. The old implementation was all for practical reason like this one. Another example is that for convenience we often put query methods directly in AR, for example, |
Agreed. Another examples |
Seems there is only two ways:
I'm for first way. [active_relation]->[scope] seems excess. Same things can be achived other ways. |
Well, it's about code reuse: you use scope because you want to reuse the same condition in multiple places. |
@qiangxue Yes, scopes goal is clean. But can you show example when you'll have any benefits from using scope inside relation definition? I see only drawbacks like "want unclean model? use scopes inside relation definition!" :) |
I would say if used judiciously, scope methods are very convenient and useful. A simple example is most content models (e.g. Yes, you can certainly directly write the condition when you define the relation, but why do you want to repeat? You want to write the condition explicitly in a relation method, but don't want to do so in a scope method? What's the difference? |
You understand me wrong, i would not write condition/scope/with when defining relation. Never. This way lead to unclean models/excess queries/non-error free models. There is one reason. When you'll need relation without condition/scope/with you'll need to find all places where such "smart" optimization was used and write condition/scope/with explicitly in that places. As result time will be wasted. But i agree scopes is usefull to reuse conditions. I do not say scopes is excess feature. I just say that possibility to use scopes (and many other things) inside relation definition usually bad practice or "too smart" optimization. In reality situations when you can use scope inside relation definition is sooo rare and also you need to be 1000% ensure that this relation will not be needed in other places without that scope in future. |
So are you opposing to supporting scope method definition in AR classes? |
@qiangxue On other hand |
@qiangxue Also issue starter solution seems not optimal. Optimal solution is: class Report extends ActiveRecord {
public static function createQuery()
{
return new ReportQuery(['modelClass' => get_called_class()]);
}
public static function createActiveRelation($config = [])
{
return new ReportRelation($config);
}
}
class ReportQuery extends ActiveQuery
{
public function myScope() {
...
}
}
class ReportRelation extends ReportQuery
{
} So maybe there is no problems at all. Want scopes? Define P.S. Seems |
Nope, this won't work: |
The issue reported is the complaint about excessive number of query classes needed, which I think is valid. Scope is not just used in relation definition. You can use it also DURING performing relational queries, e.g., |
Losing ability to use scope for relations doesn't look like acceptable loss but just reverting recent change means that there's one fully working and valid approach for scopes and it's magical definition in AR class. |
Yes, it is magical, and that's why it is called a feature. Scope methods defined in query classes aren't any special at all. We don't even need to talk about them because they are just normal methods without any special support. |
Well, it's not expected that these methods are available in one case and not available in another. Currently I see two ways solving it:
|
|
This means combining |
Combining |
Now we have the current implementation working with relations but @rawtaz has some valid points. |
Let's see if more people are requesting to add it back. If so, we may consider prefixing all scope methods in AR with |
@qiangxue How would one apply those scopes, are you thinking |
Magic again? |
Yes, it's the latter: class Post extends ActiveRecord
{
public static function scopeVisible($query)
{
$query->andWhere(['visible' => 1]);
}
}
Post::find()->visible()->all(); Yes, the signature is different, but so do the method name. This is a magical feature, anyway. |
Similar to what I said in my earlier post; Even if one can make scopes like this (in the model, with a scopeFoo() method), people who want to write "cleaner" code are still free to do so (by extending I mean, if all one wants to do is add some scopes, then having to extend a class and override a method does feel a bit overkill. Again, usually one just adds a little piece of condition, that's all. Would be different if the scope did much more than that. |
I think for now we should keep it as is and wait for feedback. |
I am against |
If you go for supporting scopes in AR model, I am 200% positive for going down the |
@Ragazzo Sorry, but where did you propose how to solve it / not use |
It's indeed way nicer without the darn |
@rawtaz currently scopes should be defined in |
class Post extends ActiveRecord { public static function scopeVisible($query) { $query->andWhere(['visible' => 1]); } } Post::find()->visible()->all(); is this working now in current yii2? |
no, scopes are only supported in custom query classes. |
I know this has been discussed in depth, but i'm unclear what's the argument against the example code by @qiangxue .. This example query basically implements support for this feature without breaking anything else.
This code has little overhead and as far as I can tell does not break BC. The argument against having different names for scopes in an ActiveQuery class vs scopes in an ActiveRecord class is not valid in my opinion. The added ease of use of this code outweights the "inconsistency" in my opinion. Obviously I can and do implement this in my base ActiveQuery / ActiveRecord classes, but I think it would improve the framework to include this. |
This sounds interesting. |
Making all static methods a scope automatically seems bad to me. If we use reflection we could go as far as to check the signature to see if it is a scope. However for me this adds no real benefit. I like having the scope prefix in my ActiveRecord class and I like not having to use the scope prefix when running the query. Also there are some static methods that are never scopes (like getDb, createQuery, tableName) I'd rather not have to think about these possible collisions; also for BC the prefix is safer since I can easily verify that any existing static methods don't start with "scope"; it is harder for me to verify that any static methods I have defined will not pass the check for being interpreted as a scope. What is bad about the prefix method? Is it bad practice? |
Using the prefix for scopes method introduces special magic. Also not everyone may actually like it. public static function whereActive($query)
{
...
return $query;
} This way scope methods looks pretty both while declaring and while applying. Also originally (back at 'beta' version) Active Record declared its scopes in this way - just a static methods without any prefix. |
It is obvious we are running circles around here. Change does not make sense. |
Ok, clear on the final arguments. Will consider releasing this as a separate module. Thanks for the input! |
$this->hasOne(Report::className(), ['fk_goal' => 'id'])->myScope()->one();
have exception
Calling unknown method: yii\db\ActiveRelation::myScope()
I must to redeclare createActiveRelation ?
Now i solve i like:
The text was updated successfully, but these errors were encountered: