I see several options.
The first:
ActiveDataProvider provides data by receiving it in response to the challenge call that you are configuring it with. The query must be an object of type yii\db\QueryInterface . You must configure your ActiveDataProvider such an instance that would receive the data already sorted as needed, you can do it using UNION . Sql query should get plus or minus like this:
(SELECT * FROM products WHERE price > 0 ORDER BY title ASC) UNION (SELECT * FROM products WHERE price = 0 ORDER BY title ASC);
That is, as UNION assumes, you combine the output of two queries to a sample. In the first request, you choose products with a positive price, in the second with zero. In two queries, specify the same sort criterion.
Again:
- Create a query object (for example,
ActiveQuery or Query ). - using the interface of the created object, describe a sql query that contains a
UNION expression that combines the two samples you need. - configure an instance of
ActiveDataProvider with the created object and work with it.
This approach has its drawbacks, but it is very likely that it will fully suit you.
Second:
Discard the idea that
It is important to get ActiveDataProvider in the end
We think differently: ultimately, we need to obtain an object that implements the yii\data\DataProviderInterface .
By the way, this is a more correct approach in terms of object-oriented design: the modules of your application should not depend on specific implementations, but should rely on interfaces.
Next, create your class that implements yii\data\DataProviderInterface .
We describe its constructor so that it yii\data\DataProviderInterface as input a collection of instances of type yii\data\DataProviderInterface , which we save in the class field. We implement the methods described in the interface, delegating their execution to each of the instantiated yii\data\DataProviderInterface transferred in the constructor, and in the class itself we collect their work results, process and return to the client.
On the client: we create 2 ActiveDataProvider objects, each of which is configured with one separate sql query (the first receives goods with a positive price, the second with zero), we collect them into a collection. We create an object of the class we have written, passing this collection to it in the constructor. Further we work with an instance of our class the same as would work with ActiveDataProvider .
The second option is more complicated, but it provides much more opportunities for flexible expansion of the application functional in the future. In the first variant, there is a certain implicit hardcode - you specify with your hands, a general sorting criterion, it will be difficult to change it on the fly in runtime. In the second, you can configure the collection elements with a common yii\data\Sort object, you can configure them different, while making decisions about this during the execution of the program, starting from the request parameters, or the application state context. By and large, the first option can also be developed to the possibility of configuration in runtime, but there it will be at best less elegant, at worst - in half with crutches. But in general, I think that for the time being, the first option may well suit you.