CakePHP 2.x retriving data with i18n in a loop - loops

I'm looping trough Features (belongTo FeatureType) and find() FeatureType.name for each Feature.feature_type_id.
I'm getting first record correct (with i18n translation) but in all the rest the i18n translation is not in place, but given as separate record.
What I am doing wrong?
this is the debug of my result table:
array(
'FeatureType' => array(
'id' => '28',
'name' => 'kolor suwaka',
'comment' => 'kolor suwaka etui notebook',
'locale' => 'pol'
)
)
array(
'FeatureType' => array(
'id' => '7',
'name' => '',
'comment' => '',
'locale' => 'pol'
),
(int) 0 => array(
'FeatureType__i18n_name' => 'kolor materiału',
'FeatureType__i18n_comment' => 'gra w klasy'
)
)
array(
'FeatureType' => array(
'id' => '11',
'name' => '',
'comment' => '',
'locale' => 'pol'
),
(int) 0 => array(
'FeatureType__i18n_name' => 'kolor',
'FeatureType__i18n_comment' => 'kółko i krzyżyk (jasnoszare i ciemnoszare)'
)
)
array(
'FeatureType' => array(
'id' => '27',
'name' => '',
'comment' => '',
'locale' => 'pol'
),
(int) 0 => array(
'FeatureType__i18n_name' => 'obwód głowy',
'FeatureType__i18n_comment' => 'rozmiar kapelusza czarownicy'
)
)
This is the code:
$features_str = "";
if (!empty($product['Features'])) {
foreach ($product['Features'] as $featureIndex => $feature) {
$featureTypeModel = new FeatureType();
$feature_type = $featureTypeModel->find("first", array("conditions" => array("FeatureType.id" => $feature['feature_type_id'])));
if (strlen($features_str) > 0) $features_str .= ", ";
$features_str .= $feature_type['FeatureType']['name'] . ': ' . $feature['name'];
unset($featureTypeModel);
}
}

Related

How to get rid of null associated model in cakephp 2.x

I am trying to get the item types that Order.Item.ItemType.show_type = 1. I have written the query but I want to show only Items that their ItemType.show_type = 1 not all items.
$brief = $this->Order->find('first', array(
'fields' => array(
'Order.*'
),
'conditions' => array(
'Order.order_id' => $orderId,
),
'contain' => array(
'Item' => array(
'fields' => array(
'Item.*', 'CHAR(64 + Item.num) AS letter'
),
'conditions' => array(
'Item.deleted' => 0,
),
'ItemType' => array(
'conditions' => array(
'ItemType.show_type' => 1
),
)
),
)
));
The query shouldn't show Item id = 25741
Associations:
// Order
public $hasMany = array(
'BriefInstalment' => array(
'foreignKey' => 'order_id'
)
);
// Item Model
public $belongsTo = array(
'Order',
'ItemType' => array(
'type' => 'inner'
)
);
// ItemType Model
public $hasMany = array('Item');
Print:
array(
'Order' => array(
'order_id' => '67817',
'service' => '',
),
'Item' => array(
(int) 0 => array(
'id' => '25741',
'order_id' => '67817',
'num' => '2',
'item_type_id' => '8',
'name' => '3-5 titles active',
'deleted' => false,
'ItemType' => array(), // <= how to remove this empty model
'Item' => array(
(int) 0 => array(
'letter' => 'B'
)
)
),
(int) 1 => array(
'id' => '25742',
'order_id' => '67817',
'num' => '3',
'item_type_id' => '2',
'name' => '1,000 pro active',
'deleted' => false,
'ItemType' => array(
'id' => '2',
'name' => 'Part Instalment',
'show_type' => true,
'deleted' => false
),
'Item' => array(
(int) 0 => array(
'letter' => 'C'
)
)
)
)
)
This could not be done using Countaible behaviour, but iwth the joins method, set the recursive to -1
$brief = $this->Order->find('first', array(
'recursive' => -1,
'fields' => array(
'Order.*'
),
'conditions' => array(
'Order.order_id' => $orderId,
),
'joins' => array(
array(
'table' => 'items',
'alias' => 'Item',
'type' => 'inner',
'conditions' => array(
'Order.id = Item.order_id'
)
),
array(
'table' => 'item_types',
'alias' => 'ItemType',
'type' => 'inner',
'conditions' => array(
'ItemType.id = Item.item_type_id'
)
),
)
));
You have to check if the table names are correct and also the foreign keys names.
Another solution would be to go through your results, and unset the empty ones
foreach($brief as $k => $v){
foreach($v['Item'] as $kk => $vv){
if(empty($vv['ItemType'])){
unset($brief[$k]['Item'][$kk];
}
}
}
debug($brief);

CakePHP joing two tables

I have a problem in viewing my data ,I need to return a year,ex(2010,2011,2012,2013) instead of returning the year id , I used contain but It did not work , what is the right way to displaying data ?!
Here is the output array:array(
(int) 0 => array(
'IndicatorDatum' => array(
'id' => '188',
'indicator_id' => '2',
'report_year_id' => '2',
'value' => '144063181',
'comment' => '0',
'reference' => '0'
)
),
(int) 1 => array(
'IndicatorDatum' => array(
'id' => '163',
'indicator_id' => '2',
'report_year_id' => '3',
'value' => '178104575',
'comment' => '0',
'reference' => '0'
)
),
(int) 2 => array(
'IndicatorDatum' => array(
'id' => '137',
'indicator_id' => '2',
'report_year_id' => '4',
'value' => '198637602',
'comment' => '0',
'reference' => '0'
)
),
(int) 3 => array(
'IndicatorDatum' => array(
'id' => '5752',
'indicator_id' => '2',
'report_year_id' => '5',
'value' => '1234',
'comment' => null,
'reference' => null
)
),
(int) 4 => array(
'IndicatorDatum' => array(
'id' => '5694',
'indicator_id' => '2',
'report_year_id' => '6',
'value' => '100',
'comment' => '0',
'reference' => '0'
)
),
(int) 5 => array(
'IndicatorDatum' => array(
'id' => '5271',
'indicator_id' => '2',
'report_year_id' => '6',
'value' => '1',
'comment' => '0',
'reference' => '0'
)
)
)
Model
public $belongsTo = array(
'Indicator' => array(
'className' => 'Indicator',
'foreignKey' => 'indicator_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'ReportYear' => array(
'className' => 'ReportYear',
'foreignKey' => 'report_year_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Organisation' => array(
'className' => 'Organisation',
'foreignKey' => 'organisation_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
);
$this->find('all',array(
'fields' => array('IndicatorDatum.id','IndicatorDatum.indicator_id','IndicatorDatum.report_year_id','IndicatorDatum.value','IndicatorDatum.comment','IndicatorDatum.reference'
),'contain' => array(
'ReportYears'),
'conditions'=>array('IndicatorDatum.indicator_id' =>'2' , 'IndicatorDatum.organisation_id'=>$organisation_id),
'order' => array('IndicatorDatum.report_year_id')
));
You just need to specify the exact fields for each model(including associated models), otherwise only the id is being returned (and it is good, because if it would be all the fields, what if you have some text column in the db with KBs of data - you do not want to retrieve it)
also, please pay attention, that by default(and by cake conventions) model names are singular, so, inside contain it should be ReportYear and not ReportYears.
here is the final query.
$this->find('all', array(
'fields' => array(
'IndicatorDatum.id',
'IndicatorDatum.indicator_id',
'IndicatorDatum.report_year_id',
'IndicatorDatum.value',
'IndicatorDatum.comment',
'IndicatorDatum.reference'
),
'contain' => array(
'ReportYear' => array(
'fields' => array(
'ReportYear.id',
'ReportYear.year' // not sure what you have as a year field name
)
)
),
'conditions' => array(
'IndicatorDatum.indicator_id' => '2',
'IndicatorDatum.organisation_id' => $organisation_id
),
'order' => array(
'IndicatorDatum.report_year_id'
)
)
);

cakephp deep conditions from controller

I am trying to get records from CoursesEmployee model within my BusinessesController. They are not linked directly which is my problem.
Each Business has Employees which can enrol in courses.
BusinessesController.php:
$options = array(
'conditions' => array('Business.' . $this->Business->primaryKey => 1)
);
$test = $this->Business->find('all', $options);
debug($test);
The output:
array(
(int) 0 => array(
'Business' => array(
'id' => '1',
'name' => 'Test Business',
),
'Employee' => array(
(int) 0 => array(
'id' => '1',
'business_id' => '1',
'name' => 'Keith Power',
'Business' => array(
'id' => '1',
'name' => 'Test Business',
),
'Course' => array(
(int) 0 => array(
'id' => '1',
'name' => 'Manual Handling',
'CoursesEmployee' => array(
'id' => '1',
'employee_id' => '1',
'course_id' => '1',
'course_module_id' => '1',
'completed' => true
)
),
(int) 1 => array(
'id' => '3',
'name' => 'Induction',
'CoursesEmployee' => array(
'id' => '2',
'employee_id' => '1',
'course_id' => '3',
'course_module_id' => '0',
'completed' => false
)
)
)
)
)
)
)
I wish to get the list of CoursesEmployee where CoursesEmployee.completed = true and Business.id = 1
Model Associations:
Business $hasMany Employee
Employee $belongsTo Business
Employee $hasAndBelongsToMany Course
public $hasAndBelongsToMany = array(
'Course' => array(
'className' => 'Course',
'joinTable' => 'courses_employees',
'foreignKey' => 'employee_id',
'associationForeignKey' => 'course_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
)
);
CoursesEmployee
public $belongsTo = array(
'Employee' => array(
'className' => 'Employee',
'foreignKey' => 'employee_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Course' => array(
'className' => 'Course',
'foreignKey' => 'course_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
cakephp 2.5
I suggest this way, if it doesn't work we'll try join way :
updated :
$coursesEmployes = $this->Business->Employee->CoursesEmployee->find('all',array(
'conditions'=>array('CoursesEmployee.completed '=> 'true' ,'Employee.business_id' => '1' ),
'recursive'=>3)
);
Hope it helps !

Searching data from associated models in CakePHP

I am using CakePHP 2.3.6. In my project, I have to search users using some values/data/parameter, which are in several tables, and the tables are associated.
The associations are :
in the model User.php :
public $hasMany=array('Education'=>array(
'className'=>'Education
'foreignKey'=>'user_id'
),
'Experience'=>array(
'className'=>'Experience',
'foreignKey'=>'user_id'
),
'Employment'=>array(
'className'=>'Employment',
'foreignKey'=>'user_id'
),
'ProfessionalQualification'=>array(
'className'=>'ProfessionalQualification',
'foreignKey'=>'user_id'
)
)
in the model Education.php :
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
in the model Experience.php :
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
in the model Employment.php :
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
in the model ProfessionalQualification.php :
public $belongsTo=array('User'=>array(
'className'=>'User',
'foreignKey'=>'user_id'
)
)
Now, in the Search form (View/Users/search.ctp) :
echo $this->Form->create('User');
echo $this->Form->input('name',array('type'=>'text'));
echo $this->Form->input('username',array('type'=>'text'));
echo $this->Form->input('address',array('type'=>'textarea'));
echo $this->Form->input('phone',array('type'=>'tel'));
echo $this->Form->input('degree',array('type'=>'text'));
echo $this->Form->input('passing_year',array('type'=>'text'));
echo $this->Form->input('title',array('type'=>'text'));
echo $this->Form->input('title.description',array('type'=>'textarea'));
echo $this->Form->input('company',array('type'=>'text'));
echo $this->Form->input('company.description',array('type'=>'textarea'));
echo $this->Form->input('certificate',array('type'=>'text'));
echo $this->Form->input('certificate.description',array('type'=>'textarea'));
echo $this->Form->submit('Search');
echo $this->Form->end();
in the UsersController.php controller :
public function search(){
$this->set('title_for_layout','Search User');
if($this->request->is('post')){
$conditions=array();
$data=$this->request->data;
if(!empty($data['name']))
$conditions['name']="%".$data['name']."%";
if(!empty($data['username']))
$conditions['username']=$data['username'];
if(!empty($data['address']))
$conditions['address']='%'.$data['address'].'%';
if(!empty($data['phone']))
$conditions['phone']=$data['phone'];
if(!empty($data['degree']))
$conditions['degree']="%".$data['degree']."%";
.
.
.
if(!empty($data)){
$users=$this->User->find('all',array('conditions'=>$conditions));
if(!empty($users)){
$this->Session->setFlash("Searching Users Successful");
$this->set('users',$users);
}else
$this->Session->setFlash("No user found");
}else
$this->Session->setFlash("You didn't give any info to search for");
}
}
I thought it'd retrieve all data I am looking for, from all the associated tables, in an array. But, it gives an error :
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'degree' in 'where clause'
SQL Query: SELECT `User`.`id`, `User`.`name`, `User`.`username`, `User`.`phone`, `User`.`address`, `User`.`created`, `User`.`modified` FROM `db_name`.`users` AS `User` WHERE `degree` = 'M.Sc.'
Here, "degree" is from the table "Education".
Then, I used ContainableBehavior. In the User.php model :
public $actsAs=array('Containable');
In the UsersController.php :
$this->User->find('all',array('contain'=>array('Education'=>array(
'conditions'=>array('Education.institution ='=>"Institute 1")
),
'Employment'=>array(
'conditions'=>array('Employment.employer ='=>"Employer 1")
),
'ProfessionalQualification'=>array(
'conditions'=>array('ProfessionalQualification.certificate ='=>"Certificate 1")
),
'Experience'=>array(
'conditions'=>array('Experience.title ='=>"Title 1")
)
)
)
);
When I use this, the result array is :
array(
(int) 0 => array(
'User' => array(
'name' => 'Name 3',
'email' => 'user3#email.com',
'mobile' => '9325028505',
'id' => '4'
),
'Education' => array(),
'Employment' => array(),
'ProfessionalQualification' => array(),
'Experience' => array()
),
(int) 1 => array(
'User' => array(
'name' => 'Name 2',
'email' => 'user2#email.com',
'mobile' => '9082730572',
'id' => '3'
),
'Education' => array(),
'Employment' => array(),
'ProfessionalQualification' => array(),
'Experience' => array()
),
(int) 2 => array(
'User' => array(
'name' => 'Name 1',
'email' => 'user1#email.com',
'mobile' => '715414918934',
'id' => '2'
),
'Education' => array(
(int) 0 => array(
'id' => '1',
'applicant_id' => '2',
'level' => 'Secondary',
'degree_title' => 'S.S.C',
'passing_year' => '2009',
'institution' => 'Institute 1',
'result' => '4',
'major' => 'Science',
'created' => '2014-05-18 16:48:08',
'modified' => '2014-05-18 17:20:12'
)
),
'Employment' => array(
(int) 0 => array(
'id' => '1',
'applicant_id' => '2',
'employer' => 'Employer 1',
'position_held' => 'Position 1',
'industry' => 'Industry 1',
'department' => 'Department 1',
'major_responsibilities' => 'Responsibilities 1',
'job_location' => 'Local',
'key_achievement' => 'Achievements 1',
'served_from' => '2005-03-12',
'served_till' => '2007-11-26',
'created' => '2014-05-18 16:48:08',
'modified' => '2014-05-18 17:20:12'
)
),
'ProfessionalQualification' => array(
(int) 0 => array(
'id' => '1',
'applicant_id' => '2',
'name_of_certificate' => 'Certificate 1',
'institute' => 'Institute 1',
'from' => '2011-10-11',
'to' => '2012-09-11',
'location' => 'Local Ins.',
'created' => '2014-05-18 16:48:08',
'modified' => '2014-05-18 17:20:12'
)
),
'Experience' => array(
(int) 0 => array(
'id' => '1',
'applicant_id' => '2',
'title' => 'Title 1',
'institute' => 'Institute 1',
'training_year' => '2013',
'location' => 'Local Ins.',
'created' => '2014-05-18 16:48:08',
'modified' => '2014-05-18 17:20:12'
)
)
),
(int) 3 => array(
'User' => array(
'name' => 'Name 4',
'email' => 'user4#email.com',
'mobile' => '9082730572',
'id' => '5'
),
'Education' => array(),
'Employment' => array(),
'ProfessionalQualification' => array(),
'Experience' => array()
)
)
Here, notice, that I only need the 2 no. array, nothing else, but it gives me all data that are not relevant.
Can you please tell me where is the problem ? What should I do ? I guess, I have to explicitly give the table names in the form, on the specific fields, like : ModelName.0.field. What do you think?
try this
public function global_search() {
$condition = array(
'User.role' => array('U', 'P'),
'User.user_status' => array('active', 'lead', 'inactive')
);
if ($this->request->is('post') || $this->request->is('put')) {
$or = array(
'PersonalInformation.first_name' => $this->request->data['User']['first_name'],
'PersonalInformation.last_name' => $this->request->data['User']['last_name'],
'PersonalInformation.primary_phone' => $this->request->data['User']['primary_phone'],
'PersonalInformation.dob' => $this->request->data['User']['dob'],
'User.email' => $this->request->data['User']['email'],
);
//==========This Function allow remove blank element from array=========//
$or = array_filter($or);
//=====End============//
$condition = array(
'User.role' => array('U', 'P'),
'User.user_status' => array('active', 'lead', 'inactive'),
'OR' => $or
);
$data = $this->User->find('first', array(
'conditions' => $condition)
);
// pr($data); exit;
$this->set('allusers', $data);
}
$data = $this->User->find('all', array(
'conditions' => $condition)
);
//pr($data); exit;
$this->set('allusers', $data);
$this->layout = 'admin';
}

How do I query data in CakePHP using HABTM relationships and translation?

I'm using Cakephp and try to make my model to ActAs 'Translation'. But i have a problem.
My Client model relations are:
public $belongsTo = array("User");
public $hasAndBelongsToMany = array(
'Category' =>
array(
'className' => 'Category',
'joinTable' => 'categories_clients',
'foreignKey' => 'client_id',
'associationForeignKey' => 'category_id',
'unique' => true,
),
);
In Category Model:
public $name = 'Category';
public $hasMany = array(
'Product'
);
public $displayField = 'title';
public $recursive = 1;
public $actsAs = array(
'Tree',
'Translate' => array(
'title',
'alias',
'description',
),
'Containable' => array('CategoryTranslations'),
);
public $translateModel = 'CategoryTranslations';
public $translateTable = 'category_translations';
When i query from Client Controller to get all Client and relative Category, i can't get field "title", "alias" and "description" of Category. Here is my code:
if(isset($this->passedArgs['language_id'])){
$language_id = $this->passedArgs['language_id'];
}
else{
$language_id = Configure::read('Config.language_site');
}
$this->Client->Category->locale = $language_id;
$this->Client->recursive = 1;
$this->paginate = array('limit' => 20,'order' => array('User.id' => 'desc'));
$Clients = $this->paginate();
Here is result:
array(
'Client' => array(
'id' => '1',
'user_id' => '1',
'client_type' => 'tenderer',
'image' => null,
'image_list' => null,
'code' => 'SG0593',
'name' => 'Oorts',
'address' => '1000 Huynh Tan Phat',
'telephone' => '0987654321',
'fax' => '0983213434',
'email' => 'nguyentuandat.vn#gmail.com',
'proxy' => 'Dat Nguyen',
'position' => 'C.E.O',
'mobile' => '0987654321',
'referred_by' => 'noone',
'order' => null,
'status' => true,
'created' => '2014-03-27 00:00:00',
'modified' => '2014-03-27 00:00:00'
),
'User' => array(
'password' => '*****',
'id' => '1',
'username' => 'admin',
'group_id' => '1',
'gender' => 'Male',
'first_name' => 'Nguyễn',
'middle_name' => 'Tuấn',
'last_name' => 'Đạt',
'email' => 'nguyentuandat.vn#gmail.com',
'phone_number' => '(+84) 947235313',
'image' => '/uploads/images/255443_102754699884371_1177788671_n.jpg',
'status' => true,
'created' => '2014-01-16 09:26:09',
'modified' => '2014-01-22 06:47:25',
'full_name' => 'Nguyễn Tuấn Đạt'
),
'Category' => array(
(int) 0 => array(
'id' => '1',
'parent_id' => '0',
'type' => 'product',
'image' => '',
'order' => '0',
'status' => true,
'lft' => '1',
'rght' => '16',
'created' => '2014-01-25 00:00:00',
'modified' => '2014-01-25 00:00:00',
'CategoriesClient' => array(
'id' => '1',
'category_id' => '1',
'client_id' => '1'
)
)
)
)
Can you help me? Thank you!
Restructure the code
Unfortunately because of how behaviors work - that's none-trivial to solve exactly as asked.
You can however do something like this:
$Clients = $this->paginate();
// extract category ids in the results
$categoryIds = array_unique(Hash::extract($Clients, '{n}.Category.{n}.id'));
$categories = $this->Client->Category->find('all', array(
'conditions' => array(
'Category.id' => $categoryIds
)
));
// generate a category-id indexed array of categories
$categories = Hash::combine($categories, '{n}.Category.id', '{n}.Category');
// replace the untranslated category entries with translated category data
foreach($Clients as &$client) {
foreach($client['Category'] as &$cat) {
$id = $cat['id'];
$cat = $categories[$id];
}
}
This example is shown as pseudo controller code - you could also consider putting it in your Client afterFind method or a custom finder.
Thank for help.
I found a solution:
I added bellow code into AppModel->afterFind and it work fine
public function afterFind($results, $primary = false) {
if(!empty($this->hasAndBelongsToMany)) {
foreach($this->hasAndBelongsToMany as $model => $settings) {
if(isset($this->{$model}->actsAs['Translate'])) {
if(!empty($results[0][$model])) {
foreach($results as $k => $v){
foreach($results[$k][$model] as $row => $result) {
$supplement = $this->{$model}->find('first', array(
'conditions' => array(
$model .'.id' => $result['id']),
'fields' => $this->{$model}->actsAs['Translate'],
'recursive' => -1));
if(!empty($supplement)) {
$results[$k][$model][$row] = array_merge($results[$k][$model][$row], array_diff($supplement[$model], $result));
}
}
}// end foreach k=>v
}
}
}
}
return $results;
}

Resources