Yii2 ActiveDataProvider find()->all() - yii2

Maybe i miss understand something about ActiveDataProvider, when i want to join table with ->joinWith('user_display')->all();
I've got error: The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.
public function search($params)
{
$query = FinanceSettingsCheckoutcounter::find()->joinWith('user_display')->all();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
return $dataProvider;
}

ActivedataProvider needs a query. In your case you send the result of the query (all())
$query = FinanceSettingsCheckoutcounter::find()->joinWith('user_display');

Related

Error Calling unknown method: omgdef\multilingual\MultilingualQuery::sort()?

Good afternoon, help me figure it out, using the OmgDef/yii2-multilingual-behavior extension, swears at this line:
public function actionIndex()
{
$data = new ActiveDataProvider([
'query' => FaqLang::find()->multilingual()->sort(), //error here
]);
return $this->render('index', [
'data' => $data
]);
}
My overridden model that stores the sort() method
<?
namespace admin\base;
/**
* Base active query class for models
* #package admin\base
*/
class ActiveQuery extends \yii\db\ActiveQuery
{
/**
* Order by order_num
* #return $this
*/
public function sort()
{
$this->orderBy(['order_num' => SORT_ASC]);
return $this;
}
}
You could try using the sort property of the ActiveDataProvider.
$data = new ActiveDataProvider([
'query' => FaqLang::find()
->multilingual()
->select(['id','question','answer']),
'sort' => [
'defaultOrder' => ['order_num' => SORT_ASC],
],
]);
To select columns use the select() method of the ActiveQuery object.
If you are using GridView to display results, you can also use it's columns property.

Yii2, how to use or operator in rest request

I am trying to use or operator in my rest request Yii2 but I cannot succeed.
Everytime I have this error :
[
{
"field": "filter",
"message": "Operator \"or\" requires multiple operands."
}
]
I tested several things but nothing works.
I want to filter
statut=0 or statut=1
Do you know or I can do it ?
I tried to
http://url/api/tickets/gestions?filter[or][statut][statut]=[0,1]
But it does not work
Here's the method within controller that manage this request :
public function actionIndex()
{
return ActionsHelper::actionIndex(
$this->modelClass,
$this->modelClass . 'Search'
);
}
$this->modelClass is defined above and is equal to 'api\modules\tickets\models\TicketGestion';
Here is ActionsHelper::actionIndex
public function actionIndex($model, $searchModel = null, $moreFilter = null,
$pagination = false)
{
$filterCondition = null;
if ($searchModel) {
$filter = new ActiveDataFilter([
'searchModel' => $searchModel
]);
if ($filter->load(\Yii::$app->request->get())) {
$filterCondition = $filter->build();
if ($filterCondition === false) {
return $filter;
}
}
}
$query = $model::find();
if ($filterCondition !== null) {
$query->andWhere($filterCondition);
}
if ($moreFilter !== null) {
$query->andWhere($moreFilter);
}
if ($pagination !== false) {
$pagination = [
'pageSize' => 100
];
}
return new ActiveDataProvider([
'query' => $query,
'pagination' => $pagination
]);
}
Here's the search model, generated by Gii
<?php
namespace api\modules\tickets\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use api\modules\tickets\models\TicketGestion;
/**
* TicketGestionSearch represents the model behind the search form of `api\modules\tickets\models\TicketGestion`.
*/
class TicketGestionSearch extends TicketGestion
{
/**
* {#inheritdoc}
*/
public function rules()
{
return [
[['id', 'priorite', 'quicree', 'quirea', 'statut', 'recurrentid', 'typerea', 'client'], 'integer'],
[['dispatch', 'service', 'type', 'sujet', 'datecrea', 'dateecheance', 'daterea'], 'safe'],
[['duree'], 'number'],
];
}
/**
* {#inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search($params)
{
$query = TicketGestion::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
if ($this->dispatch == 'null') {
$this->dispatch = 1;
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'priorite' => $this->priorite,
'quicree' => $this->quicree,
'quirea' => $this->quirea,
'datecrea' => $this->datecrea,
'dateecheance' => $this->dateecheance,
'daterea' => $this->daterea,
'duree' => $this->duree,
'statut' => $this->statut,
'recurrentid' => $this->recurrentid,
'typerea' => $this->typerea,
'client' => $this->client,
]);
$query->andFilterWhere(['like', 'service', $this->service])
->andFilterWhere(['like', 'type', $this->type])
->andFilterWhere(['like', 'sujet', $this->sujet])
->andFilterWhere(['likes', 'dispatch', $this->dispatch]);
return $dataProvider;
}
}
You were on a right track, using ActiveDataFilter, but building arrays from get is done like this (example is from my controller):
http://localhost/ntb/web/index.php?r=assembly%2Findex&filter[or][0][status]=1004&filter[or][1][status]=1005&page=1&per-page=10
so for your example it should be like this:
http://url/api/tickets/gestions?filter[or][0][statut]=0&filter[or][1][statut]=1
This was the way to build a working 'or' filter for me.

Yii2 show active() records on a new index page of the same controller

I don't even know how to define my question, so I couldn't really search for an answer, so it would be appreciated if you could point me to the right direction.
I have a model a view and a controller. Normally if I'm calling index, I'm getting all records. That works fine. Now I would like to query from the DB only the active() records. So I would like to see on a new index page only the active records. Where do I have to define this? Of course, the function itself is already defined in ModelQuery. But in Controller, I have to create a new function, in order to be able to call a new view.
public function actionIndex2() {
$searchModel = new ModelSearch;
$dataProvider = $searchModel->search($_GET);
...
return $this->render('index2', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
I have tried to add ->active() to all possible places here but no luck. I can't mess with ModelSearch, because then I would ruin basic index site functionality also. It's clear that I can use it when I'm doing so: Order::find()->active(), but now it's not the case. Do I have to create a new ModelSearch also? I hope it's not necessary. Many thanks!
Assuming you want filter by $id eg in your url /index2?id=10) you could try this way
public function actionIndex2($id) {
$searchModel = new ModelSearch;
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$dataProvider->query->
andWhere(['id' => $id]);
...
return $this->render('index2', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
}
So officially you have to add your ActiveQueries to the search method of your ModelSearch.
public function search($params) {
$query = Model::find()->activeQuery1()->activeQuery2();
$dataProvider = new ActiveDataProvider([
'query' => $query,
...
or
public function search($params) {
$query = Model::find();
$dataProvider = new ActiveDataProvider([
'query' => $query->activeQuery1()->activeQuery2(),
...
This means you have to create a new ModelSearch or a new search method in ModelSearch as many times as many combinations of ActiveQueries you wish to use.

How would I test for this line in Codeception

I am writing some unit tests and struggling to capture the 1 remaining line of this small model in Yii2.
UserSearch.php
public function search($params)
{
$query = User::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// $query->where('0=1');
return $dataProvider; // This line in tests is red and marked as not executed
}
// grid filtering conditions
$query->andFilterWhere([
'id' => $this->id,
'date_added' => $this->date_added,
'last_login' => $this->last_login,
]);
$query->andFilterWhere(['like', 'username', $this->username])
return $dataProvider;
}
UserTest.php
public function testUserSearch()
{
$model = new UserSearch();
expect_that($model->search(['id' => 2]));
}
public function testInvalidDataProvider()
{
$model = new UserSearch();
expect_that($model->search(['id' => '2']));
}
The second test passes correctly as !this->Validate() method fails as id isn't an integer, why isn't the return statement reflected as executed in the code coverage. what am I misunderstanding here?
Integer must contain only digits [see validation]: https://github.com/yiisoft/yii2/blob/master/framework/validators/NumberValidator.php#L51 '2' is valid integer
model->search() return ActiveDataProvider. Is correct.

LIMIT is not working in ActiveDataProvider

I am using following code and the limit doesnt work. But if I see the command than it shows limit in that, but when I pass the query to ActiveDataProvider it fetch all the records:
$data= User::find()->where(['category_id'=> 5])->orderBy(['rand()' => SORT_DESC])->limit(4);
$command = $data->createCommand();
$data2 = $command->queryAll();// This works fine and fetch only 4 data
$dataProvider = new ActiveDataProvider([
'query' => $data,
]); // But this displays all data without limit
What is wrong I am doing here?
Here is what happens when preparing models in yii\data\ActiveDataProvider:
/**
* #inheritdoc
*/
protected function prepareModels()
{
if (!$this->query instanceof QueryInterface) {
throw new InvalidConfigException('The "query" property must be an instance of a class that implements the QueryInterface e.g. yii\db\Query or its subclasses.');
}
$query = clone $this->query;
if (($pagination = $this->getPagination()) !== false) {
$pagination->totalCount = $this->getTotalCount();
$query->limit($pagination->getLimit())->offset($pagination->getOffset());
}
if (($sort = $this->getSort()) !== false) {
$query->addOrderBy($sort->getOrders());
}
return $query->all($this->db);
}
We're interested in this part:
if (($pagination = $this->getPagination()) !== false) {
$pagination->totalCount = $this->getTotalCount();
$query->limit($pagination->getLimit())->offset($pagination->getOffset());
}
So as you can see if pagination is not false, limit is managed automatically.
You can just set pagination to false and then manual setting of limit will work:
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false,
]);
You can use Limit in the ActiveDataProvider and keep Pagination like so:-
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => 50,
],
]);
$dataProvider->setTotalCount(1000);
This will make $this->getTotalCount() = 1000 and Keep the pagination.
Go here and here for more reference.