Yii2 ArrayHelper::map left join select - php

I have users, orders and plans. When client buy plan, data is save in orders , plans are in account_plan and the information for user is in table users. In table orders is when the plan start and when it is expired. I use for Select2 ArrayHelper, but do not show the column
here is a query
$masAcc[0] = Yii::t('app', 'Choose plan');
$masAcc['----------------'] =
ArrayHelper::map(
\backend\models\Orders::find()
->select('orders.*,account_planLang.name as name')
->leftJoin('orders_props','`orders_props`.`order_id`= `orders`.`id`')
->leftJoin('account_plan','`orders_props`.`product_id`=`account_plan`.`id`')
->leftJoin('account_planLang','account_plan.id=account_planLang.plan_id')
->where('`orders`.`dt_end`<CURDATE() + INTERVAL 5 DAY AND `orders`.`dt_end`<CURDATE()')
->all(), 'id', 'name');
but the error is :
Getting unknown property: backend\models\Orders::name
here is Select2:
$form->field($model, 'account')->widget(Select2::classname(), [
'model' => $model,
'theme' => 'bootstrap',
'options' => [
'placeholder' => Yii::t('app', 'app.choose'),
'class' => 'form-control select2'
],
'data' => $masAcc,
'pluginOptions' => [
'allowClear' => true,
],
]);
}

That is because your query returns list of Orders models, which does not have name column, so it cannot represent result of this query. You need to use asArray() when you want to query field that is not available in model:
ArrayHelper::map(
\backend\models\Orders::find()
->select('orders.*,account_planLang.name as name')
->leftJoin('orders_props','`orders_props`.`order_id`= `orders`.`id`')
->leftJoin('account_plan','`orders_props`.`product_id`=`account_plan`.`id`')
->leftJoin('account_planLang','account_plan.id=account_planLang.plan_id')
->where('`orders`.`dt_end`<CURDATE() + INTERVAL 5 DAY AND `orders`.`dt_end`<CURDATE()')
->asArray() // <- this
->all(),
'id',
'name'
);
Or add name field to your model:
class Orders extends ActiveRecord {
public $name;
// ...
}

I guess there is no need to use ArrayHepler::map(). Try this way:
Orders::find()
->select('account_planLang.name as name, table_name.id as id')
->leftJoin('orders_props','`orders_props`.`order_id`= `orders`.`id`')
->leftJoin('account_plan','`orders_props`.`product_id`=`account_plan`.`id`')
->leftJoin('account_planLang','account_plan.id=account_planLang.plan_id')
->where('`orders`.`dt_end`<CURDATE() + INTERVAL 5 DAY AND `orders`.`dt_end`<CURDATE()')
->indexBy('id')
->column();

Related

How to use CRUD controller Index (list table) in other controller

I want to make the list of table who have relation only, example:
Table:
Order
Process
In ProcessCrudController I want to replace the Process list view into Order list view that only have relation (order-process).
The solution I've tried:
Create new function in OrderCrudController return view($this->crud->getListView(), $this->data);
then, addClause using $request->type URL
The problem of that solution:
Not showing the action row in table
Easy to show all query if we try to remove URL
I really want to make the list view of Process that only already have relation to Order, or any suggestion/idea to make this happen?
NB: I'm struggling at this problem I didn't found the solution, help me please
EDIT (Adding Code):
OrderCrudController:
protected function setupListOperation()
{
// This is the solution that I described before
// $request = request();
// $this->crud->addClause('where', 'user_id', '=', $request->type ?? 1);
$this->crud->addColumns([
[
'name' => 'personal_name',
'label' => 'Name',
'type' => 'text',
],
[
'name' => 'notes',
'label' => 'Catatan',
'type' => 'textarea',
],
[
'name' => 'user_id',
'label' => 'Dibuat oleh',
'type' => 'select',
'entity' => 'user',
'attribute' => 'name',
'model' => 'App\User',
],
]);
}
ProcessCrudController:
protected function setupListOperation()
{
CRUD::setFromDb();
// This table should be listing Order's query and that only have a process (already created custom_create_view)
// That's why i want to take Order's table and not making new custom_list_view
}
you don't have to make a new view, you just modify the query result using addClause ....
in your ProcessCrudController in setupListOperation() add your clause:
$this->crud->addClause('has','order');
assuming that the relation name in Process model that point to Process is "order"

Yii2 - Removing an item from the dropDownList

In my ticket form I have a dropDownList for the employees, and in the employees model I have employee_status which is 'Available', 'Not Available'
If I change the status of the employee to 'Not Available' how am I going to remove it automatically from the dropDownList in Ticket form?
The Employee Dropdown from Ticket
<?= $form->field($model, 'employee_id')->dropDownlist(
ArrayHelper::map(Employee::find()->all(), 'id', 'employee_name'),
[
'prompt' => 'Select Employee ID',
'style' => 'width:200px'
]); ?>
You need to create a dependent dropdown for get employee list according to employee_status.Write down below code in view file for creating dependent dropdown :-
use yii\helpers\ArrayHelper;
echo $form->field($model, 'employee_status')->dropDownList([0=>'Available' , 1 => 'Not Available'],
[
'prompt' => 'Select Employee Status',
'style' => 'width:200px',
'onchange'=>'$.post( "'.Yii::$app->urlManager->createUrl('site/get-employee?status=').'"+$(this).val(), function( data ) {
$( "select#employee-employee_id" ).html( data );
});']);
<?= $form->field($model, 'employee_id')->dropDownlist(
ArrayHelper::map(Employee::find()->all(), 'id', 'employee_name'),
[
'prompt' => 'Select Employee ID',
'style' => 'width:200px'
]); ?>
Now write a controller action for get data for child dropdown. Controller action code like below :-
SiteController.php
public function actionGetEmployee($status)
{
$employee= \common\models\Employee::find()
->where(['status' => $status])
->orderBy('id DESC')
->all();
if (!empty($employee)) {
foreach($employee as $employee) {
echo "<option value='".$employee->id."'>".$employee->name."</option>";
}
} else {
echo "<option>-</option>";
}
}
Note : change the model namespace according to your code.
Perform a find query with your given criteria.
Since we only ever want available employees in our list, we can write:
Employee::find('status=:status', [
':status' => 'Available'
])->all();
I finally get it
<?= $form->field($model, 'employee_id')->dropDownlist(
ArrayHelper::map(Employee::find()->where(['status' => 'Available'])->all(), 'id', 'employee_name'),
[
'prompt' => 'Select Employee ID',
'style' => 'width:200px'
]); ?>

Kartik DateRangePicker with two attributes cause invalidDateFormat and NaN on range date selection

I've a question about the Kartik DateRangePicker Widget that i use in my gridview for filter some results.
in my SearchModel i've created two attributes
public $date_start;
public $date_end;
i use these for filter a field in database 'insert_date'.
In my view, as grid configuration, i've set these options
[
'attribute' => 'insert_date',
'options' => ['class' => 'gridview-date-column'],
'filter' => DateRangePicker::widget([
'model' => $searchModel,
'name' => 'insert_date',
'attribute' => 'insert_date',
'startAttribute' => 'date_start',
'endAttribute' => 'date_end',
'convertFormat'=>true,
'pluginOptions' => [
'opens'=>'right',
'locale' => [
'cancelLabel' => 'Clear',
'format' => 'd-m-Y',
],
]
]),
'format' => ['date', Yii::$app->formatter->datetimeFormat],
'contentOptions'=>['style'=>'min-width: 200px;']
],
By default $date_start and $date_end haven't a value, so , when i enter in my view and try to filter this field i get an 'invalidDate' error and a series of NaN on the calendars.
This is fixed if i set a value for these two fields or if remove them from the configuration ( so i can only use insert_date attribute as string with these two ranges for filtering ).
Looking in the plugin repository i've found the same case and as response of the author
This problem occurs because you have an invalid date format for the data that does not match the plugin's format.
But as empty these fields can never have a correct data format.
Someone had the same problem?
Thanks in advance for all the responses.
I've got the solution:
In Kartik plugin there's a Behavior Model that i can include in my searchModel:
use kartik\daterange\DateRangeBehavior;
Then i can instantiate it overriding behaviors() method:
public $date_start;
public $date_end;
public function behaviors() {
return [
[
'class' => DateRangeBehavior::className(),
'attribute' => 'insert_date',
'dateStartAttribute' => 'date_start',
'dateEndAttribute' => 'date_end',
'dateStartFormat' => 'd-m-Y',
'dateEndFormat' => 'd-m-Y',
]
];
}
and in the search() method:
public function search($params)
{
// Some other filters
if($this->date_start && $this->date_end) {
// filtered query
}
}
Hope this can help someone else.

yii2 Gridview does not show column with joined attributes

I have a model Certificates which has a foreign key application_id of another model called Application. So each certificate belongs to the single application.
Now there is a situation where I would like to show all the certificates of the existing user. The user id exist inside the application model like user_id.
This is the query
SELECT * FROM `certificates`
inner join applications b ON
application_id = b.id where b.user_id = 7
Now based on the records coming from the above query I would like to show some columns of the certificates and some from the applications using grid view. But for some reasons, if records are more than one then I don't get any column data from the application.
<?php Pjax::begin(); ?> <?= GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'application_id',
'verified_application_file_path',
'certificate_name',
'application.name',
'application.user_id',
[
'attribute' => 'creation_date',
'format' => ['date', 'php:d/m/Y']
],
[
'attribute' => 'expiry_date',
'format' => ['date', 'php:d/m/Y']
],
],
]); ?>
<?php Pjax::end(); ?></div>
The above grid shows name and user id if a single record get return otherwise it shows "Not set". I Am not sure why 'application.name' and 'application.user_id'are not working when more than one records receive.
Here is my query using yii2
/**
* Creates data provider instance with search query applied
*
* #param array $params
*
* #return ActiveDataProvider
*/
public function search_vendor_certificates($user_id)
{
$query = ApplicationCertificates::find()->joinWith('application b',true , 'INNER JOIN')->where(["b.user_id"=>$user_id]);
// add conditions that should always apply here
$dataProvider = new \yii\data\ActiveDataProvider([
'query' => $query,
]);
return $dataProvider; }
I will appreciate if someone would tell me what is the mistake I am doing in displaying the proper attributes of the application model.
First of all (don't use this, i'll show u an logical mistake):
->joinWith('application b',true , 'INNER JOIN')
U set alias for application b, and then in GridView use application. Anyway, it's still bad if u rename it to b in GridView.
Based on this answer:
Model TableTwo:
public function getTableOneRecord()
{
return $this->hasOne(TableOne::className(), ['id' => 't1_id']);
}
public function getTableThreeRecord()
{
return $this->hasOne(TableThree::className(), ['id' => 't3_id']);
}
public function getTableFourRecord()
{
return $this->hasOne(TableFour::className(), ['id' => 't4_id'])
->via('tableThreeRecord');
}
And the view file:
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'id',
't1_id',
'tableOneRecord.id',
't3_id',
'tableThreeRecord.id',
'tableThreeRecord.t4_id',
'tableFourRecord.id',
],
]);
In easiest way to say, your relation from search won't work in GridView, you have to define relations in Model and then use thems ;)
See the code on GitHub

column aliasing in find() select in yii2

I have 2 user_id in 2 tables and i want both idies in this query result
So how can i do it?
$ids = JobUser::find()->select('job_user.user_id AS agentId,job.user_id AS userId')
->join('LEFT JOIN', 'job', 'job.id = job_user.job_id')
->where('job_user.status="done" AND (job_user.proposed_date_time BETWEEN "'.date('Y-m-d H:i:s').'" AND "'. date('Y-m-d H:i:s', (time() + 90000)).'")')
->all();
how can we do colunm aliasing in yii2 through active record?
Add a public field in model with the same exact name used in alias
class yourModel extends \yii\db\ActiveRecord
{
public $agentId; // alias
and the proper value in attributes
and refer to this field with the alias name eg: in gridView
'columns' => [
['class' => 'yii\grid\SerialColumn'],
//'tipo',
['attribute' => 'agentId',
'label' => 'Agent ID',

Categories