Skip to content
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

Basic support for asCollection #12304

Closed
wants to merge 4 commits into from
Closed

Basic support for asCollection #12304

wants to merge 4 commits into from

Conversation

samdark
Copy link
Member

@samdark samdark commented Aug 24, 2016

Q A
Is bugfix? no
New feature? yes
Breaks BC? no
Tests pass? yes
Fixed issues #10806

@samdark samdark added this to the 2.0.x milestone Aug 24, 2016
@samdark samdark self-assigned this Aug 24, 2016
@@ -225,6 +225,10 @@ public function populate($rows)
}
}

if ($this->collectionClass !== null) {
return new $this->collectionClass($models);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest to move this line into a separate protected method. Then it could be overridden with custom logic.
Use case: I want to pass original Query object in my collection as a 2nd argument of the constructor.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense.

@SilverFire
Copy link
Member

Are we going to implement CollectionInterface?

@samdark
Copy link
Member Author

samdark commented Aug 25, 2016

No since we aren't using collections.

* @return object collection instance.
* @since 2.0.10
*/
protected function createCollection($class, $models)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO $models is enough. Method can access $this->collectionClass by itself

@klimov-paul
Copy link
Member

Are we going to implement CollectionInterface?
No since we aren't using collections.

I suppose we should create a CollectionInterface and at least a one basic implementation for it.
This is necessary thing to do in order to call this feture 'complete'. Otherwise the entire change should be dropped.

* @return $this the query object itself
* @since 2.0.10
*/
public function asCollection($className)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #12304 (comment)

$className should be optional here, while default collection class is used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default is no collection at all. It doesn't make sense to introduce any default collection since the only thing you can achieve w/ collection that you can't achieve otherwise is type safety.

@samdark
Copy link
Member Author

samdark commented Aug 25, 2016

I suppose we should create a CollectionInterface and at least a one basic implementation for it.
This is necessary thing to do in order to call this feture 'complete'. Otherwise the entire change should be dropped.

Nope. First of all, it will prevent using external collection implementations such as Laravel's. Second, there's no requirements except that first argument of the constructor is an array of data.

@klimov-paul
Copy link
Member

Default is no collection at all. It doesn't make sense to introduce any default collection since the only thing you can achieve w/ collection that you can't achieve otherwise is type safety.

As I already said then there is no sense to introduce the entire feature. What we are saving here?
Ability to write following code:

$collection = User::find()->asCollection('UserCollection')->all();

insead of:

$collection = new UserCollection(User::find()->all());

Make absolutely no sense to me.

Also what do you mean by type safety?

One more thing how this feature should behave for the Query::one()?

@klimov-paul
Copy link
Member

Also collections should be introduced at the level of the Query instead of ActiveQuery.

@samdark
Copy link
Member Author

samdark commented Aug 25, 2016

The implementation here is incomplete proof of concept. You're absolutely correct that primary collection could be filled outside of AR and it's preferred to do so. The difference should be in handling relations...

By type safety I mean in an interface you'll be able to do:

interface X
{
    public function doit(PostCollection $posts);
}

// instead of

interface X
{
    public function doit(array $posts);
}

@samdark
Copy link
Member Author

samdark commented Aug 25, 2016

One more thing how this feature should behave for the Query::one()?

Query::one() should behave exactly the same way as before.

@klimov-paul
Copy link
Member

The difference should be in handling relations

In which way it will be different?

By type safety I mean in an interface you'll be able to do:

So how the default collection class existance contradicts this ability? It is like telling the existance of the BaseActiveRecord class prevents you from specify type restiction like following:

interface X
{
    public function doit(PostActiveRecord $post);
}

while it provides more flexisbility to write following type restiction:

interface X
{
    public function doit(BaseActiveRecord $model);
}

Query::one() should behave exactly the same way as before.

In this case asCollection() method makes absolutely no sense, since it affects only single method all(). Another 'finish' method should be introduced instead like collection():

$postCollection = Post::find()->collection();

Note that asArray() method, which was used as prototype here, affects both all() and one() methods. - thus is is a separated method. For collection it make no sense.

@samdark
Copy link
Member Author

samdark commented Aug 25, 2016

In which way it will be different?

Well, relations could be automatically wrapped into collections.

@klimov-paul
Copy link
Member

By the way, what about BatchQueryResult?
All thus fuss about collection reminds the concept of data readers. This is actually the only use case, which make sense for me.

I agree with @cebe here: #10806 (comment)

The collection functionality in Yii is split into different classes, providing all necessay support for most common features.

@klimov-paul
Copy link
Member

relations could be automatically wrapped into collections.

For what purpose? Just to 'eat' more memory?

@klimov-paul
Copy link
Member

For the linking improvement we should use ActiveQuery as I said at #10806 (comment)

$object->getRelationName()->link([$id1, $id2]);

@samdark
Copy link
Member Author

samdark commented Aug 25, 2016

OK. I agree with most of your arguments. Seems it's better to approach it differently via enhancing ActiveQuery and probably writing a recipe in Yii 2.0 cookbook about how to implement simple collections.

@samdark samdark closed this Aug 25, 2016
@samdark samdark deleted the ar-ascollection branch August 25, 2016 10:26
@samdark
Copy link
Member Author

samdark commented Aug 25, 2016

@cebe cebe removed this from the 2.0.x milestone Aug 25, 2016
@cebe
Copy link
Member

cebe commented Jul 10, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants