Yii2: How to access a table column via a relation - yii2

I have two tables, dpd and cabang. One cabang can only have one dpd and each cabang should have a dpd.
This is the relation in my "Cabang" model :
public function getIdDpd()
{
return $this->hasOne(Dpd::className(), ['id_dpd' => 'id_dpd']);
}
I try to access "dpd" attribute in "dpd" table in my view, I tried to var_dump it but still got the same error :
$model = Cabang::find()
->joinWith('idDpd')
->all();
var_dump($model->dpd);
Note : 'dpd' in var_dump($model->dpd) refered to the column name in 'Dpd' table. I have a column name 'dpd' in my 'dpd' table. I also tried $model->idDpd->dpd but it return the same error.
What am I doing wrong? Thanks

Your mistake is
$model->dpd
where you are trying to access it assuming that $model has the Dpd object, but it is holding the Cabang object and you should use the relation name to get the Dpd object and then call the field name like below.
$model->idDpd->dpd
EDIT: You are using ->all() in your query not ->one() and hence you cannot simply do $model->idDpd->dpd right after the query, you need to loop through the records and then call the relation, i thought you might be doing the same way but anyway see below how to use it.
$cabangs = Cabang::find()
->joinWith('idDpd')
->all();
foreach($cabangs as $index=>$model){
$model->idDpd->dpd;
}

Related

How can I have the name of my entity instead of the id in the related tables

I'm creating a project on CakePHP 3.x where I'm quite new. I'm having trouble with the hasMany related tables to get the name of my entities instead of their ids.
I'm coming from CakePHP 2.x where I used an App::import('controller', array('Users') but in the view to retrieve all data to display instead of the ids, which is said to be a bad practice. And I wouldn't like to have any code violation in my new code. Can anybody help me? here is the code :
public function view($id = null)
{
$this->loadModel('Users');
$relatedUser = $this->Users->find()
->select(['Users.id', 'Users.email'])
->where(['Users.id'=>$id]);
$program = $this->Programs->get($id, [
'contain' => ['Users', 'ProgramSteps', 'Workshops']
]);
$this->set(compact('program', 'users'));
$this->set('_serialize', ['ast', 'relatedUser']);
}
I expect to get the user's email in the relatedUsers of the program table but the actual output is:
Notice (8): Trying to get property 'user_email' of non-object [APP/Template\Asts\view.ctp, line 601].
Really need help
Thank you in advance.
You've asked it to serialize the relatedUser variable, but that's for JSON and XML views. You haven't actually set the relatedUser variable for the view:
$this->set(compact('program', 'users', 'relatedUser'));
Also, you're setting the $users variable here, but it's never been initialized.
In addition to #Greg's answers, the variable $relateduser is still a query object, meaning that trying to access the email property will fail. The query still needs to be executed first.
You can change the query to:
$relatedUser = $this->Users->find()
->select(['Users.id', 'Users.email'])
->where(['Users.id' => $id])
->first();
Now the query is executed and the only the first entry is returned.
There is are a number of ways to get a query to execute, a lot of them are implicit is use. See:
Cookbook > Retrieving Data & Results Sets

Yii 2 Active Query joinWith issue

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.

laravel5-How can i hide the specific column of withPivot?

I use belongstomany function to get the models and used withPivot() to get an extra column data in the pivot table. However, the withPivot() function will add the 2 foreign keys in the output json. I want to hide thses keys and only show the column I want to display.
The follwing is my response data
{"status_code":"1","next_page":"2","dataset":[{"id":"829","req_start_time":"2016-03-13 14:55:00","req_end_time":"2016-03-13 09:55:00","content":[{"name":"\u9752\u6912\u7092\u725b\u8089","price":"120","pic_url":"","detail":"\u8d85\u7ea7\u597d\u5403\u7684\u54df","pivot":{"waiter_request_id":"829","goods_id":"2","count":"2"}}
as you see the pivot json object contains two id keys.
how could i remove them from the object? or some other ways to solve this get the right way of this need?
thx in advance!
Now the question already upgraded!
How can I add this 'count' parameter of pivot in the object which belongs to 'content'
Finally,I figured out the right way to solve this problem. Follwing the code:
class Goods extends Model{
......
......
public function newPivot(Model $parent, array $attributes, $table, $exists)
{
$pivot = new Pivot($parent, $attributes, $table, $exists);
$pivot->addHidden(
array(
'waiter_request_id',
'goods_id'
)
);
return $pivot;
}
}
you can rewrite this method to provide a new pivot object to the Model in your 'belongsToMany'

CakePhp mysql raw query error

I'm new to cakephp. I'm trying to search through mysql tables. I want to use nested query.
class TableController extends AppController{
.
.
public function show(){
$this->set('discouns', $this->DiscounsController->query("SELECT * FROM discoun as Discoun WHERE gcil_id = 1"));//(SELECT id FROM gcils WHERE genre = 'Shoes' AND company_name = 'Adidas')"));
}
}
Error:
Error: Call to a member function query() on a non-object
I've also tried
public function show(){
$this->DiscounsController->query("SELECT * FROM count as Count WHERE ctr_id = (SELECT id FROM ctrs WHERE genre = 'Shoes' AND company_name = 'Adidas')");
}
Error:
Error: Call to a member function query() on a non-object
File: C:\xampp\htdocs\cakephppro\myapp\Controller\CountsController.php
Please help. I've been trying this for last few hours. :/
As mentioned in the comments there are a few problems with your code.
Firstly, you are trying to call the query() method on a Controller, whereas you should be executing it on a Model, as it is models that handle database queries and the controller should simply be used to call these methods to get the data and pass them to the view.
The second thing is that you are executing a very simple SQL query raw instead of using CakePHPs built in functions <- Be sure to read this page in full.
Now for your problem, as long as you have setup your model relationships correctly and followed the correct naming conventions, this should be your code to run your SQL query from that controller:
public function show(){
$this->set('discouns', $this->Discouns->find('all', array(
'conditions' => array(
'gcil_id' => 1,
'genre' => 'shoes',
'company_name' => 'Adidas'
)
));
}
query() is not a Controller, but a Model method. That's what the error (Call to a member function on a non-object) is trying to tell you.
So the correct call would be:
$this->Discount->query()
But you are calling this in a TableController, so unless Table and Discount have some type of relationship, you won't be able to call query().
If the Table does have a relationship defined you will be able to call:
$this->Table->Discount->query()
Please not that query() is only used when performing complex SQL queries in scenarios where the standard methods (find, save, delete, etc.) are less practical.
$this->Counts->find('all',array(
'conditions' => array(
'ctrs.genre' => 'Shoes',
'ctrs.company_name' => 'Adidas'
), 'recursive' => 1
));
The above is with tables named counts and ctrs.
This is assuming you have the model set up to have some sort of relationship between the counts table and the ctrs table. It's kind of hard to tell in your code exactly what you tables are.
The CakePHP book should have all the answers you need. One of the reasons to run CakePHP over regular PHP is the FIND statement. Once you have your models set up correctly, using the find statement should be really easy.
http://book.cakephp.org/2.0/en/models.html

Magento JoinLeft() in custom orders grid causing SQL integrity constrain violation for non-admin user in multi-website setup

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!