CakePHP return invalid node - php

I am trying create a webapplication with CakePHP. I am newbie with that but i created a lot lines of code. Now i have to add ACL and now i have a big problem. My foreach loop with if statement call $this->ACL->deny('Group', 'Alias in ARO table') or $this->ACL->allow('Group', 'Alias in ARO table'). Everything is fine and automatic table acos_aros is modified great ... BUT !! i have one alias which generate something like that:
Warning (512): DbAcl::allow() - Invalid node [CORE\Cake\Model\Permission.php, line 182]
I have no idea why. It is 'Podopieczni' when i change to 'Podopieczn' or to 'Podopieczni1' then is working fine without any errors. Anybody can told me why alias 'Podopieczni' generate that error ?
EDIT 1
My bad. I have actually problem with ACO not Aro as said before. When i change alias in ACO table from Podopieczni to Podopieczni1 or something else is working. Alias Podopieczni is generate error.
Here is my code
public function pokaz(){
if ($this->request->is('post')){
$acl['Aro'] = $this->Acl->Aro->find('list', array(
'fields' => array('id', 'alias'),
'conditions' => array(
'parent_id IS NULL'
)
));
$acl['Aco'] = $this->Acl->Aco->find('list', array(
'fields' => array('id', 'alias'),
'conditions' => array(
'parent_id IS NULL'
)
));
foreach($this->request->data['uprawnienia'] AS $pozycja => $uprawnienie){
$t_aco = $acl['Aco'][split('-',$pozycja)[0]];
$t_aro = $acl['Aro'][split('-',$pozycja)[1]];
if($uprawnienie){
//echo 'ALLOW: '.$t_aro.' => '.$t_aco.'<br>';
$this->Acl->Allow($t_aro, $t_aco);
} else {
//echo 'DENY: '.$t_aro.' => '.$t_aco.'<br>';
$this->Acl->Deny($t_aro, $t_aco);
}
}
//$this->redirect(array('controller'=>'admin', 'action' => 'pokaz'));
//$this->render('/admin/pokaz');
//exit;
}
$wynik = $this->Acl->Aco->find('all', array(
'conditions' => array(
'parent_id is null'
)
));
for($a=0; $a<count($wynik); $a++){
$tmp = array();
foreach($wynik[$a]['Aro'] AS $wiersz){
$tmp[$wiersz['foreign_key']] = $wiersz;
}
$wynik[$a]['Aro'] = $tmp;
}
$this->set('wyniki', $wynik);
$this->set('grupy', $this->requestAction('/admin/pobierzGrupy'));
}
SOLVED
In the ACOS table I have two rows with this same alias.
YOU ARE AWESOME noslone. VERY BIG THANKS FOR YOUR TIME AND PATIENCE :)))

That alias does not exist in the aros or acos table.
You should create it first.
For ARO:
$aroData = array(
'id' => NULL,
'model' => 'Group',
'alias' => 'Podopieczni'
);
$this->Acl->Aro->save($aroData);
For ACO:
$acoData = array(
'id' => NULL,
'parent_id' => NULL,//or parent_id?
'alias' => 'Podopieczni'
);
$this->Acl->Aco->save($acoData);
You should read the Documentation, it is explained pretty nice.

Related

Group By within contain cakephp

Hellow , I want to use group by within contain in cakephp. In the following case i want to take only distinct organization within organizationUser array..
$options = array(
'conditions' => array('User.' .$this->User->primaryKey => $userId),
'contain' => array(
'OrganizationUser'=>array(
'conditions'=>['status'=>3],
'group'=> array( 'OrganizationUser.organization_id')),
'OrganizationUser.Organization',
'OrganizationUser.Organization.Noticeboard',
'OrganizationUser.Organization.Newsboard',
'OrganizationUser.Organization.Noticeboard.Branch',
),
'page'=>$page,
'limit'=>$limit
);
$org = $this->User->find('all', $options);
But this is throwing error like 'Column not found', and 'conditions' is working fine within OrganizationUser but 'group' not working.I am using cakephp version 2.Thanks in advance.
I don't think cakephp 2+ offer something like you are doing to make field distinct within contain. So better to try following..
Replace :
'group'=> array( 'OrganizationUser.organization_id')
By
'fields'=> array( 'DISTINCT OrganizationUser.organization_id')
that might work for you.
In my case, I'm using cake version 4+.
In my table the relation I've made
$this->belongsTo('CreatedOperator')
->setClassName(USERS_PLUGIN . '.Users')
->setForeignKey('created_by')
->setJoinType('INNER')
;
and I'm calling the relation like
$query
->disableHydration()
->select([
'CreatedOperator.id',
'CreatedOperator.first_name',
'CreatedOperator.last_name',
'full_name' => $query->func()->concat(['CreatedOperator.first_name' => 'identifier',' ','CreatedOperator.last_name' => 'identifier']),
'total' => $query->func()->count('CreatedOperator.id')])
->contain(['CreatedOperator'])
->group(['CreatedOperator.id'])
;
return $query->toList();

CakePHP display HABTM associations

I'm new to CakePHP and just want to display a list of associated tags in a post's view.
I have searched all over the web and nothing seems to work.
This is what I have at the moment:
// PostController
public function view($id = null) {
$this->set('tags', $this->Post->Tag->find('all', array('conditions' => array('PostTag.post_id' => $id))));
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
$post = $this->Post->findById($id);
if (!$post) {
throw new NotFoundException(__('Invalid post'));
}
$this->set('post', $post);
}
// Post's view.ctp
echo $this->Text->toList($tags);
This is the error I'm getting:
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'PostTag.post_id' in 'where clause'
This should be so easy but I am completely stuck.
Thanks to anyone who can help!
Is the Tag model loaded in your Post controller? How about simply:
$this->set('tags', $this->Tag->find('all', array('conditions' => array('Tag.post_id' => $id))));
Finally! After finding another question here about joining tables and some experimentation, I got it to work.
public function view($id = null) {
$options = array(
'joins' => array(
array('table' => 'posts_tags',
'alias' => 'PostTags',
'type' => 'left',
'conditions' => array(
'Post.id = PostTags.post_id'
)
),
array('table' => 'tags',
'alias' => 'Tag',
'type' => 'left',
'conditions' => array(
'PostTags.tag_id = Tag.id'
)
)
)
,'conditions' => array(
'PostTags.post_id' => $id
)
,'fields' => array(
'Tag.title' // the name of the tag
)
,'recursive' => -1
);
$tagsList = $this->Post->find('all', $options);
// added $result and foreach to ensure that all results would be printed
$result = array();
foreach ($tagsList as $tag):
array_push($result, $tag['Tag']['title']);
endforeach;
$this->set('tags', $result);
// ... rest of the call to find the post info
}
// Post's view.ctp
echo $this->Text->toList($tags);
Before I added $result, it would only print out the first association. I used "echo pr($tags);" in my view and found that the results I wanted were nested inside two arrays. After I added the foreach, it would correctly list all of the assigned tags in my view.

Cakephp $this->request->data returns id of select field instead of value which is needed and shown in the select field

I have a CakePHP controller like this:
$this->loadModel('Project');
$list2 = $this->Project->find( 'list', array(
'fields' => array('Project.project'),
'conditions' => array('Project.user_id' => $userId)
));
$this->set($list2, 'list2');
$this->loadModel('Distance');
if(!empty($this->request->data)){
$this->Distance->create();
if ($this->Distance->save($this->request->data)) {
$this->Session->setFlash('Saved.');
// $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('FAILED');
}
}else{
// $this->Session->setFlash('test');
}
and a view like this:
echo $this->Form->input('Distance.project', array('options' => $list2, 'label' => false, 'empty' => '(choose one)' ;
But I get inserted to the database the id of the project instead of the project name.
I never have such problems working with the fields - just with a list of data.
Any idea why it happens?
It's normal ... The $list2 it's and array ... and the values of the options are the indexes from that array.
If you want to insert only the project name you need to change $list2 with $list2['project_name']. You need to remove or replace the indexes of $list2.
LE: take iexiak example. He change also the code for you.
$list2 = $this->Project->find( 'list', array(
'fields' => array('Project.project'),
'conditions' => array('Project.user_id' => $userId)
)
);
This is because $list2 automatically creates a list of ID => project; and when you use that as input for your form it automatically creates the drop down to reflect this. This is generally the best practice, to link to ID's instead of to descriptions, as ID's do not change as often. The below should get you exactly what you want though:
$list2 = $this->Project->find( 'list', array(
'fields' => array('Project.project','Project.project'),
'conditions' => array('Project.user_id' => $userId)
)
);

Cakephp - Foreach in a controller, how to properly pass the result to view?

This is my first question on stackoverflow so be nice if i'm doing some mistakes. Here's my problem :
I'm working on a messaging system and in my inbox function i want to list every conversations owned by the current logged in user. This is not a problem but then i want, for each conversation, list every users that owns it too (= recipients).
Here is how i'm dealing with it :
function inbox()
{
$conversationIDs = $this->ConversationUser->find('list', array(
'fields' => array('ConversationUser.conversation_id'),
'conditions' => array('user_id' => $this->Session->read('Auth.User.id')),
'recursive' => -1
));
$i = 0;
foreach($conversationIDs as $conversation)
{
$array = $this->ConversationUser->find('first', array(
'fields' => array('ConversationUser.conversation_id', 'ConversationUser.user_id', 'Conversation.subject', 'User.username'),
'conditions' => array('ConversationUser.conversation_id' => $conversation,
'NOT' => array('ConversationUser.user_id' => $this->Session->read('Auth.User.id'))
),
'recursive' => 1
));
$result[$i] = $array;
$i++;
$this->set(compact('result'));
}
}
I'm gathering every conversation's id that the current user owns then "foreach" theses ids to find every users in these conversations.
Actually it is working very fine but i find the solution a bit dirty. Is there a better way to foreach in controller then pass this in view better than this ?
Or maybe my approach is very bad and i should do in a completely other way ?
Edit :
In my Conversation Model :
public function getConversations($userID)
{
$conversationsIDs = $this->ConversationUser->find('list', array(
'fields' => array('ConversationUser.conversation_id'),
'conditions' => array('ConversationUser.user_id' => $userID),
'recursive' => -1,
));
$conversations = $this->find('all', array(
'conditions' => array(
'Conversation.id IN('.implode(",", $conversationsIDs).')'
),
'contain' => array(
'LastMessage' => array(
'User' => array(
'fields' => array('User.username')
)
),
'ConversationUser' => array(
'User' => array(
'fields' => array('User.username')
)
)
)
));
return $conversations;
}
In my Conversation controller :
function inbox()
{
$conversations = $this->Conversation->getConversations($this->Session->read('Auth.User.id'));
$this->set(compact("conversations"));
}
What do you think about it ? Actually it's working really fine for me. :)
The problem about your approach is that it will invoke N+1 queries, where N is the number of conversations. The first query will retrieve the conversation ids, and then for every conversation it will retrieve recipients. You can optimize this by one of the following:
Use Join to retrieve all the conversations and their recipients all at once: http://book.cakephp.org/view/1047/Joining-tables
Use WHERE ConversationUser.user_id IN (id1,id2,id3) sql condition in the second query to retrieve the recipients for all the conversations in a single query.

Cakephp returns empty but sql query has results

I have been fighting with this code:
function getNextActionFObyBalance($when) {
$theQuery = $this->find('first', array(
'fields' => array(
'Contract.id',
'Contract.start_balance'
),
'conditions' => array(
'AND' => array(
'Status.next_action_by' => 'frontoffice',
'Status.status_type' => 'active',
'Status.visibility' => 'frontoffice',
'OR' => array(
'Contract.next_action_on' => null,
'Contract.next_action_on <=' => $when
)
)),
'order' => 'Contract.start_balance DESC',
'recursive' => 0,
));
return $theQuery;
}
I have enabled logging on the MySQL server at this is what the server indicates that CakePHP is requesting:
SELECT `Contract`.`id`, `Contract`.`start_balance` FROM `contracts` AS `Contract` LEFT JOIN `statuses` AS `Status` ON (`Contract`.`status_id` = `Status`.`id`) LEFT JOIN `users` AS `User` ON (`Contract`.`user_id` = `User`.`id`) WHERE ((`Status`.`next_action_by` = 'frontoffice') AND (`Status`.`status_type` = 'active') AND (`Status`.`visibility` = 'frontoffice') AND (((`Contract`.`next_action_on` IS NULL) OR (`Contract`.`next_action_on` <= '2010-09-13 10:13:04')))) ORDER BY `Contract`.`start_balance` DESC LIMIT 1
if I use that in the phpmyadmin tool, I get exactly what I was expecting 1 record with two fields. BUT CakePHP just gives me an empty result set.
Can anyone enlighten me?
PS the code was working but I can figure out what changed!
The problem was with a stub to do some post processing afterFind. The problem is that I have completely forgotten to return $results;
I found the error by doing a step by step debugging down the find method in model.php. Found that the after find was called at some point and went to check my afterFind.
Took my about 4 hours for a simple error but I am learning!
Presumably this method is defined in models/contract.php?
The recursive = 0 statement looks a bit suspect to me. Are the models correctly related in their respective model files?
Have you tried loadModel in case the associations aren't working properly?
It would be useful to see the relationship definitions from the respective models.
--EDIT--
I've formatted the code from your comment here as I can't edit your OP
var $belongsTo = array(
'Status' => array(
'className' => 'Status',
'foreignKey' => 'status_id',
),
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id',
)
);
var $hasMany = array(
'Transaction' => array(
'className' => 'Transaction',
'foreignKey' => 'contract_id',
'dependent' => false,
)
);

Categories