How to disambiguate column names in yii MANY_MANY relation - activerecord

I have a nice case of folder and item in the folder. All mysql is abbreviated for clarity.
CREATE TABLE folder
folder_id INT,
name VARCHAR(32),
sort_weight INT
CREATE TABLE item
item_id INT,
name VARCHAR(32)
and of course the linking table
CREATE TABLE item_folder
folder_id INT,
item_id INT,
sort_weight INT
As you might have guessed one item can be in more than one folder (sort of like hard links in linux file system) and notice that folder has sort_weight too becuase it can be sorted inside another folder. Now I am using Yii and I have a nice relation in Item model like this:
public function relations()
{
return array(
'folderitems' => array(self::MANY_MANY, 'Folder', 'item_folder(item_id, folder_id)'),
);
}
The problem is that when I try to make some nice AR request and I try to sort it I have a problem. My AR request:
$items = Item::model()->with(array(
'folderitems' => array(
'condition' => "folderitems.folder_id = $someid"
),
))->findAll(array('order'=> "folderitems.sort_weight"));
Now the problem is, that with syntax like this, instead of sorting by item_folder.sort_weight it sorts by folder.sort_weight.
If I change the name of the field to say item_folder.sort_weight2 and try:
[...] ))->findAll(array('order'=> 'sort_weight2'));
it works.
However if I keep both names the same and try
[...] ))->findAll(array('order'=> 'item_folder.sort_weight'));
it says unknown column.
So the question is - how to disambiguate it correctly.

try
[...] ))->findAll(array('order'=> 't.sort_weight'));
http://www.yiiframework.com/doc/guide/1.1/en/database.arr#disambiguating-column-names
"When a column name appears in two or more tables being joined together, it needs to be disambiguated. This is done by prefixing the column name with its table's alias name.
In relational AR query, the alias name for the primary table is fixed as t, while the alias name for a relational table is the same as the corresponding relation name by default."

Related

I get duplicate entries with the attach method in Laravel 5. Not sure what the problem is

So I'm trying to attach id's with some meta data to a pivot table in Laravel 5.
For some reason, I get the two inserts where there should be one, and the wrong ID's being inserted the second time round.
I'm not sure if there is something I might be missing here.
This is the code:
$match_values = array(
'dataId' => $result->id,
'dataMetaId' => $the_meta->id
);
$result->campaignDataMeta()->attach($match_values, [
'meta_value' => $value
]);
The database structure consists of a main campaignData table for email campaigns, a campaignDataMeta table (id, timestamps, name) for email meta data names, and a lookup table campaignDataMatches (id, campaignDataId, campaignDataMetaId, meta_value).
In campaignDataMatches I get the campaignDataId value sometimes being inserted into the campaignDataMeta column.
I've solved the problem.
Apparently had to add the relevant ID (in this case the dataMetaId) within the attach parameter.
Like this:
$result->dataMeta()->attach([$data_meta_id => [
'meta_value' => $value
]]);
Check the database columns primary maybe the dataId and metaId are both primary.

cakebake not working with prefix in cakephp3

I am using cakephp 3.4.9. When I am using a table with prefix n field its working properly after baking but if I use prefix in table fields its not working.
Like when I am using post with following fields like
id,
post,
date
it's working fine but if I use following fields its not working
p_id,
p_post,
p_date
it is adding extra codes in model
$this->belongsTo('Ps', [
'foreignKey' => 'p_id',
'joinType' => 'INNER'
]);
public function buildRules(RulesChecker $rules)
{
$rules->add($rules->existsIn(['p_id'], 'Ps'));
return $rules;
}
why ps is adding here? If I use articales table like same its become As.
Please help.
I would like to suggest you, read this article.
CakePHP naming convention documentation
In cakePHP framework everything you have to keep in mind while creating the table is the CakePHP naming conventions. In your case, This is happening because cakePHP expects the primary column of any table will be only 'id', and the foreign key for the table will be the Related table name with an underscore id
(ex: If product table BelogsTO categories you have to make a column in your product table as category_id)
In your case cakePHP considering p_id as a foreign key for the table P. And by default cakePHP has a validation for the forein key that the existsIn which means that while saving that p_id, it will check for the existance of id in P table.
In one sentense this is because of the naming convention issue. You can change only p_id to id and keeping other things same will work for you.
HAPPY CODING :)

Drupal 7 | Query through multiple node references

Let me start with structure first:
[main_node]->field_reference_to_sub_node->[sub_node]->field_ref_to_sub_sub_node->[sub_sub_node]
[sub_sub_node]->field_type = ['wrong_type', 'right_type']
How to efficiently query all [sub_sub_node] ids with right_type, referenced by main_node (which is current opened node)?
Doing node_load on foreach seems a bit of overkill for this. Anybody has some better solutions? Greatly appreciated!
If you want to directly query the table of the fields:
$query = db_select('node', 'n')->fields('n_sub_subnode', array('nid'));
$query->innerJoin('table_for_field_reference_to_sub_node', 'subnode', "n.nid = subnode.entity_id AND subnode.entity_type='node'");
$query->innerJoin('node', 'n_subnode', 'subnode.subnode_target_id = n_subnode.nid');
$query->innerJoin('table_for_field_ref_to_sub_sub_node', 'sub_subnode', "n_subnode.nid = sub_subnode.entity_id AND sub_subnode.entity_type='node'");
$query->innerJoin('node', 'n_sub_subnode', 'sub_subnode.sub_subnode_target_id = n_sub_subnode.nid');
$query->innerJoin('table_for_field_type', 'field_type', "n_sub_subnode.nid = field_type.entity_id AND field_type.entity_type='node'");
$query->condition('n.nid', 'your_main_node_nid');
$query->condition('field_type.field_type_value', 'right_type');
Here is the explanation of each line:
$query = db_select('node', 'n')->fields('n_sub_subnode', array('nid'));
We start by querying the base node table, with the alias 'n'. This is the table used for the 'main_node'. The node ids which will be returned will be however from another alias (n_sub_subnode), you will see it below.
$query->innerJoin('table_for_field_reference_to_sub_node', 'subnode', "n.nid = subnode.entity_id AND subnode.entity_type='node'");
The first join is with the table of the field_reference_to_sub_node field, so you have to replace this with the actual name of the table. This is how we will get the references to the subnodes.
$query->innerJoin('node', 'n_subnode', 'subnode.subnode_target_id = n_subnode.nid');
A join back to the node table for the subnodes. You have to replace the 'subnode_target_id' with the actual field for the target id from the field_reference_to_sub_node table. The main purpose of this join is to make sure there are valid nodes in the subnode field.
$query->innerJoin('table_for_field_ref_to_sub_sub_node', 'sub_subnode', "n_subnode.nid = sub_subnode.entity_id AND sub_subnode.entity_type='node'");
The join to the table that contains references to the sub_sub_node, so you have to replace the 'table_for_field_ref_to_sub_sub_node' with the actual name of the table. This is how we get the references to the sub_sub_nodes.
$query->innerJoin('node', 'n_sub_subnode', 'sub_subnode.sub_subnode_target_id = n_sub_subnode.nid');
The join back to the node table for the sub_sub_nodes, to make sure we have valid references. You have to replace the 'sub_subnode_target_id' with the actual field for the target id from the 'field_ref_to_sub_sub_node' table.
$query->innerJoin('table_for_field_type', 'field_type', "n_sub_subnode.nid = field_type.entity_id AND field_type.entity_type='node'");
And we can now finally join the table with the field_type information. You have to replace the 'table_for_field_type' with the actual name of the table.
$query->condition('n.nid', 'your_main_node_nid');
You can put now a condition for the main node id if you want.
$query->condition('field_type.field_type_value', 'right_type');
And the condition for the field type. You have to replace the 'field_type_value' with the actual name of the table field for the value.
Of course, if you are really sure that you always have valid references, you can skip the joins to the node table and directly join the field tables using the target id and the entity_id fields (basically the target_id from on field table has to be the entity_id for the next one).
I really hope I do not have typos, so please check the queries carefully.

Laravel 4 how to set up many-to-many relationship with the same table

I have a resources table set up in the following way:
resources
id - integer, pk
name - string
description - string
type_id - integer, fk
...
My goal is to set up a many-to-many relationship between the items in the same table. So when a user is viewing one resource they will also be able to see all the other resources that are linked to it.
I'm assuming I will need to set up a pivot table, something like ...
resource_links
id - integer, pk
id_left- integer
id_right - integer
Then I can set up a query scope to select entries from the pivot table where id_left or id_right is equal to the resource's id, and return all rows from the resources table where id_left/right is not equal to the current resource's id.
What is the best way to do what I want?
UPDATE:
My resources table also has a column to define what type of resource it is. Is it possible, using the belongsToMany relation, to retrieve only those linked resources that are of a specific type?
What about
resources
id - integer
name - string
description - string
resource_links
id - integer
resource_id - integer
linked_resource_id - integer
This makes it a bit clearer to anyone looking at the pivot what it is doing. Then you can retrieve the linked resources for a given resource ($resource_id below) with something like
$linked_resources = DB::table('resources')
->join('resource_links', 'resources.id', '=', 'resource_links.linked_resource_id')
->where('resource_links.resource_id', '=', $resource_id)
->get();
Edit:
Or you could add a many to many relationship on the model back to itself
public function linkedResources()
{
return $this->belongsToMany('Resource', 'resource_links', 'resource_id', 'linked_resource_id');
}
And then return the linked resources with
Resource::find(1)->linked_resources;
Edit:
If you wanted to limit the linked resources by type something like the following is one approach
$linked_resources = Resource::with(array('linkedResources' => function($query) {
$query->where('type', '=', 'book');
}))->where('id','=',1)->get();

Sequel Migration update with a row's ID

How can you run a Sequel migration that updates a newly added column with a value from the row?
The Sequel documentation shows how you can update the column with a static value:
self[:artists].update(:location=>'Sacramento')
What I need to do is update the new column with the value of the ID column:
something like:
self[:artists].each |artist| do
artist.update(:location => artist[:id])
end
But the above doesn't work and I have been unable to figure out how to get it to go.
Thanks!
artist in your loop is a Hash, so you are calling Hash#update, which just updates the Hash instance, it doesn't modify the database. That's why your loop doesn't appear to do anything.
I could explain how to make the loop work (using all instead of each and updating a dataset restricted to the matching primary key value), but since you are just assigning the value of one column to the value of another column for all rows, you can just do:
self[:artists].update(:location=>:id)
if you need update all rows of a table, because it is a new column that need be populate
artists = DB[:artists]
artists.update(:column_name => 'new value')
or if you need, update only a unique row into your migration file you can:
artists = DB[:artists]
artists.where(:id => 1).update(:column_name1 => 'new value1', :column_name2 => "other")

Resources