Yii2 ActiveQuery join relation issue - php

ActiveQuery doesn't select map.src_fin_position_id column
$query = FinancePossibleFinPositions::find()
->select (['dst.row_num', 'dst.src_value', 'map.src_fin_position_id'])
->from('finance.possible_fin_positions dst')
->leftJoin('finance.fin_pos_mapping map','map.map_fin_position_id = dst.possible_fin_positions_id')
->leftJoin('finance.possible_fin_positions src','src.possible_fin_positions_id = map.src_fin_position_id AND src.possible_fin_docs_id = :possible_fin_docs_id',[":possible_fin_docs_id"=> 95])
->where('dst.possible_fin_docs_id=:possible_fin_docs_id', [":possible_fin_docs_id"=> 88])
->orderBy('dst.row_num')
->all();
gives
array(2) {
["row_num"]=>
string(4) "1000"
["src_value"]=>
string(18) "My value"
}
although
$query = (new \yii\db\Query())
->select(["dst.row_num", "dst.src_value", "map.src_fin_position_id"])
->from('finance.possible_fin_positions dst')
->join('LEFT JOIN','finance.fin_pos_mapping map','map.map_fin_position_id = dst.possible_fin_positions_id')
->join('LEFT JOIN','finance.possible_fin_positions src','src.possible_fin_positions_id = map.src_fin_position_id AND src.possible_fin_docs_id = :possible_fin_docs_id',[":possible_fin_docs_id"=> $fin_doc])
->where('dst.possible_fin_docs_id=:possible_fin_docs_id', [":possible_fin_docs_id"=> $main_fin_doc])
->orderBy('dst.row_num')->all();
gives the result I need to get with ActiveQuery
array(3) {
["row_num"]=>
string(4) "1000"
["src_value"]=>
string(18) "My value"
["src_fin_position_id"]=>
int(3426)
}
I would use \yii\db\Query() but when I fill tabular form with this array the $_POST is empty.
Does anyone know how to solve this issue?
UPDATE
Simpler example
form.php
<div class="col-md-6">
<?php
$form = ActiveForm::begin(['id'=>'post-multiple','action' => ['submit-posts']]);
echo TabularForm::widget([
'form' => $form,
'dataProvider' => $dataProvider,
'serialColumn' => false,
'actionColumn' => false,
'checkboxColumn' => false,
'attributes' => [
'post_id' => ['type' => TabularForm::INPUT_STATIC, 'columnOptions'=>['hAlign'=>GridView::ALIGN_CENTER]],
'post_title' => ['type' => TabularForm::INPUT_STATIC],
'post_description' => ['type' => TabularForm::INPUT_TEXT, 'options' => ['class' => 'droppable']],
],
'gridSettings' => [
'floatHeader' => true,
'panel' => [
'heading' => '<h3 class="panel-title"><i class="glyphicon glyphicon-book"></i> Manage Books</h3>',
'type' => GridView::TYPE_PRIMARY,
'after'=>
Html::a(
'<i class="glyphicon glyphicon-plus"></i> Add New',
'#',
['class'=>'btn btn-success']
) . ' ' .
Html::a(
'<i class="glyphicon glyphicon-remove"></i> Delete',
'#',
['class'=>'btn btn-danger']
) . ' ' .
Html::submitButton(
'<i class="glyphicon glyphicon-floppy-disk"></i> Save',
['class'=>'btn btn-primary']
)
]
]
]);
ActiveForm::end(); ?>
</div>
Controllers
public function actionTabular()
{
// $query = (new \yii\db\Query())
// ->select("post_id, post_title, post_description")
// ->from('posts');
$query = Posts::find()->indexBy('post_id');
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false,
]);
return $this->render('tabular', [
'dataProvider'=>$dataProvider,
]);
}
public function actionSubmitPosts()
{
var_dump(Yii::$app->request->post());exit;
}
$query = Posts::find()->indexBy('post_id');
<input type="text" id="posts-40-post_description" class="droppable form-control ui-droppable" name="Posts[40][post_description]" value="tre">
$_POST is not empty
$query = (new \yii\db\Query())
->select("post_id, post_title, post_description")
->from('posts');
<input type="text" id="-28-post_description" class="droppable ui-droppable" name="[28][post_description]" value="tre">
$_POST is empty
Both queries fill the form correctly
The difference is inputs names. But I don't need to validate this form and it is strange why
[28][post_description] doesn't go into $_POST.

From Yii 2 Guide:
Note: If you call select() while eagerly loading relations, you have to make sure the columns referenced in the relation declarations are being selected. Otherwise, the related models may not be loaded properly. For example,
$orders = Order::find()->select(['id', 'amount'])->with('customer')->all();
// $orders[0]->customer is always null.
// To fix the problem, you should do the following:
$orders = Order::find()
->select(['id', 'amount', 'customer_id'])
->with('customer')->all();

I figured this out.
For yii\db\Query
I should have used
<?= Html::beginForm(['save-posts','method'=>'post']); ?>

Related

Laravel backpack edit form displaying checklist items with selected values from database

In my crud controller, There is one field called "roles (Multiple checklist)", While before saving the roles, I am converting array into string like 1,2,3 using implode.
Ex: CrudController
setUp() method
$options = [
'name' => 'roles',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
];
$this->crud->addField($options);
In Store method,
public function store(StoreRequest $request)
{
$sel_roles = $request->input("roles");
$roles = !empty($sel_roles) ? implode(",",$sel_roles) : "";
$request->request->set("roles",$roles);
//dd($request);
return parent::storeCrud($request);
}
Edit Method looks like this,
public function edit($id) {
$this->crud->hasAccessOrFail('update');
// get the info for that entry
$this->data['entry']= $this->crud->getEntry($id);
$options = [
'name' => 'roles',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
];
$this->crud->addField($options);
$this->data['crud'] = $this->crud;
$this->data['fields'] = $this->crud->getUpdateFields($id);
$this->data['id'] = $id;
return view('crud::edit', $this->data);
}
If am trying to access, Edit page, I am getting below error,
ErrorException in line 15:
Call to a member function pluck() on string (View: /var/www/html/app/vendor/backpack/crud/src/resources/views/fields/checklist.blade.php)
checklist.blade.php page looks like below
<div #include('crud::inc.field_wrapper_attributes') >
<label>{!! $field['label'] !!}</label>
<?php $entity_model = $crud->getModel(); ?>
<div class="row">
#foreach ($field['model']::all() as $connected_entity_entry)
<div class="col-sm-4">
<div class="checkbox">
<label>
<input type="checkbox"
name="{{ $field['name'] }}[]"
value="{{ $connected_entity_entry->id }}"
#if( ( old( $field["name"] ) && in_array($connected_entity_entry->id, old( $field["name"])) ) || (isset($field['value']) && in_array($connected_entity_entry->id, $field['value']->pluck('id', 'id')->toArray())))
checked = "checked"
#endif > {!! $connected_entity_entry->{$field['attribute']} !!}
</label>
</div>
</div>
#endforeach
</div>
{{-- HINT --}}
#if (isset($field['hint']))
<p class="help-block">{!! $field['hint'] !!}</p>
#endif
</div>
How do I display the roles with selected values in the edit page.
Thanks
After hours of debug and verified,
Send the edit values in the collection format,
$options = [
'name' => 'role_id',
'label' => 'Roles',
'type' => 'checklist',
'entity' => 'roles',
'attribute' => 'name',
'model' => "Backpack\PermissionManager\app\Models\Role",
"value" => collect([$edit_value_array])
];

CakePHP 3.6: Update control value based on the selection of a dropdown control

I have the following tables:
customers[id, name, surname, phone, text, balance, created]
service_types[id, title, price, length, is_subscription, created, payment]
customer_service_types[id, customer_id, service_type_id, price, created]
And the relations:
ServiceTypesTable.php:
$this->hasMany('CustomerServiceTypes', [
'foreignKey' => 'service_type_id'
]);
CustomerServiceTypesTable.php:
$this->belongsTo('Customers', [
'foreignKey' => 'customer_id',
'joinType' => 'INNER'
]);
$this->belongsTo('ServiceTypes', [
'foreignKey' => 'service_type_id',
'joinType' => 'INNER'
]);
In CustomerServiceTypes\add.ctp I have a dropdown with the services and a field for the price:
echo $this->Form->control('customer_id', ['options' => $customers,'label' => 'Customer']);
echo $this->Form->control('service_type_id', ['options' => $serviceTypes, 'label' => 'Service']);
echo $this->Form->control('price', ['label' => 'Price']);
In the CustomerServiceTypesController.php:
public function add($customerid = null)
{
$customerServiceType = $this->CustomerServiceTypes->newEntity();
if ($this->request->is('post')) {
$customerServiceType = $this->CustomerServiceTypes->patchEntity($customerServiceType, $this->request->getData());
if ($this->CustomerServiceTypes->save($customerServiceType)) {
//debug($this->request->getData("customer_id"),true);
$this->Flash->success(__('Success'));
return $this->redirect(['controller' => 'customers', 'action' => 'edit', $customerid]);
}
$this->Flash->error(__('Fail'));
}
$customers = $this->CustomerServiceTypes->Customers->find('list', ['limit' => 200])->where(['Customers.id =' => $customerid]);
$serviceTypes = $this->CustomerServiceTypes->ServiceTypes->find('list', [
'valueField' => function ($row) {
return $row['title'] . ' (Suggested price: ' . $row['price'] . ')';
}
], ['limit' => 200]);
$this->set(compact('customerServiceType', 'customers', 'serviceTypes'));
}
Which adds in the services dropdown valuefield the value of the specific service:
Service_1 (Suggested price: 100)
Service_2 (Suggested price: 150)
.....
But what I want to achieve is to update the price field with the suggested price when user makes a selection in the dropdown field. Is it possible to achieve that server side? Without the use of javascript? Because my knowledge is very limited in javascript. If not can you provide a working example based on my question?
Make Following changes:
add.ctp
<div ng-app="" ng-init='servicePrices = <?php echo json_encode($servicePrices); ?>;' >
<?php
echo $this->Form->create();
echo $this->Form->control('customer_id', ['options' => $customers,'label' => 'Customer']);
echo $this->Form->control('service_type_id', [
'options' => $serviceTypes, 'label' => 'Service',
'ng-model'=>'service_type_id'
]);
echo $this->Form->control('price', [
'label' => 'Price',
'ng-model'=>'servicePrices[service_type_id]'
]);
echo $this->Form->submit('submit');
?>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js" ></script>
CustomerServiceTypesController.php
// add this
$servicePrices = $this->CustomerServiceTypes
->ServiceTypes
->find()
->limit(200)
->combine('id','price');
$this->set(compact('customerServiceType', 'customers', 'serviceTypes','servicePrices'));

Yii2 Pjax reloads the page

I have a Pjax container in which i want to load either books or authors.My active form has two tabs by which i choose what to load. I tested my sql in phpmyadmin and they are ok(returns what expected). Tried to var_dump after each row of my controller but it seems to be ok also. But when i comes to the 'magic of the pjax' the page get reloaded. There is no errors in the console log. The response from the request in the Network tab returns the whole html. Can you take a look and give and advance?
Controller action:
public function actionSingleGenre(){
$first_step = Yii::$app->getRequest()->getQueryParam('first_step');
$second_step = Yii::$app->getRequest()->getQueryParam('second_step');
$id = end(explode('-', $second_step));
$genresPage = Page::findOne(76);
$booksPage = Page::findOne(45);
$authorsPage = Page::findOne(46);
$lang = Lang::getCurrent();
$genre = Brands::findOne($id);
$banner = CategoryImage::find()->where(['page_id' => $genresPage->id])->one();
$pageSize = 12;
$entity = 'book';
$sql = "SELECT *
FROM `product` as p
LEFT JOIN `productLang` as pl ON p.`id`=pl.`product_id`
LEFT JOIN `book_brand` as bb ON p.`id`=bb.`book_id`
WHERE bb.`brand_id`=$id";
if(Yii::$app->request->isPjax){
if(isset($_GET['type']) && $_GET['type'] != ''){
$type = $_GET['type'];
if($type == 1){
$sql = "SELECT *
FROM `product` as p
LEFT JOIN `productLang` as pl ON p.`id`=pl.`id`
LEFT JOIN `book_brand` as bb ON p.`id`=bb.`book_id`
WHERE bb.`brand_id`=$id";
}
else if($type == 2)
{
$sql = "SELECT *
FROM `author` as a
LEFT JOIN `authorLang` as al ON a.`id`=al.`author_id`
WHERE a.`id` IN (
SELECT p.`author_id`
FROM `product` as p
LEFT JOIN `book_brand` as bb ON p.`id`=bb.`book_id`
WHERE bb.`brand_id`=$id
)";
$entity = 'author';
}
}
}
$count = count(Yii::$app->db->createCommand($sql)->queryAll());
$dataProvider = new SqlDataProvider([
'sql' => $sql,
'totalCount' => $count,
'pagination' => [
'pageSize' => $pageSize,
'route' => $first_step . '/' . $second_step
]
]);
$models = $dataProvider->getModels();
$pagination = new Pagination([
'pageSize' => $pageSize,
'totalCount' => $count,
'route' => $first_step . '/' . $second_step
]);
if(Yii::$app->request->isPjax){
return $this->renderAjax('single-genre', [
'genresPage' => $genresPage,
'authorsPage' => $authorsPage,
'lang' => $lang,
'banner' => $banner,
'booksPage' => $booksPage,
'genre' => $genre,
'models' => $models,
'pagination' => $pagination,
'entity' => $entity,
]);
}
return $this->render('single-genre', [
'genresPage' => $genresPage,
'authorsPage' => $authorsPage,
'lang' => $lang,
'banner' => $banner,
'booksPage' => $booksPage,
'genre' => $genre,
'models' => $models,
'pagination' => $pagination,
'entity' => $entity,
]);
}
jQuery:
function pjaxFilterForm() {
var dataString = $("#filter-group2").serialize();
$.pjax.defaults.timeout = false;
$.pjax({
container: "#booksGrid",
url: location.href.split("?")[0],
data: dataString,
scrollTo: false
});
return false;
}
View:
<div class="filter-tags-holder">
<?php \yii\bootstrap\ActiveForm::begin([
'method' => 'get',
'action' => '#',
'options' => ['data-pjax'=>true, 'onsubmit'=>'return pjaxFilterForm()', 'id'=>'filter-group2']
]) ?>
<div id="submit-helper-tab"></div>
<input type="hidden" name="type">
<ul id="filterGenresList" class="option-set">
<li><a class="selected" data-value="1" href="#"><?= Yii::t('app', 'app.Books') ?></a></li>
<li><a data-value="2" href="#"><?= Yii::t('app', 'app.Authors') ?></a></li>
</ul>
<?php \yii\bootstrap\ActiveForm::end(); ?>
</div>
<!-- Filter Nav -->
<!-- Recommended -->
<?php \yii\widgets\Pjax::begin(['id'=>'booksGrid']) ?>
<?php if($models) : ?>
<div id="filter-masonry" class="gallery-masonry">
<?php foreach ($models as $model){
if($entity == 'book'){
$model = \backend\modules\products\models\Product::findOne($model['product_id']);
echo $this->render('_authorBooks', ['book' => $model, 'lang' => $lang, 'booksPage' => $booksPage]);
}else if($entity == 'author'){
$model = \backend\models\Author::findOne($model['author_id']);
echo $this->render('_authorGenre', ['book' => $model, 'lang' => $lang, 'authorsPage' => $authorsPage]);
}
} ?>
</div>
<div class='pagination-holder'>
<?= \yii\widgets\LinkPager::widget([
'pagination' => $pagination,
'hideOnSinglePage' => true,
'prevPageLabel' => Yii::t('app', 'app.Prev'),
'nextPageLabel' => Yii::t('app', 'app.Next')
]) ?>
</div>
<?php endif; ?>
<?php \yii\widgets\Pjax::end() ?>

Yii2 Implode beforeSave is not working

Basically, I have a model that I display to standard checkboxlist that have a value :
I got this from my model
echo $model->bundle_numbers;
Array
(
[0] => 1
[1] => 2
[2] => 3
)
So, In controller,
if ($model->load($request->post()) && $model->save()) {
return [
'forceReload' => '#crud-datatable-pjax',
'title' => "Create new OutgoingPipe",
'content' => '<span class="text-success">Create Outgoing Pipe success</span>',
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::a('Create More', ['create'], ['class' => 'btn btn-primary', 'role' => 'modal-remote'])
];
}
Now I wnat to change the array into string format :
So, use beforeSave :
public function beforeSave($insert){
$this->bundle_numbers = implode(",", $this->bundle_numbers);
return parent::beforeSave($insert); // TODO: Change the autogenerated stub
}
In rules, based Gii generator model, I remove string rules
[['bundle_numbers'], 'string', //deleted
But still not success to insert the data.
No errors displayed.
Please advise.
** update **
I can see all errors,
$model->save(false);
$model->getErrors();
Now, I can see, I have a lot of errors in another rule.
By the way, thanks for the help.
public function beforeSave($insert){
if (parent::beforeSave($insert)) {
$this->bundle_numbers = implode(",", $this->bundle_numbers);
return $this->bundle_numbers;
} else {
return false;
}
}
try this
Try if you have some error in load or validate
if ($model->load($request->post()) {
if ($model->save()){
return [
'forceReload' => '#crud-datatable-pjax',
'title' => "Create new OutgoingPipe",
'content' => '<span class="text-success">Create Outgoing Pipe success</span>',
'footer' => Html::button('Close', ['class' => 'btn btn-default pull-left', 'data-dismiss' => "modal"]) .
Html::a('Create More', ['create'], ['class' => 'btn btn-primary', 'role' => 'modal-remote'])
];
} else {
var_dump('save fail');
var_dump( $model->errors);
}
do like this
<?php
if ($model->load($request->post()) {
$model->bundle_numbers = implode(",", $model->bundle_numbers);
$model->save();
return //wherever you want return
}

How can I get the selected data/item rows in CheckboxColumn Gridview - Yii2

I have a problem on getting all the selected values/data Yii2 Gridview using checkboxColumn.
I can only get one of the value in the grid using this code:
'class' => 'yii\grid\CheckboxColumn',
'checkboxOptions' => function($model, $key, $index, $widget) {
return ['value' => $model['item_id'] ];
},
Need some suggestions on how can I get all the values in the grid...
Here is my Code Code snippet Controller/View:
Controller:
public function actionBulk(){
$action=Yii::$app->request->post('action');
$selection=(array)Yii::$app->request->post('selection');
print_r($selection);
}
View:
<?=Html::beginForm(['transjournal/bulk'],'post');?>
<?=GridView::widget([
'dataProvider' => $dataProvider,
'bordered'=>true,
'striped'=>true,
'condensed'=>true,
'hover'=>true,
'export' => false,
'showOnEmpty' => false,
'panel'=>[
'after'=>Html::submitButton('<i class="glyphicon glyphicon-plus"></i> Posted', ['class' => 'btn btn-success']),
],
'columns' => [
[
'class' => 'yii\grid\CheckboxColumn',
'checkboxOptions' => function($model, $key, $index, $widget) {
return ['value' => $model['item_id'] ];
},
],
'item_id',
'description',
],
]);
?>
<?= Html::endForm();?>
Here is my attachment:
This is the GridView
This is the Result in the GridView (Selected Data only returns item_id)
How can I return both item_id and description?
Issue with your code 'checkboxOptions' =>, can you remove it?
<?=Html::beginForm(['controller/bulk'],'post');?>
<?=Html::dropDownList('action','',[''=>'Mark selected as: ','c'=>'Confirmed','nc'=>'No Confirmed'],['class'=>'dropdown',])?>
<?=Html::submitButton('Send', ['class' => 'btn btn-info',]);?>
<?=GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\CheckboxColumn'],
...
],
]); ?>
<?= Html::endForm();?>
In Controller:
public function actionBulk(){
$action=Yii::$app->request->post('action');
$selection=(array)Yii::$app->request->post('selection');//typecasting
foreach($selection as $id){
$model = Post::findOne((int)$id);//make a typecasting
//do your stuff
$model->save();
// or delete
}
}
basically, i am using yii's CheckboxColumn:
<?php
namespace common\grid;
class CheckboxColumn extends \yii\grid\CheckboxColumn {
public $headerOptions = ['class' => 'text-center', 'style' => 'width: 5em'];
public $contentOptions = ['class' => 'text-center'];
}
?>
then i wrote a jquery plugin for triggering operations with selected items, plus custom Actions and so on, here the relevant javascript code, where options.grid is the id/selector for your grid, e.g. '#grid':
var selection = [];
$(options.grid + ' input:checkbox[name="selection[]"]:checked').each(function() {
selection.push($(this).val());
});
so var selection contains an array with my item ids. length is:
selection.length

Categories