cakephp 2 threaded not showing children - cakephp-2.0

Hi i don't know what is wrong with the threaded of cakephp 2 please help
when i use threaded without condition it will show its children
$category = $this->Category->find('threaded');
output:
Array
(
[0] => Array
(
[Category] => Array
(
[id] => 11
[name] => Affinity Collection
[parent_id] => 0
[lft] => 25
[rght] => 30
[alias] => affinity-collection
[status] => 0
)
[children] => Array
(
[0] => Array
(
[Category] => Array
(
[id] => 113
[name] => Core samples
[parent_id] => 11
)
)
)
but when i use this with condition it won't show its parent
$this->Category->find('threaded',array('conditions'=>array('Category.id'=>11)));
output:
Array
(
[0] => Array
(
[Category] => Array
(
[id] => 11
[name] => Affinity Collection
[parent_id] => 0
[lft] => 25
[rght] => 30
[alias] => affinity-collection
[status] => 0
)
[children] => Array
(
)
)
)
please help why it is not showing the children when use with condition

I think the problem is because you are asking for all categories with an id of 11. Insted you should ask for all categories that are children of categorie 11.
You could use your left and right columns to get a nested array (keyword Tree behaviour). Try this:
$parentCategorie = $this->Categorie->find('first', array(
'conditions' => array(
'Categorie.id' => 11
)
);
$children = $this->Categorie->find('first', array(
'conditions' => array(
'Categorie.lft BETWEEN ? AND ?' => array($parentCategorie['Categorie']['lft'], $parentCategorie['Categorie'])['rght']
)
);

Probably the best chance you have to achive what you want is to use the children method of the Tree behavior.
You coul use it as follows
$parent=$this->Category->find('first',
array('conditions'=>array('Category.id'=>11)));
$this->Category->children($parent['Category']['id']);

Related

Organize a groupBy within another groupBy using Collection in CakePHP

I have the following array and I would like to be able to organize it through collection
$collection = Collection($total);
$filter = $collection->groupBy('date_general')->toArray();
[2017-11-14] => Array
(
[0] => Array
(
[status] => pending
[date_general] => 2017-11-14
[user_id] => 164
)
[1] => Array
(
[status] => pending
[date_general] => 2017-11-14
[user_id] => 112
)
)
Up to this point I already have the array organized by dates. Now within each date I need to organize it by user, that is to say that it is:
[2017-11-14] => Array
(
[164] => Array
(
[0] => Array
(
[status] => pending
[date_general] => 2017-11-14
[user_id] => 164
)
)
[112] => Array
(
[0] => Array
(
[status] => pending
[date_general] => 2017-11-14
[user_id] => 112
)
)
)
You'll have to process each date group and individually group their contents.
$collection = collection($total)
->groupBy('date_general')
->map(function ($data) {
return collection($data)->groupBy('user_id')->toArray();
});
See also
Cookbook > Collections

cakephp multiple records data array fit in request data

I need to get multiple records from model, then put them into request->data for a view to render into a form with multiple input fieldsets for example name='data[Applicant][0][display_name]'. name='data[Applicant][1][display_name]'...data value goes in for each applicant.
Actually I've already done what i want, but i do not think it is a good method to do so.
Appreciate if anyone can guide me
foreach ($this->Applicant->data['Applicant'] as $key=>$item){
$data['Applicant'][] = $item['Applicant'];
}
$this->request->data = $data;//set Model to data
$this->set('data' , $this->Applicant->data);
$this->Applicant->data is the following:
Array
(
[Applicant] => Array
(
[0] => Array
(
[Applicant] => Array
(
[id] => 1
[application_id] => 17
[name] => User
[first_name] =>
...
)
)
[1] => Array
(
[Applicant] => Array
(
[id] => 3
[application_id] => 17
[name] =>
[first_name] =>
the following is the desired output (less one level):
Array
(
[Applicant] => Array
(
[0] => Array
(
[id] => 1
[application_id] => 17
[name] => User
[first_name] =>
...
)
[1] => Array
(
[id] => 3
[application_id] => 17
[name] =>
[first_name] =>
thanks
This should suffice:
$this->request->data['Applicant'] = Hash::extract( $this->Applicant->data, 'Applicant.{n}.Applicant' );

How to list all tags (HABTM) with number of stories in less than 2 queries in Cakephp?

I would like to be able to list the 10 most popular tags (subjects) of my site on the right menu as an element.
I however have been thinking 30 minutes about this now and unlike ending up with 1 statement to do this, I seem to be ending up with 3 statements that would drastically decrease the performance of the site.
I have a site with short stories and tags. This is a HABTM (Has-and-belongs-to-many) relationship between them using a table 'stories_tags'. A story can have multiple tags and a tag can be used by multiple stories.
The goal is listing $tagname ($storycountwiththattag), from highest number of stories per tag, to 10th highest. I have this so far, but it doesn't seem too close.
$tags = $this->Tag->find('all',array('fields'=>array('Tag.name')));
$tags_count = $this->Tag->Story->find('count',array('conditions'=>array('Story.tag'=>$tags)));
debug($tags_count);
I have tried a lot of possible queries. I could do it with restricted find('all')'s, or with:
Getting all ID's of all tags
Running 1 count-query per tag...
Use those results.
But I have picked Cakephp to make better applications so I wondered how you guys would do this! The site gets only a few hundred visitors daily, so performance is not extremely vital, but avoiding extremely dumb queries seems something I should try to do even if some performance penalty wouldn't matter.
use counterCache on your tag (although you can't use with HABTM though, you'll have to define another "Tag hasMany StoriesTag" relationship. You can also Cache the query result.
I make some test in the same scenario but differents ModelNames. I hope you can use it.
function top(){
$options = array(
'fields' => array('*','COUNT(CategoriesEnterprise.enterprise_id) AS num')
, 'group' => array( 'CategoriesEnterprise.category_id' )
, 'order' => 'num DESC'
, 'limit' => '3'
, 'joins' => array(array(
'table' => 'categories',
'alias' => 'Category',
'type' => 'LEFT',
'conditions' => array('CategoriesEnterprise.category_id = Category.id')
))
);
$categories = $this->Category->CategoriesEnterprise->find('all', $options);
debug($categories);
$this->autoRender = false;
}
The result
Array
(
[0] => Array
(
[CategoriesEnterprise] => Array
(
[category_id] => 3
[enterprise_id] => 7
)
[Category] => Array
(
[id] => 3
[name] => Turismo y Viajes
[modified] => 2011-05-16
[created] => 2011-04-14
)
[0] => Array
(
[num] => 4
)
)
[1] => Array
(
[CategoriesEnterprise] => Array
(
[category_id] => 24
[enterprise_id] => 5
)
[Category] => Array
(
[id] => 24
[name] => Compras
[modified] => 2011-05-05
[created] => 2011-05-05
)
[0] => Array
(
[num] => 3
)
)
[2] => Array
(
[CategoriesEnterprise] => Array
(
[category_id] => 32
[enterprise_id] => 8
)
[Category] => Array
(
[id] => 32
[name] => Salud y Belleza
[modified] => 2011-05-16
[created] => 2011-05-16
)
[0] => Array
(
[num] => 3
)
)
)

How do I format the output array in CakePHP

Let's say I have an index action where I want to get a list of projects:
$this->Project->find('all', array('order' => 'Project.modified DESC', 'conditions' => array('Project.user_id' => 1)));
It works well and returns the following array:
Array ( [0] => Array ( [Project] => Array ( [id] => 2 [title] => test project ) ) [1] => Array ( [Project] => Array ( [id] => 1 [title] => first project ) ) )
How do I modify the find function, so it returns the array in the following format:
Array ( [projects] => Array ( [0] => Array ( [id] => 2 [title] => test project ) [1] => Array ( [id] => 1 [title] => first project ) ) )
Thank you!
You could use the Set::combine() utility method to do this. I've used it for similar means as so:
public function groupByMenu() {
return Set::combine (
$this->find (
'all',
array (
'conditions' => array ( 'NavItem.active' => 1 ),
'order' => 'NavMenuItem.display_order'
)
),
'{n}.NavItem.title',
'{n}',
'{n}.NavMenu.id'
);
}
The code above takes a set of navigation items and reorganizes them so that they're grouped by the menu(s) they are displayed within.
It's not really clear if it's the fact that the result is under 'Project' rather than 'projects', but if you don't like that it's under [0] I believe you could use PHPs array_shift:
$result = $this->Project->find('all', array('order' => 'Project.modified DESC', 'conditions' => array('Project.user_id' => 1)));
$result = array_shift($result);
The result will be:
Array ( [Project] => Array ( [id] => 2 [title] => test project ) ) [1] => Array ( [Project] => Array ( [id] => 1 [title] => first project ) )

Cakephp how to use Set Class to make an assoc array?

I have the output array from a $Model->find() query which also pulls data from a hasMany relationship:
Array(
[Parent] => Array
(
[id] => 1
)
[Child] => Array
(
[0] => Array
(
[id] => aaa
[score] => 3
[src] => stage6/tn~4bbb38cc-0018-49bf-96a9-11a0f67883f5.jpg
[parent_id] => 1
)
[1] => Array
(
[id] => bbb
[score] => 5
[src] => stage0/tn~4bbb38cc-00ac-4b25-b074-11a0f67883f5.jpg
[parent_id] => 1
)
[2] => Array
(
[id] => ccc
[score] => 2
[src] => stage4/tn~4bbb38cc-01c8-44bd-b71d-11a0f67883f5.jpg
[parent_id] => 1
)
)
)
I'd like to transform this output into something like this, where the child id is the key to additional child attributes:
Array(
[aaa] => Array
(
[score] => 3
[src] => stage6/tn~4bbb38cc-0018-49bf-96a9-11a0f67883f5.jpg
)
[bbb] => Array
(
[score] => 5
[src] => stage0/tn~4bbb38cc-00ac-4b25-b074-11a0f67883f5.jpg
)
[ccc] => Array
(
[score] => 2
[src] => stage4/tn~4bbb38cc-01c8-44bd-b71d-11a0f67883f5.jpg
)
}
Is there an easy way to use Set::extract, Set::combine, Set::insert, etc. to do this efficiently? I cannot figure it out.
I've used Set::combine to do this a few times, but I can't make an argument for efficiency. As an example, I had a list of volunteers and each of those volunteers belonged to a group. I wanted to retrieve each committee and its volunteers, but as an associative array keyed by the committee name. Here's the code I used to do that:
$volunteers = Set::combine (
$this->Volunteer->Committee->find (
'all',
array ( 'order' => 'display_order' )
),
'{n}.Committee.title',
'{n}.Volunteer'
);
Hopefully that helps. The documentation for Set::combine may help elaborate on the details.
As Rob says, Set::combine is the answer to your question. Here's a sample solution, using the XPath 2.0 syntax:
$parents = $this->Parent->find('all');
$assocChildren = Set::combine( $parents, '/Child/id', '/Child' );

Resources