I would like to make a Post object containing an instance of its associated table User and the easiest would be if I could access user results and post results separately.
The query:
$query = $this->connection->newQuery()->from('post');
$query->select(
[
'post.message',
'post.created_at',
'user.name',
'user.email',
'user.role',
'user.status',
]
)->join(['table' => 'user', 'conditions' => 'post.user_id = user.id']);
$postsRows = $query->execute()->fetchAll('assoc');
The query above outputs an array of the result rows and I have no way to know if the column is from the user table or post table.
$postsRows = array (
0 =>
array (
'message' => 'This is a test post',
'created_at' => '2021-01-01 00:00:01',
'name' => 'Admin Example',
'email' => 'admin#example.com',
'role' => 'admin',
'status' => 'active',
),
1 =>
array (
'message' => 'This is another test post',
'created_at' => '2021-01-01 00:00:01',
'name' => 'User Example',
'email' => 'user#example.com',
'role' => 'user',
'status' => 'active',
),
)
Naturally I can make aliases for each column
$query = $this->connection->newQuery()->from('post');
$query->select(
[
'post.*',
'user_name' => 'user.name',
'user_email' => 'user.email',
'user_role' => 'user.role',
'user_status' => 'user.status',
]
)->join(['table' => 'user', 'conditions' => 'post.user_id = user.id']);
$postsRows = $query->execute()->fetchAll('assoc');
But then I have to go through them and split the array manually later, I can't alias the post column names as I use the expression * and it won't work when joining the same table.
I guess what would be ideal would be the following output. Is something like this possible?
$postsRows = array(
0 => array(
'post' => array(
'message' => 'This is a test post',
'created_at' => '2021-01-01 00:00:01',
),
'user' => array(
'name' => 'Admin Example',
'email' => 'admin#example.com',
'role' => 'admin',
'status' => 'active',
)
),
1 => array(
'post' => array(
'message' => 'This is another test post',
'created_at' => '2021-01-01 00:00:01',
),
'user' => array(
'name' => 'User Example',
'email' => 'user#example.com',
'role' => 'user',
'status' => 'active',
),
),
)
As discussed here, the workflow that interests me is more "use case" based, and then it doesn't make sense to do what I requested (as it would kind of be reinventing ORM which I did first).
What works out for me is creating specific DTOs with high cohesion like UserPost in which case the origin of the table is not relevant as fields are selected individually, precisely.
Related
I am trying to retrieve data from "Opportunities" Reports.
This is my scenario: Opportunity module, field sales_person is a realated field from users module.
In Bids modules I have a relate field with opportunities.
During report generation, I am trying to retrieve the sales_person name in opportunities. But it is not listing in Bids report field_lists.
My dictionary in Bids
'opportunity_id_c' => array(
'required' => false,
'name' => 'opportunity_id_c',
'vname' => 'LBL_OPPORTUNITY_OPPORTUNITY_ID',
'type' => 'id',
'reportable' => true,
'calculated' => false,
'len' => 36,
'size' => '20',
),
'opportunity' => array(
'required' => false,
'source' => 'non-db',
'name' => 'opportunity',
'vname' => 'LBL_OPPORTUNITY',
'type' => 'relate',
'reportable' => true,
'unified_search' => false,
'merge_filter' => 'disabled',
'len' => '255',
'size' => '20',
'id_name' => 'opportunity_id_c',
'ext2' => 'Opportunities',
'module' => 'Opportunities',
'rname' => 'name',
'quicksearch' => 'enabled',
'studio' => 'visible',
),
Relationship:
$dictionary['Opportunity']['fields']['opportunities_procurements'] = [
'name' => 'opportunities_procurements',
'type' => 'link',
'relationship' => 'opportunities_procurements',
'module' => 'Procurement',
'bean_name' => 'Procurement',
'source' => 'non-db',
'vname' => '',
];
$dictionary['Opportunity']['relationships']['opportunities_procurements'] = [
'lhs_module' => 'Opportunities',
'lhs_table' => 'opportunities',
'lhs_key' => 'id',
'rhs_module' => 'Procurement',
'rhs_table' => 'procurement',
'rhs_key' => 'opportunity_id_c',
'relationship_type' => 'one-to-many',
];
This is what I tried: I tried to create a similar field opportunity in bids module named as opportunity_sales_userand in dictionary instead of 'rname' => 'name', I use 'rname' => 'sales_person', but I didn't get the data as the sales_person is related record.
I couldn't retrieve the vales in Reports.
How can I create a full relationship so I can get the sales_person value in Bids reports generation?
I am facing same problem so , i choose to write a simple SQL query
global $db;
$query = "Your Sql to get Reports";
$re = $db->query($query);
$data = '';
while ($row = $db->fetchByAssoc($re)) {
your code
}
I run a solr query, which returns a result set of jobs.
Some of the jobs are duplicates (but from different sources), which is decided based on if the job title, description and location are the same.
I want to loop through my result set, and combine any duplicated into one job, with that one job having multiple sources... something like:
original result:
$jobs = array(
array(
'id' => 'job1',
'title' => 'test',
'description' => 'test',
'location' => 'test',
'source' => 'source1',
),
array(
'id' => 'job2',
'title' => 'test',
'description' => 'test',
'location' => 'test',
'source' => 'source2',
),
array(
'id' => 'job3',
'title' => 'test',
'description' => 'test',
'location' => 'test',
'source' => 'source3',
),
array(
'id' => 'job4',
'title' => 'testing',
'description' => 'testing',
'location' => 'testing',
'source' => 'source1',
)
);
would become:
$jobs = array(
array(
'id' => 'job1',
'title' => 'test',
'description' => 'test',
'location' => 'test',
'source' => 'source1',
'other_sources' => array(
array(
'id' => 'job2',
'title' => 'test',
'description' => 'test',
'location' => 'test',
'source' => 'source2'
),
array(
'id' => job3,
'title' => 'test',
'description' => 'test',
'location' => 'test',
'source' => 'source3'
),
),
),
array(
'id' => 'job4',
'title' => 'testing',
'description' => 'testing',
'location' => 'testing',
'source' => 'source1'
)
);
how can I achieve this? Either in PHP or perhaps in the Solr query itself (I'm using Solarium to do my Solr querying)
How about something like this?
<?php
$result = array();
foreach ($jobs as $job) {
if (!empty($result[$job['title']])) {
$result[$job['title']]['other_sources'][] = $job;
}
else {
$result[$job['title']] = $job;
}
}
It initializes an empty array($result) and then loops through the job array. The empty array will store the jobs with the title being used as the key. If the job title does not exist in the result array, then it will add it. If the job title does exist in the job array, then it will append the job to an array inside the existing job (under the key 'other_sources')
I cant use a join to get the required data from the table relationship of
Student HABTM Subject, and
Guardian 1 to many Student
Without giving all the code,my find gets the required data but it adds another table (AvailabilityForStudent)which has a HABTM relationship with Student, along with other fields. I simply get too much data.
I have to add Guardian2 to the Guardian table to avoid a conflict which i dont understand.
What is the correct join to display data from 3 tables only?
$students = $this->find('all', array(
'joins'=>$joins,
'conditions' => $conditions,
'fields'=> $fields,
'order'=>$order,
));
$joins = array(
array('table' => 'students_subjects',
'alias' => 'StudentsSubject',
'type' => 'LEFT',
'conditions' => array(
'Student.id=StudentsSubject.student_id',
)
),
array('table' => 'subjects',
'alias' => 'Subject',
'type' => 'LEFT',
'conditions' => array(
'StudentsSubject.subject_id=Subject.id',
)
),
array('table' => 'guardians',
'alias' => 'Guardian2',
'type' => 'LEFT',
'conditions' => array(
'Student.guardian_id=Guardian2.id',
)
),
);
(int) 0 => array(
'Student' => array(
'id' => '267',
'last_name' => 'xxx',
'first_name' => 'xxx',
'address_suburb' => 'xxx',
'student_inactive' => false,
'student_mobile' => '0'
),
'Guardian' => array(
'guardian_last_name' => 'xx',
'guardian_first_name' => 'xxxx',
'id' => '267',
'guardian_mobile' => 'xxxx',
'guardian_email' => 'xx#yahoo.com.au'
),
'Subject' => array(
'name' => 'English: Year 7 - 10',
(int) 0 => array(
'id' => '9',
'name' => 'English: Year 7 - 10',
'StudentsSubject' => array(
'id' => '1079',
'student_id' => '267',
'subject_id' => '9',
'created' => null,
'modified' => null
)
)
),
'StudentsSubject' => array(
'id' => '1079'
),
'AvailabilityForStudent' => array(
(int) 0 => array(
Update- added this line $this->recursive = -1 instead of $this->Student->recursive = -1; and it works
Update- added this line $this->recursive = -1 instead of $this->Student->recursive = -1; and it works
I have a HABTM relationship of Students and Subjects. I simply want to display all the subjects associated with a student without repetition of student details. I dont want the student details to keep repeating in the data output. How do I get the student details as shown below to output once and then all the subjects associated with this student to output?
Group didnt work. I didnt see the answer in the docs but I am sure this is a simple task to do.
http://book.cakephp.org/2.0/en/models/retrieving-your-data.html
$this->Student->recursive = -1;
$joinoptions = array(
// $options['joins'] = array(
array('table' => 'students_subjects',
'alias' => 'StudentsSubject',
'type' => 'LEFT',
'conditions' => array(
'Student.id = StudentsSubject.student_id',
)
),
array('table' => 'subjects',
'alias' => 'Subject',
'type' => 'LEFT',
'conditions' => array(
'StudentsSubject.subject_id=Subject.id',
)
),
);
$fieldoptions = array('Student.id,Student.last_name,Student.first_name,Student.address_street,Student.address_suburb,'
. 'Subject.name,Subject.id, StudentsSubject.id, Student.first_name,Student.last_name,Student.address_lat,Student.address_long,Student.tutor_gender_preference'
);
$student=$this->Student->find('all',array(
'conditions'=> array( 'Student.id' => $student_id),
'fields'=>$fieldoptions,
'joins'=> $joinoptions,
// 'group' => 'Student.id',
'recursive' =>-1,
));
array(
(int) 0 => array(
'Student' => array(
'id' => '216',
'last_name' => 'Ncc',
'first_name' => 'Acc',
'address_street' => '8 sdsdt',
'address_suburb' => 'Hasdsdk',
'address_lat' => 'xx',
'address_long' => 'xx',
'tutor_gender_preference' => 'No Preference'
),
'Subject' => array(
'name' => 'English: Year 7 - 10',
'id' => '9'
),
'StudentsSubject' => array(
'id' => '531'
)
),
(int) 1 => array(
'Student' => array(
'id' => '216',
'last_name' => 'Ncc',
'first_name' => 'Acc',
'address_street' => '8 sdsdt',
'address_suburb' => 'Hasdsdk',
'address_lat' => 'xx',
'address_long' => 'xx',
'tutor_gender_preference' => 'No Preference'
),
'Subject' => array(
'name' => 'Maths: Year 7 - 10',
'id' => '16'
),
'StudentsSubject' => array(
'id' => '532'
)
),
(int) 2 => array(
'Student' => array(
'id' => '216',
'last_name' => 'Ncc',
'first_name' => 'Acc',
'address_street' => '8 sdsdt',
'address_suburb' => 'Hasdsdk',
'address_lat' => 'xx',
'address_long' => 'xx',
'tutor_gender_preference' => 'No Preference'
),
'Subject' => array(
'name' => 'Physics: Year 11',
'id' => '28'
),
'StudentsSubject' => array(
'id' => '583'
)
)
)
I have 3 models: messages, forums and users
A forum may have several messages and each message has posted by one user.
I would like to have in my forum model all messages and their owner.
So, in my Forum.php (model), I write:
public $belongsTo=array(
'User' => array(
'className' => 'User',
'foreignKey'=>'id_user'
),
);
public $hasMany=array(
'Message' => array(
'className' => 'Message',
'foreignKey'=>'id_forum'
),
);
and in my Message.php (model) :
public $belongsTo=array(
'User' => array(
'className' => 'User',
'foreignKey'=>'id_user'
),
);
With "debug($this->Forum->find('all'));", I get :
array(
(int) 0 => array(
'Forum' => array(
'id' => '3',
'titre' => 'rooo',
'message' => 'tooo',
'id_user' => '2',
'date_create' => '2014-07-20 17:24:07'
),
'User' => array(
'password' => '*****',
'id' => '2',
'username' => 'member',
'date_sign' => '2014-07-04 11:34:52'
),
'Message' => array(
(int) 0 => array(
'id' => '5',
'message' => 'hi',
'id_user' => '3',
'id_forum' => '3',
'date_add' => '2014-07-20 18:53:51'
)
)
)
)
But with "debug($this->Message->find('all'));", I get :
array(
(int) 0 => array(
'Message' => array(
'id' => '5',
'message' => 'hi',
'id_user' => '3',
'id_forum' => '3',
'date_add' => '2014-07-20 18:53:51'
),
'User' => array(
'password' => '*****',
'id' => '3',
'username' => 'membre2',
'date_sign' => '2014-07-20 18:26:41'
)
)
)
I don't understand why I don't get my user informations on my 1st model but it's working in the 2nd.
Thanks for helping.
You need to set recursive property of Forum modal to 2
$this->Forum->recursive=2;
For more information check here cakephp docs