I have a db structure like this in MySql. And I use Cake PHP 3.5.
I wolud like to add to table1 a belongsToMany connection to table4. And add its inverse to table4 too.
$this->belongsToMany('Table4', /*What goes here*/);
And what is for table4?
Can I make this Join with a finder in the belongsToMany?
Thanks!
As ndm said in comments Cake does not suport what you want to do, just for a reason, this is not a many to many relation, please create you database by migrations, first of all https://book.cakephp.org/3.0/pt/migrations.html after that (bake migration, execute migration) your database will exist, the you can run a bake for create models, then you will realize that you can build a query like
$this->table1->table2->table3->table4->find()->where([conditions]);
or another like
$this->table1->find()->contain(['table2' => ['table3' => ['table4' => 'conditions' => ['RealConditions']]]])->first();
If you don't want to learn all of this you can go throught the paintfull path. Or just read about it first https://book.cakephp.org/3.0/en/orm/associations.html#belongstomany-associations
Related
I've created migrations and also their relationships. looks like I'm using polymorphic relations, because in one table, I could have the value of one model or i could have the value of another model. as you might guess, I have something like this
ID Mappable_type Mappable_id value
Mappable_type could be one or many other models. mappable_id will be appropriate id from that model. I needed this because I'm creating dynamic form builder and that's how I designed a database.
Now I need to fetch some records from 5 tables together, so I gotta use joins. the table where I have mappable_type is at the third place from those 5 joins. now What should I do also to only fetch data from these 5 joins that have specific model type that is in that morph table? I'm doing something like that for now:
$final = Dynamic::join('dynamic_properties_values','dynamic_properties_values.dynamic_id','=','dynamic.id')
->join('dynamic_properties_mapping','dynamic_properties_mapping.id','=','dynamic_properties_values.mapping_id')
->where('dynamic_properties_mapping.mappable_type','=','App\Driver')
->get();
As you see, I have written by hand something like
"App\Driver"
. It doesn't matter I have written it by hand or had it saved into a variable and than used it here. WHat really bothers me is that let's say when I was inserting data into these morph tables, Model got saved as "App\Driver". what if I make a mistake and when fetching with joins, I write something like App\Http\Driver? or what If I changed the location of the model itself in my code project?
What's the best practice not to make those kind of errors by the time my project reaches huge amount of users?
I'm using cakephp. In some query I use these kind of find:
$this->Photo->Behaviors->attach('Containable', array('autoFields' => true));
This is the Contain array that i use in the find:
'contain'=>array(
'User'=>array('fields'=>array('User.Name','User.Username')),
'Like' => array('User'=>array('fields'=>'Name'),
'order'=>'Timestamp DESC'
)),
'recursive' => 2,
The problem is that every time i want the Name of User that liked a photo. Cakephp does this query.
For example: SELECT `User`.`Name` FROM `Users` AS `User` WHERE `User`.`id` = 2175
If i have 300 likes on one photo i will make another 300queries for the User.Name. So, I would like to cache this kind of request. I've installed memcache correctly in my server, it's working normally. But I can't find a way to cache the query that cake make with the Containable Behaviors.
Has some one had this problem?
Thanks
G.
Why not use cakephp's counterCache feature instead?
There is a lot of documentation in the cakephp book about caching queries not just in me cache but many other ways as well such. Check out the CakeCache class.
there are a number of approaches on this topic.
if it is only about belongsTo relations it boils down to manually join tables using bindModel().
here is a good behavior: http://planetcakephp.org/aggregator/items/891-linkable-behavior-taking-it-easy-in-your-db
it takes care of that itself.
What is the proper way to delete rows from several tables in one query?
The reason I ask is because I am doing this with PHP. If I use multiple queries to delete from each table one at a time, PHP has to make multiple trips to the database. Will there be any effect on performance if I used this method?
I am aware of the ON DELETE CASCADE option, but this does not work on every storage engine. Also, there may be situations where I do not want to remove all of the records from the child tables when I delete the parent record.
DELETE
t1, t2
FROM
table1 AS t1 INNER JOIN table2 AS t2
ON
joinCondition
WHERE
whereCondition
As usual with DELETE queries: be very careful
More details here: http://dev.mysql.com/doc/refman/5.5/en/delete.html
If you don't know the answer to this question, then you shouldn't be trying to support numerous RDMS's for your application. To put bluntly. The CASCADE option is available in like every relational db that matters. Also, you should consider looking at how to store hierarchical data, to delete child records.
For example, if you were trying to delete all "files" in a "folder" when using Nested Set Model, it would simply be a matter of
DELETE from files where id > :lft and id < :rgt
But, in any case, you can still delete from multiple tables, by using JOIN deletes. However, this is not support by a lot of RDMS, so if you are worried about using cascade, then you are never going to be able to use join deletes accross every database, even if you use a DBAL.
The Answer
Use a DBAL, such as Doctrine DBAL (not the ORM), and use Cascades where supported.
Pick a single database, and develop with what you know on that.
I was also once faced with a similar problem. My solution was to write my own min-recusive query. Just one query and it does the rest for you. Here is how it goes:
//main function
function factory($db){ $table=array('table1', 'table2', 'table3'...);
//mine went all the way to table 12 for($i=0;
$i<''sizeof($table); $i++){ delete($db, $table[$i]); } }
//delete function.. could as well setit up withn the factory function but 4 undestanging sake
delete($db, $table){
$sql='delete from '.$table; if($db->query($sql)){ echo
ucfirst($table).' delete completed 100%';
}
}
Thats all... to make work for non-predefined insert array, crete a varible to hold the array size from your data entry page and change the delete to 'insert into table' prepare statement and execute.
Hope it has helped you in some way
convert following query into cakephpquery.
"SELECT * FROM user1.user_favourites,esl.esl_lyrics
WHERE
esl_lyrics.id=user_favourites.fav_recordID
AND user_favourites.fav_userID=".$user_id."
AND user_favourites.fav_widgetID=$wid_id";
Models files are esl.php and userFavourite.php
DB are user1 and esl.
DB tables are user_favourites in user1 and esl_lyrics in esl DB.
plz give details.what changes are do in esl.php and userFavourite.php
please Help me...
It will be difficult to determine what to write until you can provide a data map for the various IDs you are using. Since you are not conforming to standards in your SQL, the fields are all named different in the various tables. But here is what I understand so far:
esl_lyrics.id = user_favorites.fav_recordID
From your description there are two models. So you will need to make sure you have relationships between the two. This will require that you determine if it is belongsTo, hasOne, hasMany, etc.
It also appears you are using multiple databases (schemas), so you will need to configure the database.php so that you can access each one.
Once everything is configured you should be able to access the data as:
$this->Model1->Model2->find('all', array('conditions' => array('Model1.id' => 'Model2.id', 'Model2.user_id' => $user_id, 'Model2.widgetID' => $wid_id)));
It will return an array with the data from both models. But until you can share what your models look like and a mapping of ids etc., this will be as good of an answer as you will get.
I have the following relationships set up:
A HABTM B
B belongsTo C
C hasMany B
Now, for a given A, I need all C with the B's attached. I can write the SQL queries, but what's the proper CakePHP way? What method do I call on which model, and with which parameters?
I'd go with Aziz' answer and simply process the data as it comes in. If you need C to be your primary model though, you'll have to do a little workaround. Cake is not terrifically good with conditions on related models yet, especially on removed 3rd cousins kind of queries. It usually only does actual JOIN queries on belongsTo or hasMany relations; not on HABTM relations though, those it gets in separate queries. That means you can't include conditions on related HABTM models.
Your best bet then might be something like this:
// get related records as usual with the condition on A, limit to as little data as necessary
$ids = $this->A->find('first', array(
'conditions' => array('A.id' => 'something'),
'recursive' => 2,
'fields' => array('A.id'),
'contain' => array('B.id', 'B.c_id', 'B.C.id') // not quite sure if B.C.id works, maybe go with B.C instead
));
// find Cs, using the ids we got before as the condition
$Cs = $this->C->find('all', array(
'conditions' => array('C.id' => Set::extract('/B/C/id', $ids)),
'recursive => 1
);
Note that this produces quite a bunch of queries, so it's not really an optimal solution. Writing your own SQL might actually be the cleanest way.
EDIT:
Alternatively, you could re-bind your associations on the fly to make them hasMany/belongsTo relationships, most likely using the join table/model of A and B. That might enable you to use conditions on related models more easily, but it's still tricky to fetch Cs when the condition is on A.
$this->A->find(
'first',
array('conditions'=>array('id'=>'someword'),
'recursive'=>2)
);
like this?
this might work
$this->C->find('all',
array('conditions'=>array('id'=>'someword','B.aid'=>$a.id)));
I'd think of "Containable" behaviour (http://book.cakephp.org/view/474/Containable)... gives a lot control on finding related data.