-
Notifications
You must be signed in to change notification settings - Fork 11.2k
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
[11.x] Add CollectedBy attribute #53122
Conversation
May be worth memoizing the resolution from the attribute? Otherwise it's a lot of reflection operations each time this method is called. |
Very good point! I've updated the PR and wrapped the logic in the |
Co-authored-by: Jeffrey Angenent <1571879+devfrey@users.noreply.github.com>
@@ -15,6 +18,27 @@ trait HasCollection | |||
*/ | |||
public function newCollection(array $models = []) | |||
{ | |||
return new static::$collectionClass($models); | |||
$collectionClass = $this->resolveCollectionAttribute() ?? static::$collectionClass; |
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.
instead of once()
this could also work, IMO easier to debug and troubleshoot.
static::$resolvedCollectionClass ??= $this->resolveCollectionAttribute() ?? static::$collectionClass;
return new static::$collectionClass($models);
required addition to Model.php
protected static $resolvedCollectionClass = null;
I believe |
/** | ||
* Create a new attribute instance. | ||
* | ||
* @param class-string $collectionClass |
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 should probably match the typehint in Database\Eloquent\Model#L228
@param class-string<\Illuminate\Database\Eloquent\Collection<*, *>> $collectionClass
@johanrosenson @taylorotwell But using a static variable like that wouldn't work as the resolved value would be shared across all models: abstract class Model
{
public static $resolvedCollectionClass = null;
}
class A extends Model
{
public function resolveCollectionClass()
{
static::$resolvedCollectionClass = CustomCollection::class;
}
}
class B extends Model {}
(new A)->resolveCollectionClass();
var_dump(B::$resolvedCollectionClass); // string(16) "CustomCollection" I suppose an array in a static variable used as a lookup table, where the key is the model class name, could work? |
/** | ||
* @template TCollection of \Illuminate\Database\Eloquent\Collection | ||
*/ | ||
trait HasCollection | ||
{ | ||
/** | ||
* @var array<class-string<static>, class-string<TCollection>> |
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'm not entirely sure about this type. If a phpstan wizard would like to have a look at this, that would be awesome
Is this better than overriding the |
@browner12 From a DX standpoint, it is primarily different; from a semantic standpoint, from a semantic(?) it gravitates more towards being declarative while |
@taylorotwell Do you want me to submit a PR to the docs documenting the attribute? |
@alsterholm fyi, you might be interested in this: #53126 |
This pull request adds a new
CollectedBy
attribute for specifying a custom Collection class for a model.With this attribute added, one would only have to add the attribute rather than override the
newCollection
method on the Model class (or taking the undocumented route and setting the$collectionClass
static property).This also brings the approach closer in line with the new
ObservedBy
andScopedBy
attributes.