I am following example documented at http://book.cakephp.org/view/83/hasAndBelongsToMany-HABTM
I am trying to retrieve associated data using hasOne.
I created 3 tables posts, tags and posts_tags.
I wrote following code to debug Posts.
$this->Post->bindModel(array(
'hasOne' => array(
'PostsTag',
'FilterTag' => array(
'className' => 'Tag',
'foreignKey' => false,
'conditions' => array('FilterTag.id = PostsTag.tag_id')
))));
$output=$this->Post->find('all', array(
'fields' => array('Post.*')
));
debug($output);
I was expecting output something like below.
Array
(
0 => Array
{
[Post] => Array
(
[id] => 1
[title] => test post 1
)
[Tag] => Array
(
[0] => Array
(
[id] => 1
[name] => php
)
[1] => Array
(
[id] => 2
[name] => javascript
)
[2] => Array
(
[id] => 3
[name] => xml
)
)
}
But my output do not have Tags at all.
Here is what I got.
Array
(
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => test post1
)
)
[1] => Array
(
[Post] => Array
(
[id] => 2
[title] => test post2
)
)
)
How do I get associated tags along with the post.
I know I am missing something, but unable to figure out.
Any help would be highly appreciated.
Edit 1:
Ok I tried few more variants.
I tried:
$this->Post->bindModel(array(
'hasOne' => array(
'PostsTag',
'FilterTag' => array(
'className' => 'Tag',
'foreignKey' => false,
'conditions' => array('FilterTag.id = PostsTag.tag_id')
))));
$output=$this->Post->find('all');
I got:
Array
(
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => test post1
)
[PostsTag] => Array
(
[id] => 1
[post_id] => 1
[tag_id] => 1
)
[FilterTag] => Array
(
[id] => 1
[name] => php
)
)
[1] => Array
(
[Post] => Array
(
[id] => 1
[title] => test post1
)
[PostsTag] => Array
(
[id] => 2
[post_id] => 1
[tag_id] => 2
)
[FilterTag] => Array
(
[id] => 2
[name] => javascript
)
)
[2] => Array
(
[Post] => Array
(
[id] => 1
[title] => test post1
)
[PostsTag] => Array
(
[id] => 3
[post_id] => 1
[tag_id] => 3
)
[FilterTag] => Array
(
[id] => 3
[name] => xml
)
)
)
I tried:
$output=$this->Post->find('all', array(
'fields' => array('Post.*', 'FilterTag.*'),
'recursive' => 1
));
I got:
Array
(
[0] => Array
(
[Post] => Array
(
[id] => 1
[title] => test post1
)
[FilterTag] => Array
(
[id] => 1
[name] => php
)
)
[1] => Array
(
[Post] => Array
(
[id] => 1
[title] => test post1
)
[FilterTag] => Array
(
[id] => 2
[name] => javascript
)
)
[2] => Array
(
[Post] => Array
(
[id] => 1
[title] => test post1
)
[FilterTag] => Array
(
[id] => 3
[name] => xml
)
)
)
Just in case I am missing something, here is my Posts controller:
class PostsController extends AppController {
var $name = 'Posts';
var $helpers = array('Html','Ajax','Javascript');
var $components = array( 'RequestHandler' );
function index() {
$this->Post->bindModel(array(
'hasOne' => array(
'PostsTag',
'FilterTag' => array(
'className' => 'Tag',
'foreignKey' => false,
'conditions' => array('FilterTag.id = PostsTag.tag_id')
))));
$output=$this->Post->find('all', array(
'fields' => array('Post.*', 'FilterTag.*'),
'recursive' => 1
));
}
}
And here is my Posts model:
class Post extends AppModel {
var $name = 'Post';
}
I still wonder why is the example from cookbook not working.
I would recommend checking 3 things:
See if you have set your
associations right (hasMany,
hasAndBelongsToMany)
Make sure you have set the Post HABTM Tag and Tag HABTM Post relationships correctly.
Check the value
of $recursive
Most of the examples in the CakePHP book require that you have your $recursive property set to 1.
Remove the fields
restriction: 'fields' =>
array('Post.*')
It's possible that Cake is restricting only the Post fields, which is why no Tag fields are showing up. Remove this restriction and try it again.
Let us know if this works for you.
Related
I would like to get the distinct code_y values, and I use below code, the output is equal to select distinct code_y from table_x,
$res = $db_x->command (
array(
"aggregate" => "table_x",
"pipeline" =>
array(
array( '$group' => array( "_id" => ['id' =>'$code_y', 'name' => '$code_x', 'color' => '$color']))),
"cursor" => ['batchSize' => 200]
)
);
I got results as below, I don't need [_id] => Array, just id, name and color, How to separate array from nested arrays with MongoDB and PHP aggregate? Or how to put [_id] => Array together with id, name and color? as in my front-end htmls pages, I got [object] [Object] because of those nested arrays.
[0] => Array
(
[_id] => Array
(
[id] => a1
[name] => bbb
[color] => blue
)
)
[1] => Array
(
[_id] => Array
(
[id] => a2
[name] => aaa
[color] => blue
)
)
[2] => Array
(
[_id] => Array
(
[id] => a3
[name] => abc
[color] =>red
)
)
What I want is as below:
[0] => Array
(
[id] => a1
[name] => bbb
[color] => blue
)
[1] => Array
(
[id] => a2
[name] => aaa
[color] => blue
)
[2] => Array
(
[id] => a3
[name] => abc
[color] =>red
)
What you need is a another stage after the group.
You could either use project and list each field:
array( '$project' => array(
"id" => '$_id.id',
"name" => '$_id.name',
"color" => '$_id.color'
))
or $replaceRoot to grab them all:
array( '$replaceRoot' => array( "newRoot" => '$_id' ))
I have a class that I am using as part of the CMB2 framework for WordPress. It has a protected object that I am trying to append a list of years to. My code looks like this in my function
function cmb2_team_members_metaboxes() {
global $redux_rg;
$prefix = '_cmb2_';
$cmb_team_members = new_cmb2_box(array(
'id' => 'team_member_metabox',
'title' => __( 'Team Member Metabox', 'rev-group' ),
'object_types' => array( 'post_type_teammember', ), // Post type
'context' => 'normal', // 'normal', 'advanced', or 'side'
'priority' => 'high', // 'high', 'core', 'default' or 'low'
'show_names' => true, // Show field names on the left
));
I add more fields then below I am trying to append the years() output to an options list of an HTML select / dropdown. to do this I need to append $cmb_team_members->meta_box['fields']['_cmb_start_year']['options'] with the output array from the function years(). Below is where I am trying to extend CMB2 class which is protected with the years() output.
class yearsClass extends CMB2
{
public function __set($name, $value)
{
$this->$cmb_team_members->meta_box['fields']['_cmb_start_year']['options'] = years();
}
}
I know I am doing this completely wrong but I can't seem to crack this. Any help would be appreciated.
I have years defined in my functions.php file and it outputs:
array(
2015 => 2015,
2014 => 2014
)
When I output the CMB2 Object I get this:
CMB2 Object (
[cmb_id:protected] => team_member_metabox
[meta_box:protected] => Array
(
[id] => team_member_metabox
[title] => Team Member Metabox
[type] =>
[object_types] => Array
(
[0] => post_type_teammember
)
[context] => normal
[priority] => high
[show_names] => 1
[show_on_cb] =>
[show_on] => Array
(
)
[cmb_styles] => 1
[enqueue_js] => 1
[fields] => Array
(
[_cmb2_division] => Array
(
[name] => Division
[desc] => The division of the company this person works in (These can be edited in the Revolution Group theme options)
[id] => _cmb2_division
[type] => select
[options] => Array
(
)
)
[_cmb2_photo] => Array
(
[name] => Photo
[desc] =>
[id] => _cmb2_photo
[type] => file
)
[_cmb2_position] => Array
(
[name] => Position
[desc] => Job position
[id] => _cmb2_position
[type] => text
)
[_cmb2_email] => Array
(
[name] => Email
[desc] => Email address
[id] => _cmb2_email
[type] => text_email
)
[_cmb2_bio] => Array
(
[name] => Bio
[desc] =>
[id] => _cmb2_bio
[type] => wysiwyg
[options] => Array
(
[media_buttons] => 1
[textarea_rows] => 5
)
)
[_cmb2_start_year] => Array
(
[name] => Year Started
[desc] => The year the team member started with Revolution Group
[id] => _cmb2_start_year
[type] => select
[options] => Array
(
)
)
[_cmb2_certifications_repeat_group] => Array
(
[id] => _cmb2_certifications_repeat_group
[type] => group
[description] => Certifications (These can be edited in the Revolution Group theme options)
[options] => Array
(
[group_title] => Certification {#}
[add_button] => Add Another Certification
[remove_button] => Remove Certification
[sortable] => 1
)
[fields] => Array
(
[certification] => Array
(
[name] => Certification
[description] => Please select
[id] => _cmb2_certification
[type] => select
[options] => Array
(
)
)
[certification_year] => Array
(
[name] => Year Obtained
[description] => The year this certification was aquired
[id] => _cmb2_certification_year
[type] => select
[options] => Array
(
)
)
)
)
[_cmb2_skills_repeat_group] => Array
(
[id] => _cmb2_skills_repeat_group
[type] => group
[description] => Skills (These can be edited in the Revolution Group theme options)
[options] => Array
(
[group_title] => Skill {#}
[add_button] => Add Another Skill
[remove_button] => Remove Skill
[sortable] => 1
)
[fields] => Array
(
[skill] => Array
(
[name] => Skill
[description] => Please select
[id] => _cmb2_skill
[type] => select
[options] => Array
(
)
)
)
)
[_cmb2_fun_fact] => Array
(
[name] => Fun Fact
[desc] =>
[id] => _cmb2_fun_fact
[type] => wysiwyg
[options] => Array
(
[media_buttons] => 1
[textarea_rows] => 5
)
)
[_cmb2_order] => Array
(
[name] => Order
[desc] => Order that the team member should be displayed. The lower the number the hghter on the list when displayed
[id] => _cmb2_order
[type] => text
)
)
[hookup] => 1
[save_fields] => 1
[closed] =>
[new_user_section] => add-new-user
)
[object_id:protected] => 0
[object_type:protected] => post
[mb_object_type:protected] => post
[updated:protected] => Array
(
)
[mb_defaults:protected] => Array
(
[id] =>
[title] =>
[type] =>
[object_types] => Array
(
)
[context] => normal
[priority] => high
[show_names] => 1
[show_on_cb] =>
[show_on] => Array
(
)
[cmb_styles] => 1
[enqueue_js] => 1
[fields] => Array
(
)
[hookup] => 1
[save_fields] => 1
[closed] =>
[new_user_section] => add-new-user
)
[fields:protected] => Array
(
)
[hidden_fields:protected] => Array
(
)
[data_to_save] => Array
(
)
[generated_nonce:protected] =>
)
In my app, I have the following Models and relationships:
ActiveMember belongsTo Team
ActiveMember belongsTo Rank
ActiveMember hasMany ContactInfo
ContactInfo belongsTo ContactType
In my controller, I am them doing a contained find as so;
$this->Team->contain(array(
'ActiveMember' => array (
'fields' => array('id','surname','firstname'),
'Rank' => array(
'fields' => array('id','display','position')) ,
'ContactInfo' => array (
'ContactType',
'conditions' => 'contact_type_id IN (1, 2, 3, 4)'
)
)
)
);
$Teams = $this->Team->find('all', array('conditions' => 'Team.active = 1 AND Team.display_order<99'));
This then returns an array like this:
Array
(
[0] => Array
(
[Team] => Array
(
[id] => 3
[name] => Command
[display_order] => 1
[active] => 1
)
[ActiveMember] => Array
(
[0] => Array
(
[id] => 1
[surname] => Bloggs
[firstname] => Joe
[rank_id] => 1
[team_id] => 3
[Rank] => Array
(
[id] => 1
[display] => Commander
[position] => 1
)
[ContactInfo] => Array
(
[0] => Array
(
[id] => 2
[member_id] => 1
[contact_type_id] => 1
[info] => 1234 5678
[ContactType] => Array
(
[id] => 1
[name] => Home Phone
[format] => #### ####
)
)
)
)
[1] => Array
(
[id] => 3
[surname] => Smith
[firstname] => Jane
[rank_id] => 2
[team_id] => 3
[Rank] => Array
(
[id] => 2
[display] => Dep Comm
[position] => 10
)
[ContactInfo] => Array
(
)
)
)
)
[1] => Array
(
[Team] => Array
(
[id] => 1
[name] => Support
[display_order] => 2
[active] => 1
)
[ActiveMember] => Array
(
[0] => Array
(
[id] => 124
[surname] => Johnson
[firstname] => John
[rank_id] => 6
[team_id] => 1
[Rank] => Array
(
[id] => 6
[display] => Member
[position] => 50
)
[ContactInfo] => Array
(
)
)
And then I want to sort the result as per 'ORDER BY Team.display_order, Team.Member.Rank.position, Team.Member.surname, Team.Member.firstname'
Given that I can't do this complex sort in the query without doing adhoc joins, I thought I could use Set::sort, called four times to sort the order.
$Teams = Set::sort($Teams,'{n}.ActiveMember.{n}.surname','asc');
$Teams = Set::sort($Teams,'{n}.ActiveMember.{n}.firstname','asc');
$Teams = Set::sort($Teams,'{n}.ActiveMember.{n}.Rank.position','asc');
$Teams = Set::sort($Teams,'{n}.Team.display_order','asc');
However, despite the Set path of the first three lines returning correct values if I do a Set::extract, they do not have any effect on the array order (either when called as a group, or as the only sort). The final line works.
Can someone please advise where my mistake is, or another way to achieve the same result?
Updated: I have two separate arrays which hold some data returned from search() function of SolrPhpClient. The arrays contain data in form of Apache_Sole_Document objects. These objects in turn contain the actual fields and values. I merge these two arrays to get a single array holding all items using array_merge() of PHP
The array will have some duplicate items which needs to be removed.
I am not sure how to achieve it in this structure.
The array structure is as such:
Array ( [0] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 111 [name] => ABCD )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[1] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 222 [name] => DEFG )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[2] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 333 [name] => LMNO )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[3] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 111 [name] => ABCD )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[4] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 444 [name] => PQRS )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[5] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 222 [name] => DEFG )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
)
As you can see there is a [id] field and a [name] field.
I would like to remove duplicates from the array comparing the [id] field.
The final array after removing duplicates should look like this:
Array ( [0] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 111 [name] => ABCD )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[1] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 222 [name] => DEFG )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[2] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 333 [name] => LMNO )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
[3] => Apache_Solr_Document Object (
[_documentBoost:protected] =>
[_fields:protected] => Array ( [id] => 444 [name] => PQRS )
[_fieldBoosts:protected] => Array ( [id] => [name] => )
)
)
How can I achieve this? somebody please help!
I guess you could iterate over the array and remove the duplicates, but that doesn't seem like a neat solution to me.
I'm not familiar with the SolrPhpClient, but Solr does support grouping on fields. You can group on the id by adding this part to your request:
group=true&group.field=id
The documents returned will be grouped on the id. For more details check this page.
Update:
I looked at the SolrPhpClient documentation and see that you can add additional parameters to your request like this:
$additionalParameters = array(
'fq' => 'a filtering query',
'facet' => 'true',
'facet.field' => array(
'field_1',
'field_2'
)
);
$results = $solr->search($query, $start, $rows, $additionalParameters);
I assume you can add the grouping parameters to this:
$additionalParameters = array(
'group' => 'true',
'group.field' => 'id'
)
);
$results = $solr->search($query, $start, $rows, $additionalParameters);
For more details on this, check this page
I am retrieving data from sql server and then present them in an organised way.
I have an array of object like this:
Array
(
[0] => stdClass Object
(
[post_id] => 1
[controller] => Cato
[controller_method] => edit
[http_method] => post
)
[1] => stdClass Object
(
[post_id] => 1
[controller] => Cato
[controller_method] => edit
[http_method] => get
)
[2] => stdClass Object
(
[post_id] => 1
[controller] => Cato
[controller_method] => create
[http_method] => post
)
[3] => stdClass Object
(
[post_id] => 1
[controller] => Cato
[controller_method] => create
[http_method] => get
)
)
Somehow I need to convert to things like this:
Array(
[0] => Array(
[controller] => controller1,
[controller_methods] => Array (
[0] => Array (
[controller_method] => create,
[http_methods] => Array (
[0] => get,
[1] => post
)
),
[0] => Array (
[controller_method] => edit,
[http_methods] => Array (
[0] => get,
[1] => post
)
)
)
),
[0] => Array(
[controller] => controller2,
[controller_methods] => Array (
[0] => Array (
[controller_method] => create,
[http_methods] => Array (
[0] => get,
[1] => post
)
),
[0] => Array (
[controller_method] => edit,
[http_methods] => Array (
[0] => get,
[1] => post
)
)
)
)
)
I always encounter things like this when working with php with sql db
Is there any convenient way to do this?