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.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I want to create searchModel with Yii2, my query have default limit is 7, and I have an input dropdownlist on the page to switch limit of query between 7 and 30.
How I can do this?
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($modelSearch, 'limit')->dropDownlist([
7 => '7 days',
30 => '30 days',
]); ?>
<?php ActiveForm::end(); ?>
and this is Model
class SearchModel extend \yii\base\Models
{
public $limit;
public function search($params) {
$query = Objects::find()->where(['attribute1'=>'a', 'attribute2'=>b]);
$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => ['attributes' => ['attribute1', 'attribute2',]]
]);
$this->load($params);
return $dataProvider;
}
}
and this is controller
public function actionIndex()
{
$searchModel = new ModelSearch();
$dataProvider = $searchModel->search(Yii::$app->request->post());
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
I've tried to add
if(empty($params['limit'])) {
$query->limit(7);
}else {
$query->limit($params['limit']);
}
into the models - it worked but I think it's not a smart way to resolve it.
You may define SearchModel like:
<?php
namespace app\models\search;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use app\models\Human;
/**
* Class HumanSearch
*
* #package app\models\search
*/
class HumanSearch extends Model
{
/**
* #var int $limit
*/
public $limit;
/**
* #return array
*/
public function rules(): array
{
return [
[['limit'], 'integer', 'min' => 7, 'max' => 30], // Limit can be between 7 and 30.
[['limit'], 'default', 'value' => 7], // Default query limit is 7 rows.
];
}
/**
* #param array $params
*
* #return ActiveDataProvider
*/
public function search(array $params): ActiveDataProvider
{
// Initialize query.
$query = Human::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// Load additional params to search model.
if (!$this->load($params) && $this->validate()) {
return $dataProvider;
}
// Set query limit.
$query->limit($this->limit);
return $dataProvider;
}
}
And then use it in actionIndex() in Controller:
<?php
namespace app\controllers;
use Yii;
use yii\rest\Controller;
use yii\data\ActiveDataProvider;
use app\models\search\HumanSearch;
class HumanController extends Controller
{
public function actionIndex(): ActiveDataProvider
{
$params = Yii::$app->getRequest()->getQueryParams();
$search = new HumanSearch;
return $search->search($params);
}
}
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.
I've customized the query in FrameSearch Model and build my query with findbysql. I'm also trying to customize the action column. My gridview looks fine except the action Column.
Getting error -
FrameSearch Model Code -
<?php
namespace frontend\modules\framestock\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use frontend\modules\framestock\models\Frame;
use frontend\modules\framestock\models\Poitemframe;
use yii\db\Query;
use yii\db\Command;
/**
* FrameSearch represents the model behind the search form about `frontend\modules\framestock\models\Frame`.
*/
class FrameSearch extends Frame
{
public $purchase;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['f_id'], 'integer'],
[['f_brand', 'f_name','purchase'], 'safe'],
];
}
/**
* #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)
{
$subQuery1 = (new Query())->select(['poi_framename','sum(poi_qty) as purchased'])->from ('poitemframe')->join('LEFT JOIN','Frame','frame.f_name = poitemframe.poi_framename')->groupby('poi_framename');
$subQuery2 = (new Query())->select(['o_frame','count(o_frame) as sold'])->from ('orders')->join('LEFT JOIN','Frame','frame.f_name = orders.o_frame')->groupby('o_frame');
$query = (new Query())->select(['f_brand','f_name','COALESCE(pt.purchased,0)as purchased' , 'COALESCE(st.sold,0) as sold', '(COALESCE(pt.purchased,0) - COALESCE(st.sold,0)) as stock'])->from ('frame')->leftJoin(['pt' => $subQuery1],'pt.poi_framename = frame.f_name')->leftJoin(['st' => $subQuery2],'st.o_frame = frame.f_name');
// ->joinWith(['purchase']);
// $items = $query
// ->select([
// 'f_brand',
// 'f_name',
// 'sum(poitemframe.poi_qty) as purchased',
// ])
// //->where(['stock.product_id'=>3])
// ->groupBy('f_name')
// ->all();
// 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;
}
// grid filtering conditions
$query->andFilterWhere([
'f_id' => $this->f_id,
]);
$query->andFilterWhere(['like', 'f_brand', $this->f_brand])
->andFilterWhere(['like', 'f_name', $this->f_name]);
return $dataProvider;
}
}
index.php
<?php
use yii\helpers\Html;
use yii\grid\GridView;
use yii\db\Query;
use yii\db\Command;
/* #var $this yii\web\View */
/* #var $searchModel frontend\modules\framestock\models\FrameSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Frames';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="frame-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'f_brand',
'f_name',
'purchased',
'sold',
'stock',
[
'class' => 'yii\grid\ActionColumn',
'template' => '{ledger}',
'buttons' => [
'ledger' => function ($url, $model) {
return Html::a(
'<span class="glyphicon glyphicon-eye-open"></span>',
['/frame/ledger', 'f_name' => $model->f_name],
[
'title' => 'Ledger',
'data-pjax' => '0',
]
);
},
],
],
],
]); ?>
</div>
update
After adding exit;
Please tell me how to resolve this. I want to get the f_name from the action column button which I'll pass to another page to filter a grid.
I usually recommend to use ArrayHelper::getValue .
For example:
ArrayHelper::getValue($model, 'f_name')
will work when $model is some object (Model or ActiveRecord), array or empty (=null).
Moreover, it has 3nd argument for default value:
ArrayHelper::getValue($model, 'f_name', 'value that returned when attribute not found in $model')
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');
I have form of creating shop item which was generated by Gii.
So i myself must to enter id value. But I need to get rid of this field, and make an assignment automatically.
For auto assignment creating and updating time, i just adding this function in my module
public function behaviors() {
return [
TimestampBehavior::className(),
];
}
How can i do this for id value?
UPD
Rules:
public function rules() {
return [
[['category_id', 'title', 'desc', 'price', ], 'required'],
[['id', 'category_id', 'price', 'in_stock', 'discount', 'created_at', 'updated_at'], 'integer'],
[['desc', 'options', 'photos'], 'string'],
[['title'], 'string', 'max' => 100]
];
}
UPD 2
<?php
namespace backend\modules\shop\controllers;
use backend\modules\shop\models\ShopCategories;
use Yii;
use backend\modules\shop\models\ShopItems;
use backend\modules\shop\models\ShopItemsSearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* ItemsController implements the CRUD actions for ShopItems model.
*/
class ItemsController extends Controller {
public function behaviors() {
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
];
}
/**
* Lists all ShopItems models.
* #return mixed
*/
public function actionIndex() {
$searchModel = new ShopItemsSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single ShopItems model.
* #param integer $id
* #return mixed
*/
public function actionView($id) {
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new ShopItems model.
* If creation is successful, the browser will be redirected to the 'view' page.
* #return mixed
*/
public function actionCreate() {
$model = new ShopItems();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'category' => ShopCategories::find()->all()
]);
}
}
/**
* Updates an existing ShopItems model.
* If update is successful, the browser will be redirected to the 'view' page.
* #param integer $id
* #return mixed
*/
public function actionUpdate($id) {
$model = $this->findModel($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
'category' => ShopCategories::find()->all()
]);
}
}
/**
* Deletes an existing ShopItems model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* #param integer $id
* #return mixed
*/
public function actionDelete($id) {
$this->findModel($id)->delete();
return $this->redirect(['index']);
}
/**
* Finds the ShopItems model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* #param integer $id
* #return ShopItems the loaded model
* #throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id) {
if (($model = ShopItems::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
}
You should not include attributes that are managed automatically or by programmer in model validation rules. Validation make sense only for user entered data.
Remove id from that line and everything should be OK:
[['id', 'category_id', 'price', 'in_stock', 'discount', 'created_at', 'updated_at'], 'integer'],
created_at and updated_at are also redundant because they don't depend on user, so this is enough:
[['category_id', 'price', 'in_stock', 'discount'], 'integer'],
Update:
After deeper investigation we found that primary key didn't have auto increment. After executing this query problem disappeared:
ALTER TABLE `shop_items`
CHANGE COLUMN `id` `id` INT(11) NOT NULL AUTO_INCREMENT,
DROP PRIMARY KEY,
ADD PRIMARY KEY (`id`);
Credits for Miroslav's answer to this question.