cakephp Associations Delete not working - cakephp

I have a table of files and a table of permissions. The idea is that the user can assign permissions to other users to allow them to read, edit, etc. I set up an association so that the files, which I call workspaces, have many permissions. Here is the declaration in the workspaces model linking the permissions model
public $hasMany = array(
'Permission' => array(
'className' => 'Permission',
'foreignKey'=> 'workspace_id',
'dependent' => true
)
);
The problem is that when I go to delete a file, I get an error.
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Permission.id' in 'field list'
SQL Query: SELECT `Permission`.`id` FROM `cadwolfc_workspaces`.`permissions` AS `Permission` WHERE `Permission`.`workspace_id` = 71
Why is cakephp looking for an id parameter in the permissions table when I have clearly defined the workspace_id as the foreign key? I had assumed that by linking the models and then deleting a workspace, the associated permissions would be deleted. That is what I am trying to do here. I don't understand why a select query is being executed when a delete query is what is needed?
Update: The call to delete the workspace item is done through an ajax call by passing the id of the workspace. I have confirmed that $fileid is the correct number.
$this->Workspace->delete($fileid);
Update 2: When I add a column to the permissions table titled 'id' add make its value the appropriate number, then the delete call works fine and all items are deleted. Why is this?

Related

Can an aliased query use a contain clause?

I use a union to join two datasets and then the following query to setup for pagination correctly
$paginationQuery = $this->find('all')
->contain(['EmailAddresses' => [
'foreignKey' => false,
'queryBuilder' => function($q) {
return $q->where(['Members__id' => 'EmailAddresses.member_id']);
}
]])
->select( $selectMainUnion )
->from([$this->getAlias() => $query])
->order(['Members__last_name' => 'ASC', 'Members__first_name' => 'ASC']);
I have also tried
$paginationQuery = $this->find('all')
->contain(['EmailAddresses'])
->select( $selectMainUnion )
->from([$this->getAlias() => $query])
->order(['Members__last_name' => 'ASC', 'Members__first_name' => 'ASC']);
and tried
$query->loadInto($query, ['EmailAddresses']); where $query is the result of the union.
Neither of these result in email addresses added to $paginationQuery.
Is there a way to do this?
Adding to clarify the code
$selectMain =['Members.id',
'Members.member_type',
'Members.first_name',
'Members.middle_name',
'Members.last_name',
'Members.suffix',
'Members.date_joined'];
foreach($selectMain as $select) {
$selectMainUnion[] = str_replace('.', '__', $select);
}
$this->hasMany('EmailAddresses', [
'foreignKey' => 'member_id',
'dependent' => true,
]);
Looking at the SQL in DebugKit SQL Log, there is no reference to the EmailAddresses table.
Generally containments do work fine irrespective of the queries FROM clause, whether that's a table or a subquery should be irrelevant. The requirement for this to work however is that the required primary and/or foreign key fields are being selected, and that they are in the correct format.
By default CakePHP's ORM queries automatically alias selected fields, ie they are being selected like Alias.field AS Alias__field. So when Alias is a subquery, then Alias.field doesn't exist, you'd have to select Alias.Alias__field instead. So with the automatic aliases, your select of Members__id would be transformed to Members.Members__id AS Members__Members__id, and Members__Members__id is not something the ORM understands, it would end up as Members__id in your entities, where the eager loader would expect id instead, ie the name of the primary key which is used to inject the results of the queried hasMany associated records (this happens in a separate query), your custom queryBuilder won't help with that, as the injecting happens afterwards on PHP level.
Long story short, to fix the problem, you can either change how the fields of the union queries are selected, ie ensure that they are not selected with aliases, that way the pagination query fields do not need to be changed at all:
$fields = $table->getSchema()->columns();
$fields = array_combine($fields, $fields);
$query->select($fields);
This will create a list of fields in the format of ['id' => 'id', ...], looks a bit whacky, but it works (as long as there's no ambiguity because of joined tables for example), the SQL would be like id AS id, so your pagination query can then simply reference the fields like Members.id.
Another way would be to select the aliases of the subquery, ie not just select Member__id, which the ORM turns into Member__Member__id when it applies automatic aliasing, but use Members.Member__id, like:
[
'Member__id' => 'Members.Member__id',
// ...
]
That way no automatic aliasing takes place, on SQL level it would select the field like Members.Member__id AS Member__id, and the field would end up as id in your entities, which the eager loader would find and could use for injecting the associated records.

delete from database in cakePHP

$this->Attrriskcontrol->deleteAll(
array(
'Attrriskcontrol.assessid'=>'$assess_id',
'Attrriskcontrol.controlid'=>'$control_id'
));
I want to delete where the value is assessid and controlid in the database. How should i put the values in $assess_id and $control_id?
And is this the right query to delete?

CakePHP: Save data in two models

In CakePHP I have two models: Clients & Tickets. A client can have many tickets and a ticket can only have 1 client.
When adding a new ticket I want to automatically create a new client by only entering a name. So the form would be:
Name = "Name client" >> Name should be save in Client table en new client_ID in Ticket table
Info = Ticket information >> Save in Ticket table.
"Save"
I'm not sure how this works. I have associations in the model and tried to saveAll but there is no data stored in the Client table. And how do I get the ID in the Ticket table?
Hope someone can point me in the right direction. I've searched for other answers but cant seem to find a solution. Is saveAll the right way to do this?
You should set a php condition before insert values into the table, the sql request 4 exemple return the numbers of repetition of the same ticket_id so if the returned value is greater than 1 the request can't execute else the request insert the values
The function to count number of rows : mysql_num_rows('request');
You can use the callback methods.
If you have defined your relation in the Ticket model with belongsTo Client, it will be accessible from that model.
public $belongsTo = array(
'Client' => array(
'className' => 'Client',
'foreignKey' => 'client_id',
),
);
So, if you want to make a new client before saving the ticket, you can do:
public function beforeSave ($options = array()) {
$this->data['Client']['name'] = $someVar;
$this->Client->save($this->data);
$this->data[$this->alias]['client_id'] = $this->Client->getInsertID();
return true;
}

ACO alias doesn't work with 'controllers/Controller' value

I am new to ACLs in CakePHP. I believe my Administrator group is set up correctly with full access to the 'controllers' ACO. However I get an error when I try to go to any controller or action that is not explicitly made public.
Warning (512): DbAcl::check() - Failed ARO/ACO node lookup in permissions check. Node references:
Aro: Array
(
[User] => Array
(
[id] => 9
[email] => Admin
[group_id] => 3
[is_active] => 1
[created] => 2013-04-08 07:59:52
[modified] => 2013-04-08 07:59:52
[Group] => Array
(
[id] => 3
[name] => Administrators
[user_count] => 2
[created] => 2013-04-08 06:34:58
[modified] => 2013-04-08 06:34:58
)
)
)
Aco: controllers/Users/index [CORE/Cake/Model/Permission.php, line 94]
In my acos table there is an entry for 'controllers/Users/index' as the alias. This entry has a parent_id that references 'controllers/Users', which in turn has a parent_id which references 'controllers'.
There is only one entry in my 'aros_acos' table that is granting full permission to the Administrators group.
Based on the error above I did a little digging and found that if I directly try to call $this->Acl->Aco->node('controllers/Users/index'); the returned value is false. But if I do the same query on $this->Acl->Aco->node('controllers'); the returned value is the correct array.
Something is clearly not functioning properly but I can't figure out where I am going wrong. I have been digging in the Documentation Book and API all day and have not found any reason why 'controllers/Users/index' isn't found but 'controllers' is. At this point it seems like it has something to do with the / character but I don't know why. I used the same string when adding the Aco and it saved correctly.
Thanks!
I found the problem by installing the ACL Plugin at:
http://www.alaxos.net/blaxos/pages/view/plugin_acl_2.0
After running this great utility I found that I was incorrectly adding my ACOs with the fill path in the alias. It turns out the alias is just the action or controller name and based on the parent_id's it finds the correct path.
This is not very well documented in the CakePHP Documentation, but what else is new.
Example:
I was adding 'controllers/Users/index' instead of 'index'.
Hope this can help someone else solve this problem! I wasted an entire day on it.

CakePHP help with read()

I am following the blog tutorial and modifying it to fit my site's needs. I am having a little trouble with my view function.
function view($id = null)
{
$this->Article->articleid = $id;
$this->set('article', $this->Article->read());
}
This line does not work, I get this error: Warning (512): SQL Error: 1054: Unknown column 'Article.id' in 'where clause' [CORE/cake/libs/model/datasources/dbo_source.php, line 681]
However, I got it to work with $this->set('article', $this->Article->find('first' , array('conditions' => array('Article.articleid' => $id))));
My schema for articles is
articleid
userid
title
text
The query has WHERE Article.id = '1'
however, thats wrong. It should be articleid instead of id
Anyway I can change this so I could use read()?
Have you specified inside the Article model that var $primaryKey = 'articleid'; ?
From the documentation:
Each table normally has a primary key, id. You may change which field name the model uses as its primary key. This is common when setting CakePHP to use an existing database table.

Resources