The sections are related to the level and degree. So I need to show on the field select level, grade and section.
Reading the cakephp 3 book found that using "valueField" I can show the field I want. But this time I need to show two fields.
In my controller:
$secciones = $this->Users->Secciones->find('list', [
'keyField' => 'id',
'valueField' => ['nivele.nivel']
])->contain(['Niveles', 'Grados']);
When I put in the valueField ['nivele.nivel','grado.grado'] only show a semicolon.
How can display two relationship in the select field?
Thanks.
I readed the solution in
How do I create a keyValue pair by combining/having two fields in CakePHP 3?
but in that case no relation. In my case i need to use two fields with
relation.
Reading the solution in
How do I create a keyValue pair by combining/having two fields in CakePHP 3?
I did this:
$secciones = $this->User->Secciones
->find()
->select(['id', 'nivele_id', 'grado_id'])
->formatResults(function($results) {
/* #var $results \Cake\Datasource\ResultSetInterface|\Cake\Collection\CollectionInterface */
return $results->combine(
'id',
function($row) {
return $row['nivele.nivel'] . ' ' . $row['grado.grado'];
}
);
})
->contain(['Niveles', 'Grados']);
But I have a fatal error :-(
Related
I'm using Laravel and I'm trying to return this on API:
{
id: 1
name: BOM DIA
},
id: 2
name: BOM DIA (SUPERM VANEZA, BATISTA & IZEPE, BOM DIA)
}
But I'm confused. I have a table named 'Teams', and at this table, some columns have a number 'biid'. This 'biid' is the same information from another table name 'Clients'.
More than one 'Clients' can have same 'biid', but 'Teams' only have unique 'biid' or don't have any 'biid'.
I wanna to concat 'Teams' who has 'biid' with column named 'slug' in table 'Clients'.
Tables:
This should be like this:
How can I even think in make this?
Hello you need relations to do it if i know your problem
so let's talk about relation in your case Teams as many clients
the relation in your model teams will be this:
public function client(){
return $this->belongsToMany(Client::class);
}
What laravel does with belongsToMany method ?
for each client who as the same id's who you references teams and laravel will add it to you Eloquent Object.
Your client has one teams
soin your client model if you named it client :
public function team(){
return $this->belongsTo(Model::class);
}
to get the detail of relation who you need :
you will need to make the relations request, this will contribute to remove n +1 problem:
$clients = Client::with(['team']);
$teams = Team::with(['client']);
// here i don't know if you need ->get() try without and with
To access the relations:
foreach($clients as $client){
echo $client->team->name;
}
foreach($teams->client as $team){
echo $team->name;
}
// or
foreach($teams as $team){
echo $team->client->name;
}
But i think for that you need to rename you column because that are not explicit for laravel
to access relations you column need to have client_id and team_id to work.
Already received a great answer at this post
Laravel Query using GroupBy with distinct traits
But how can I modify it to include more than just one field. The example uses pluck which can only grab one field.
I have tried to do something like this to add multiple fields to the view as such...
$hats = $hatData->groupBy('style')
->map(function ($item){
return ['colors' => $item->color, 'price' => $item->price,'itemNumber'=>$item->itemNumber];
});
In my initial query for "hatData" I can see the fields are all there but yet I get an error saying that 'colors', (etc.) is not available on this collection instance. I can see the collection looks different than what is obtained from pluck, so it looks like when I need more fields and cant use pluck I have to format the map differently but cant see how. Can anyone explain how I can request multiple fields as well as output them on the view rather than just one field as in the original question? Thanks!
When you use groupBy() of Laravel Illuminate\Support\Collection it gives you a deeper nested arrays/objects, so that you need to do more than one map on the result in order to unveil the real models (or arrays).
I will demo this with an example of a nested collection:
$collect = collect([
collect([
'name' => 'abc',
'age' => 1
]),collect([
'name' => 'cde',
'age' => 5
]),collect([
'name' => 'abcde',
'age' => 2
]),collect([
'name' => 'cde',
'age' => 7
]),
]);
$group = $collect->groupBy('name')->values();
$result = $group->map(function($items, $key){
// here we have uncovered the first level of the group
// $key is the group names which is the key to each group
return $items->map(function ($item){
//This second level opens EACH group (or array) in my case:
return $item['age'];
});
});
The summary is that, you need another loop map(), each() over the main grouped collection.
I have a Active Record model "Event" with a hasOne relation 'getUser'.
Now, if I do :
$eventModels = Event::find()->joinWith([
'user' => function($q){
return $q;
}])->all();
----------------------------------------------------
foreach($eventModels as $m){
var_dump($m->user); //Everything good as $m->user returns the related user object
die('skdw');
}
But, if I add the "select" in the joinWith query, then related "user" object becomes null. Here is the issue :
$eventModels = Event::find()->joinWith([
'user' => function($q){
$q->select('email');// or, ['email'] or ['user.email'] etc. fields.
return $q;
}])->all();
----------------------------------------------------
foreach($eventModels as $m){
var_dump($m->user); // Returns NULL
die('skdw');
}
But, if I make it $q->select('*'), then $m->user working .
I believe it used to work in some previous versions of Yii 2 (Right now, I am working on Yii 2.0.9)
Is this expected behavior ? If yes, then what is the solution to fetch only some select fields for the related joinWith model ? I don't want to fetch all the related fields as some of the related fields might contain "TEXT" data type.
You need to select the primary key column for the relation for Yii to build them.
e.g. assuming your column is called id
$eventModels = Event::find()->joinWith(['user' => function($q){
$q->select(['id', 'email']);
}])->all();
Also, you don't need to return the $q variable.
I am using Laravel 4.2 and mysql db . I have an exam table in which i am taking Exams entry and the fields are --> id | examdate | batch | chapter | totalmarks
I have made a combined unique key using $table->unique( array('examdate','batch','chapter') ); in schema builder.Now I want to add a validation rule to it. I know i can add unique validation by laravel unique validator rule but the problem is ,it checks only for one field . I want it to add uniqueness to the 3 fields combined(user must not be able to add second row with same value combination of examdate,batch and chapter fields).
Is it even possible to do it in laravel 4 .Is there any workaround if its not possible?
You could write a custom validator rule. The rule could look something like this:
'unique_multiple:table,field1,field2,field3,...,fieldN'
The code for that would look something like this:
Validator::extend('unique_multiple', function ($attribute, $value, $parameters)
{
// Get table name from first parameter
$table = array_shift($parameters);
// Build the query
$query = DB::table($table);
// Add the field conditions
foreach ($parameters as $i => $field)
$query->where($field, $value[$i]);
// Validation result will be false if any rows match the combination
return ($query->count() == 0);
});
You can use as many fields as you like for the condition, just make sure the value passed is an array containing the values of the fields in the same order as declared in the validation rule. So your validator code would look something like this:
$validator = Validator::make(
// Validator data goes here
array(
'unique_fields' => array('examdate_value', 'batch_value', 'chapter_value')
),
// Validator rules go here
array(
'unique_fields' => 'unique_multiple:exams,examdate,batch,chapter'
)
);
It didn't work for me so I adjusted the code a tiny bit.
Validator::extend('unique_multiple', function ($attribute, $value, $parameters, $validator)
{
// Get the other fields
$fields = $validator->getData();
// Get table name from first parameter
$table = array_shift($parameters);
// Build the query
$query = DB::table($table);
// Add the field conditions
foreach ($parameters as $i => $field) {
$query->where($field, $fields[$field]);
}
// Validation result will be false if any rows match the combination
return ($query->count() == 0);
});
The validator looks like this. You don't need a particular order of DB table column names as stated in the other answer.
$validator = Validator::make($request->all(), [
'attributeName' => 'unique_multiple:tableName,field[1],field[2],....,field[n]'
],[
'unique_multiple' => 'This combination already exists.'
]);
I have extended the Mage_Adminhtml_Block_Sales_Order_Grid class with a custom module to add several customer attributes (Magento EE 1.10) to the grid.
I added the custom attributes to the collection in my MyCompany_MyModule_Block_Adminhtml_Order_Grid class in the _prepareCollection() method using three joins like this:
protected function _prepareCollection()
{
$collection = Mage::getResourceModel($this->_getCollectionClass());
//get the table names for the customer attributes we'll need
$customerEntityVarchar = Mage::getSingleton('core/resource')
->getTableName('customer_entity_varchar');
$customerEntityInt = Mage::getSingleton('core/resource')
->getTableName('customer_entity_int');
// add left joins to display the necessary customer attribute values
$collection->getSelect()->joinLeft(array(
'customer_entity_int_table'=>$customerEntityInt),
'`main_table`.`customer_id`=`customer_entity_int_table`.`entity_id`
AND `customer_entity_int_table`.`attribute_id`=148',
array('bureau'=>'value'));
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_table`.`entity_id`
AND `customer_entity_varchar_table`.`attribute_id`=149',
array('index_code'=>'value'));
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_2_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_2_table`.`entity_id`
AND `customer_entity_varchar_2_table`.`attribute_id`=150',
array('did_number'=>'value'));
$this->setCollection($collection);
return parent::_prepareCollection();
}
UPDATE: While everything displays fine when viewing orders, things are not fine when I try to search / filter orders by any of the text join fields (index_code or did_number). The result is a SQL error: "SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'store_id' in where clause is ambiguous."
This problem also exists if I remove all but one of the leftJoin() statements, so something is going wrong with both (either) of the joins with the customer_entity_varchar table.
As now there are two columns with the name store_id, you have to specify filter_index when you add the column to the grid:
$this->addColumn('store_id', array(
...
'filter_index'=>'main_table.store_id',
));
So that it knows which one you are referring while filtering.
I hope it helps!
More than likely it is because you are joining customer_entity_varchar_table twice.
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_table`.`entity_id`
AND `customer_entity_varchar_table`.`attribute_id`=149',
array('index_code'=>'value'));
$collection->getSelect()->joinLeft(array(
'customer_entity_varchar_2_table'=>$customerEntityVarchar),
'`main_table`.`customer_id`=`customer_entity_varchar_2_table`.`entity_id`
AND `customer_entity_varchar_2_table`.`attribute_id`=150',
array('did_number'=>'value'));
You may want to combine those, you can also try and print the SQL to see what the Query looks like:
$collection->getSelect()->getSelectSql();
More info on collections: http://blog.chapagain.com.np/magento-collection-functions/
The problem appears to exist in two different places. One case is if logged in as a user with a single store, the other as a user who can filter various stores.
Single store user
The solution I went with was to override the addAttributeToFilter method on the collection class. Not knowing exactly what changing the Enterprise_AdminGws_Model_Collections::addStoreAttributeToFilter method would affect other behavior I wanted to avoid that, and I found adding a filter index in Mage_Adminhtml_Block_Sales_Order_Grid as Javier suggested did not work.
Instead I added the following method to Mage_Sales_Model_Resource_Order_Grid_Collection:
/**
* {#inheritdoc}
*/
public function addAttributeToFilter($attribute, $condition = null)
{
if (is_string($attribute) && 'store_id' == $attribute) {
$attribute = 'main_table.' . $attribute;
}
return parent::addFieldToFilter($attribute, $condition);
}
A patch can be found here: https://gist.github.com/josephdpurcell/baf93992ff2d941d02c946aeccd48853
Multi-store user
If a user can filter orders by store at admin/sales_order, the following change is also needed to Mage_Adminhtml_Block_Sales_Order_Grid around line 75:
if (!Mage::app()->isSingleStoreMode()) {
$this->addColumn('store_id', array(
'header' => Mage::helper('sales')->__('Purchased From (Store)'),
'index' => 'store_id',
'type' => 'store',
'store_view'=> true,
'display_deleted' => true,
'filter_index' => 'main_table.store_id',
));
}
A patch can be found here: https://gist.github.com/josephdpurcell/c96286a7c4d2f5d1fe92fb36ee5d0d5a
I had the same bug, after grepping the code, I finally found the troublemaker which is in the Enterprise_AdminGws_Model_Collections class at line ~235:
/**
* Add store_id attribute to filter of EAV-collection
*
* #param Mage_Eav_Model_Entity_Collection_Abstract $collection
*/
public function addStoreAttributeToFilter($collection)
{
$collection->addAttributeToFilter('store_id', array('in' => $this->_role->getStoreIds()));
}
You have to replace 'store_id' by 'main_table.store_id', of course you'll have to extend that particular method in your own rewrite to stick into Magento guidelines :p
Hope it helps!