How can I show attribute value with check Box in Yii 2 GridView - checkbox

i like to put mission_id in checkbox
$req = 'select c.mission_id as mission_id, c.user_id as user_id from order c';
$dataProvider = new SqlDataProvider([
'sql' => $req,
]);
return $this->render('factures', [
'dataProvider' => $dataProvider,
]);
in _index.php
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
'mission_id',
'user_id',
],
]); ?>
This it's ok, but when i use checkbox, it s KO : Trying to get property of non-object
[
'attribute' => 'id',
'format' => 'raw',
'value' => function($data) {
return '<input type="checkbox" name="chk_group" value="'.$data->mission_id.'" />Mission : '.$data->mission_id;
},
],
Your help please

a some response : Trying to get property of non-object with :
[
'attribute' => 'id',
'format' => 'raw',
'value' => function($model) {
return '<input type="checkbox" name="chk_group" value="'.$model->mission_id.'" />Mission : '.$model->mission_id;
},
],

Related

Showing Validation error below the input field in cakephp3.8

I am new to cake php and started to watch a video tutorial about cake php on youtube but I could only find the cake php version 3.6 whereas I am currently using the 3.8 one.
I have followed all the steps within the tutorial on youtube but in my case at the validation part the error is not showing up below the input field and I dont know why. Are there any options in 3.6 and 3.8 to show the error validation below the input field? Please see the attached What I want and What I did pictures.
my codes:
UsersController.php
<?php
namespace App\Controller;
class UsersController extends AppController
{
//User Login
public function login()
{
$this->set('title', 'Login');
}
// User registration
public function registration()
{
$this->set('title', 'Registration');
$users = $this->Users->newEntity($this->request->getData(), ['validate' => 'register']);
// Do work to show error messages.
$this->set('users', $users);
}
}
UsersTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class UsersTable extends Table
{
public function validationRegister(Validator $validator){
#Firstname
$validator->notEmpty('firstName');
#Lastname
$validator->notEmpty('lastName');
#Username
$validator->notEmpty('username')->lengthBetween('username', [4,18]);
#password
$validator->notEmpty('password');
#confirm password
$validator->notEmpty('confirmPassword')
->add('confirmPassword', 'no-misspelling',[
'rule' => ['compareWith', 'password'],
'message' => 'Password does not match',
]);
#email
$validator->notEmpty('email')->add('email', 'valid', [
'rule' => 'email',
'message' => 'Please enter a valid email',
]);
return $validator;
}
}
?>
Registration.ctp
<div class="container container-small mt-5">
<?php
//Set form Tempaltes
$myTemplates = [
'inputContainer' => '<div class="form-group">{{content}}</div>',
//'input' => '<input type="{{type}}" class = "form-control is-invalid" name="{{name}}"{{attrs}}/>',
'inputContainerError' => '<div class="input {{type}}{{required}} error">{{content}}{{error}}</div>',
'error' => '<div class="error-message">{{content}}</div>'
];
$this->Form->setTemplates($myTemplates);
echo $this->Form->create($users);
if($this->Form->isFieldError('firstName')){
echo '
<br>
<div class="alert alert-danger alert-dismissible fade show" role="alert">
Please fill up all the fields.
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
';
}else{
echo '';
}
// for multiple forms
echo $this->Form->controls(
[
'Firstname' => [
'name' => 'firstName',
'placeholder' => 'FirstName',
'required' => false,
'label' => 'First Name',
'class' => ($this->Form->isFieldError('firstName')) ? 'form-control is-invalid' : 'form-control'
],
'Lastname' => [
'name' => 'lastName',
'placeholder' => 'Lastname',
'required' => false,
'label' => 'Last Name',
'class' => ($this->Form->isFieldError('lastName')) ? 'form-control is-invalid' : 'form-control'
],
'Username' => [
'name' => 'username',
'placeholder' => 'Username',
'required' => false,
'class' => ($this->Form->isFieldError('username')) ? 'form-control is-invalid' : 'form-control'
],
'Password' => [
'type' => 'password',
'name' => 'password',
'placeholder' => 'Password',
'required' => false,
'class' => ($this->Form->isFieldError('password')) ? 'form-control is-invalid' : 'form-control'
],
'Confirm Password' => [
'type' => 'password',
'name' => 'confirmPassword',
'placeholder' => 'Confirm Password',
'required' => false,
'label' => 'Confirm Password',
'class' => ($this->Form->isFieldError('confirmPassword')) ? 'form-control is-invalid' : 'form-control'
],
'Email' => [
'name' => 'email',
'placeholder' => 'Email',
'required' => false,
'class' => ($this->Form->isFieldError('email')) ? 'form-control is-invalid' : 'form-control'
],
],
['legend' => 'Registration']
);
echo $this->Form->submit('Register', ['class' => 'btn btn-primary']);
echo $this->Form->end();
?>
</div>

How to display array data in Yii2 GridView using ActiveDataprovider?

In my db,
"email" : [
"amnop#mailinator.com",
"abc#mail.com"
],
When I print_r($model->email),
it shows
Array ( [0] => amnop#mailinator.com [1] => abc#mail.com )
In my GridView,
<?= GridView::widget([
'dataProvider' => $dataProvider,
----
'columns' => [
-----
'price',
[
'attribute' => 'email',
'value' => function($model) {
//I need help here... I prefer any foreach function
}
],
-----
]
?>
I have to display all the emails in the same column. How to do this?
Edit
I use ActiveDataprovider as I'm getting the values from my db.
Depending on what you want to achieve, you can just implode emails array:
[
'attribute' => 'email',
'value' => function($model) {
if (is_array($model->email)) {
return implode(', ', $model->email);
}
return $model->email;
}
],
assuming you an array as
$data = [
['email' => 'amnop#mailinator.com'],
['email' => 'abc#mail.com'],
...
['email' => 'youremail100#mail.com'],
];
you can use an ArrayDataProvider
$provider = new ArrayDataProvider([
'allModels' => $data,
'pagination' => [
'pageSize' => 10,
],
'sort' => [
'attributes' => [ 'email'],
],
]);
send the data provider to the as usual
so in gridview you can use ,
<?= GridView::widget([
'dataProvider' => $dataProvider,
----
'columns' => [
-----
'price',
[
'attribute' => 'email',
'value' => function($model) {
//I need help here...
}
],
-----
]
?>
you can take a look at yii2 guide https://www.yiiframework.com/doc/guide/2.0/en/output-data-providers
and doc https://www.yiiframework.com/doc/api/2.0/yii-data-arraydataprovider

cakephp: plumSearch - Changing filter's label in parameters

Using PlumSearch plugin, it is mentioned in its documentation that we can modify 'label':
formConfig: Contains Form::input $options settings like class, input type, label name...
In my controller/initialize(), I need to change the label of some fields ("IP Address" instead of "Ip Adress", "Status" instead of "Asset Status"):
public function initialize()
{
parent::initialize();
$parameters = [
['name' => 'serial_number', 'className' => 'Input'],
['name' => 'model_number', 'className' => 'Input'],
['name' => 'ip_address', 'label' => 'IP Address', 'className' => 'Input'],
];
if ($this->request->param('action') == 'reportFacility') {
$statuses = $this->AssetsAssignations->AssetStatuses->find('list')->order(['name' => 'asc']);
$this->set(compact('asset_statuses'));
$parameters = [
['name' => 'asset_status_id', 'className' => 'Select', 'label' => 'Status',
'finder' => $statuses
],
];
} elseif ($this->request->param('action') == 'reportClient') {
$clients = $this->AssetsAssignations->Clients->find('list')->order(['last_name' => 'asc', 'first_name' => 'asc']);
$this->set(compact('clients'));
$parameters = [
['name' => 'client_id', 'className' => 'Select', 'label' => 'Client',
'finder' => $clients
],
];
} elseif ($this->request->param('action') == 'reportRoom') {
$rooms = $this->AssetsAssignations->Rooms->find('list')->order(['name' => 'asc']);
$this->set(compact('rooms'));
$parameters = [
['name' => 'room_id', 'className' => 'Select', 'label' => 'Room',
'finder' => $rooms
],
];
}
$this->loadComponent('PlumSearch.Filter', ['parameters' => $parameters]);
}`
The code above did not work for labels.
I was told to use the following code:
$inputOptions = [
'search' => [
'placeholder' => __('Type to search...'),
'class' => 'form-control',
'label' => 'Search'
]
];
$this->set(compact('inputOptions'));
but I failed to determine where and how in my code.
Any help please ?
simply you have to add it to the $parameters array this way
$parameters = [
/* other fields here */
[
'name' => 'ip_address',
'className' => 'Input',
'formConfig' => ['label' => 'IP Address']
],
];

Using Yii2 with array of data and a Gridview with sorting and filter

I've an array
$resultData = [
array("id"=>1,"name"=>"Cyrus","email"=>"risus#consequatdolorvitae.org"),
array("id"=>2,"name"=>"Justin","email"=>"ac.facilisis.facilisis#at.ca"),
array("id"=>3,"name"=>"Mason","email"=>"in.cursus.et#arcuacorci.ca"),
array("id"=>4,"name"=>"Fulton","email"=>"a#faucibusorciluctus.edu"),
array("id"=>5,"name"=>"Neville","email"=>"eleifend#consequatlectus.com"),
array("id"=>6,"name"=>"Jasper","email"=>"lectus.justo#miAliquam.com"),
array("id"=>7,"name"=>"Neville","email"=>"Morbi.non.sapien#dapibusquam.org"),
array("id"=>8,"name"=>"Neville","email"=>"condimentum.eget#egestas.edu"),
array("id"=>9,"name"=>"Ronan","email"=>"orci.adipiscing#interdumligulaeu.com"),
array("id"=>10,"name"=>"Raphael","email"=>"nec.tempus#commodohendrerit.co.uk"),
];
A dataprovider :
$dataProvider = new ArrayDataProvider([
'key'=>'id',
'allModels' => $resultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
And the Gridview :
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'value' => 'email',
]
]
]);
As is, the code make me View the array in a grid, and the possibility to sort it when clicking on columns. That's ok.
But how to do to use filtering ?
I tried with the following :
$searchModel = ['id' => null, 'name' => '', 'email' => ''];
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'filter' => '<input class="form-control" name="filteremail" value="da" type="text">',
'value' => 'email',
]
]
]);
But it's not working.
Does I have to filter myself the object depending on the $get value ?
My solution with full code :
$resultData = [
array("id"=>1,"name"=>"Cyrus","email"=>"risus#consequatdolorvitae.org"),
array("id"=>2,"name"=>"Justin","email"=>"ac.facilisis.facilisis#at.ca"),
array("id"=>3,"name"=>"Mason","email"=>"in.cursus.et#arcuacorci.ca"),
array("id"=>4,"name"=>"Fulton","email"=>"a#faucibusorciluctus.edu"),
array("id"=>5,"name"=>"Neville","email"=>"eleifend#consequatlectus.com"),
array("id"=>6,"name"=>"Jasper","email"=>"lectus.justo#miAliquam.com"),
array("id"=>7,"name"=>"Neville","email"=>"Morbi.non.sapien#dapibusquam.org"),
array("id"=>8,"name"=>"Neville","email"=>"condimentum.eget#egestas.edu"),
array("id"=>9,"name"=>"Ronan","email"=>"orci.adipiscing#interdumligulaeu.com"),
array("id"=>10,"name"=>"Raphael","email"=>"nec.tempus#commodohendrerit.co.uk"),
];
function filter($item) {
$mailfilter = Yii::$app->request->getQueryParam('filteremail', '');
if (strlen($mailfilter) > 0) {
if (strpos($item['email'], $mailfilter) != false) {
return true;
} else {
return false;
}
} else {
return true;
}
}
$filteredresultData = array_filter($resultData, 'filter');
$mailfilter = Yii::$app->request->getQueryParam('filteremail', '');
$namefilter = Yii::$app->request->getQueryParam('filtername', '');
$searchModel = ['id' => null, 'name' => $namefilter, 'email' => $mailfilter];
$dataProvider = new \yii\data\ArrayDataProvider([
'key'=>'id',
'allModels' => $filteredresultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'filter' => '<input class="form-control" name="filteremail" value="'. $searchModel['email'] .'" type="text">',
'value' => 'email',
]
]
]);
On the previous soultion. I created a loop to make the filters, columns and searchModel.
$items = [
array("id" => 1, "name" => "Cyrus", "email" => "risus#consequatdolorvitae.org"),
array("id" => 2, "name" => "Justin", "email" => "ac.facilisis.facilisis#at.ca"),
array("id" => 3, "name" => "Mason", "email" => "in.cursus.et#arcuacorci.ca"),
array("id" => 4, "name" => "Fulton", "email" => "a#faucibusorciluctus.edu"),
array("id" => 5, "name" => "Neville", "email" => "eleifend#consequatlectus.com"),
array("id" => 6, "name" => "Jasper", "email" => "lectus.justo#miAliquam.com"),
array("id" => 7, "name" => "Neville", "email" => "Morbi.non.sapien#dapibusquam.org"),
array("id" => 8, "name" => "Neville", "email" => "condimentum.eget#egestas.edu"),
array("id" => 9, "name" => "Ronan", "email" => "orci.adipiscing#interdumligulaeu.com"),
array("id" => 10, "name" => "Raphael", "email" => "nec.tempus#commodohendrerit.co.uk"),
];
$searchAttributes = ['id', 'name', 'email'];
$searchModel = [];
$searchColumns = [];
foreach ($searchAttributes as $searchAttribute) {
$filterName = 'filter' . $searchAttribute;
$filterValue = Yii::$app->request->getQueryParam($filterName, '');
$searchModel[$searchAttribute] = $filterValue;
$searchColumns[] = [
'attribute' => $searchAttribute,
'filter' => '<input class="form-control" name="' . $filterName . '" value="' . $filterValue . '" type="text">',
'value' => $searchAttribute,
];
$items = array_filter($items, function($item) use (&$filterValue, &$searchAttribute) {
return strlen($filterValue) > 0 ? stripos('/^' . strtolower($item[$searchAttribute]) . '/', strtolower($filterValue)) : true;
});
}
echo GridView::widget([
'dataProvider' => new ArrayDataProvider([
'allModels' => $items,
'sort' => [
'attributes' => $searchAttributes,
],
]),
'filterModel' => $searchModel,
'columns' => array_merge(
$searchColumns, [
['class' => 'yii\grid\ActionColumn']
]
)
]);
here are some improvements for the filtering function
function ($item) {
$mailfilter = strtolower(Yii::$app->request->getQueryParam('filteremail', ''));
if (strlen($mailfilter) > 0) {
return strpos(strtolower($item['email']), $mailfilter) !== false;
} else {
return true;
}
}
Use strtolower() in both places($item['email']) & mailfilter) function if you want your filter to be not case sensitive
Check also type for strpos() ("!== false" instead of "!= false") function, otherwise, it will not work while trying to filter for the first characters of the string
A dataprovider :
if ($this->load($params)) {
$name = strtolower(trim($this->name));
$resultData= array_filter($resultData, function ($role) use ($name){
return (empty($name) || strpos((strtolower(is_object($role) ? $role->name : $role['name'])),$name) !== false);
});
}
$dataProvider = new ArrayDataProvider([
'key'=>'id',
'allModels' => $resultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
https://getyii.com/topic/736

CakePHP 3.0 Can't save hasMany associated data

I've problem when saving data with hasMany association
This is my table
1) post table: each item has an unique id.
id | title | ...
1 | Aloha | ...
2) images table
id | post_id | image | ...
1 | 1 | abc.jpg | ...
2 | 1 | efg.jpg | ...
My Model (Table)
Posts Model
// PostsTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class PostsTable extends Table {
public function initialize(array $config) {
$this->table('posts');
$this->displayField('title');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->hasMany('Images', [
'foreignKey' => 'id'
]);
}
}
...
Images Model
// ImagesTable.php
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class ImagesTable extends Table {
public function initialize(array $config) {
$this->table('images');
$this->displayField('id');
$this->primaryKey('id');
$this->addBehavior('Timestamp');
$this->belongsTo('Posts');
}
}
...
My Controller
// PostsController.php
...
public function add() {
$post = $this->Posts->newEntity($this->request->data, [
'associated' => ['Images']
]);
if ($this->request->is('post')) {
if ($this->Posts->save($post, ['associated' => ['Images']])) {
$this->Flash->success('The post has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The post could not be saved. Please, try again.');
}
}
$this->set('post', $post);
}
...
My Template
// add.ctp
<?= $this->Form->create($post); ?>
<?php echo $this->Form->input('title'); ?>
<?php echo $this->Form->input('images.0.image'); ?>
<?php echo $this->Form->input('images.1.image'); ?>
<?php echo $this->Form->input('images.2.image'); ?>
<?= $this->Form->button(__('Submit'), ['class' => 'button-green']) ?>
<?= $this->Form->end() ?>
Input array result Debug
[
'title' => 'Hello',
'images' => [
(int) 0 => [
'image' => 'testa.jpeg'
],
(int) 1 => [
'image' => 'testb.jpeg'
],
(int) 2 => [
'image' => 'testc.jpeg'
]
]
]
(Update)
debug($post)
object(App\Model\Entity\Story) {
'new' => true,
'accessible' => [
'title' => true,
'images' => true
],
'properties' => [
'title' => 'Hello',
'images' => [
(int) 0 => object(App\Model\Entity\Image) {
'new' => true,
'accessible' => [
'post_id' => true,
'image' => true,
'post' => true
],
'properties' => [
'image' => 'testa.jpeg'
],
'dirty' => [
'image' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Images'
},
(int) 1 => object(App\Model\Entity\Image) {
'new' => true,
'accessible' => [
'post_id' => true,
'image' => true,
'post' => true
],
'properties' => [
'image' => 'testb.jpeg'
],
'dirty' => [
'image' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Images'
},
(int) 2 => object(App\Model\Entity\Image) {
'new' => true,
'accessible' => [
'post_id' => true,
'image' => true,
'post' => true
],
'properties' => [
'image' => 'testc.jpeg'
],
'dirty' => [
'image' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Images'
}
]
],
'dirty' => [
'title' => true,
'images' => true
],
'original' => [],
'virtual' => [],
'errors' => [],
'repository' => 'Stories'
}
I can't figure out what I am doing wrong
Thanks
I haven't looked everything, but I saw there is an error in your association declaration:
$this->hasMany('Images', [
'foreignKey' => 'id'
]);
The docs say:
foreignKey: the name of the foreign key found in the other model. This is especially handy if you need to define multiple hasMany relationships. The default value for this key is the underscored, singular name of the actual model, suffixed with ‘_id’.
So it should be:
$this->hasMany('Images', [
'foreignKey' => 'post_id'
]);
or even:
$this->hasMany('Images');
I've just finished my 3-hour tour with saving hasMany content along with the main model. This struggle seems to be even worse, if considered saving many main model's objects with many associated items.
Foreign key in hasMany relationship is the singular name of the current model (entity) with _id suffix, so it's like:
class MainModel extends Table {
...
public function initialize(array $config) {
...
// remember the "s" at the end of the name
$this->hasMany('VeryWeirdCalleds', [
'className' => 'VeryWeirdCalleds',
'foreignKey' => 'main_model_id',
'propertyName' => 'very_weird_calleds'
]);
...
}
...
}
Then, you set the accessible in the MAIN Entity, so that the MAIN model can save the association based on "very_weird_calleds" index:
class MainModel extends Entity {
protected $_accessible = [
...
'very_weird_calleds' => true,
];
}
And the last (but not least): the Controller save. It's usually the hardest part to overcome, due to the fact, that docs do not clarify the whole process in detail:
class MainModelsController extends AppController {
public function add($data) {
$data = [
[
'name' => 'Hello',
'body' => 'Bla bla',
'very_weird_calleds' => [
[
'name' => 'Very Weird Called'
]
]
]
];
foreach ($data as $record) {
$main = $this->MainModels->newEntity($record);
if(isset($record['images']) && !empty($record['images'])) {
foreach($record['images'] as $record_image) {
$image = $this->MainModels->VeryWeirdCalleds->newEntity();
$image->IMAGE = $record_image['IMAGE'];
$import->very_weird_calleds[] = $image;
}
}
if (!$this->MainModels->save($main)) {
$this->Flash->error('The main model could not be saved. Please, try again.');
}
}
}
Explanation? First of all, we loop through the data, previously prepared as follows:
[ 'main', 'model', 'data', 'association_accessible_property' => [ 'associated_data' ] ] ]
Then we create new entries for associated data, using the same method as for the main model. The last thing, is to add those associated Entities to the main model Entity.
Pay an extreme attention to the names given in this example. The 's'-es and CamelCases are not coincidental.
try this :
<?php echo $this->Form->input('0.Images.image'); ?>
<?php echo $this->Form->input('1.images.image'); ?>
<?php echo $this->Form->input('2.images.image'); ?>
with int before , according with http://book.cakephp.org/3.0/en/views/helpers/form.html#field-naming-conventions

Resources