Join table without id as column name - Cakephp 3 - cakephp-3.0

I have a big problem, I don't know how to join a table without passing '_id' as the referenced column name and also including multiple tables who do not have this constraint.
For example, I want to join A.code = B.code_defaut
I tried both methods :
$cycle = $this->Cycles->find('all')
->where(['Cycles.id'=>$id])
->contain(['Quais',
'Defauts',
'Traces'])
->join([
'ReferentielTraces'=>[
'table'=>'referentiel_traces',
'type'=>'LEFT',
'conditions'=>'ReferentielTraces.code = Defauts.code_defaut'
]
]);
$cycle = $this->Cycles->find('all')
->where(['Cycles.id'=>$id])
->contain(['Quais',
'Defauts',
'Traces',
'Defauts.ReferentielTraces']);
But in the first case I have this problem (yes sorry it's french ^^ ):
Error: SQLSTATE[42P01]: Undefined table: 7 ERREUR: entrée manquante de la clause FROM pour la table « defauts » LINE 1: ...ces ReferentielTraces ON ReferentielTraces.code = Defauts.co... ^
which means " missing entry of the FROM clause for the table "Defauts".
And in the second case I have this:
Error: SQLSTATE[42883]: Undefined function: 7 ERREUR: l'opérateur n'existe pas : integer = character varying LINE 1: ..._traces ReferentielTraces ON ReferentielTraces.id = (Defauts... ^
which means "we can't compare integer and character varying " as they are trying to compare ReferentielTraces.id and Defauts.code_defaut
I also tried to make a group of join like join([firstTable, secondTable ...]). But I have no datas for Defauts, Traces, Quais and ReferentielTraces.
Here is the relationship between tables:
Cycles:
//Quais.id = Cycles.quai_id
$this->belongsTo('Quais', [
'foreignKey' => 'quai_id'
]);
//Defauts.cycle_id = Cycles.id
$this->hasMany('Defauts', [
'foreignKey' => 'cycle_id'
]);
//Traces.cycle_id = Cycles.id
$this->hasMany('Traces', [
'propertyName'=>'Traces',
'foreignKey' => 'cycle_id',
]);
Defauts:
//Defauts.code_defaut = ReferentielTraces.code
$this->belongsTo('ReferentielTraces',[
'className'=>'ReferentielTraces',
'foreignKey' => 'code_defaut'
]);
Could you help me please?

You can use bindingKey , which will be something similar to the following :
//Defauts.code_defaut = ReferentielTraces.code
$this->belongsTo('ReferentielTraces',[
'className'=>'ReferentielTraces',
'foreignKey' => 'code_defaut',
'bindingKey' => 'code'
]);

Related

How to have relationship in Laravel 5.7 based on a json data key saved in a table column?

I am using this Staudenmein package in Laravel and referring to this answer given by the package owner himself.
I have two tables, pets and notifications with models Pet and Notification.
The notifications table has a column called data which is of JSON dataType and stores JSON data
{"pet_id":"4","pet_type_id":1,"lost_report_id":3,"pet_sighting_id":21,"latitude":"22.676846","longitude":"88.338509"}
The key pet_id denotes the id column of the pets table. I need a relationship so that I can fetch the name of the pet from pets table.
By referring to the answer link given above, I wrote my Notification model like this:-
namespace App\Models;
use DB, App, Auth, Hash, Lang, Mail, Config, Exception, Validator, Globals;
use Illuminate\Database\Eloquent\Model;
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
use App\User;
use App\Models\AdminConfig;
use App\Models\ReceivedAppNotification;
class Notification extends Model
{
protected $casts = [
'data' => 'json'
];
public function notificationPet()
{
return $this->belongsTo('App\Models\Pet', 'data->pet_id');
}
}
When I am running the query like this:-
$notificationQuery = Notification::with('notificationPet')
->whereRaw("FIND_IN_SET('$userId', in_app_notification_receiver)")
->where(array(
'status' => Globals::SMALL_CHAR_ACTIVE,
'is_delete' => Globals::SMALL_CHAR_NO,
))->get()->toArray();
I get the notificationPet relationship as empty, ie. the data-set is like this:-
Array
(
[id] => 10
[title] =>
[message] =>
[data] => Array
(
[pet_id] => 4
[latitude] => 22.676846
[longitude] => 88.338509
[pet_type_id] => 1
[lost_report_id] => 3
[pet_sighting_id] => 34
)
[no_of_in_app_notification_receiver] => 2
[no_of_push_notification_receiver] => 1
[from_user] => 22
[in_app_notification_receiver] => 2,23
[push_notification_receiver] => 2
[status] => a
[is_delete] => n
[push_notification_sent] => n
[created_date] => 2020-03-19 13:23:17
[modified_date] => 2020-03-19 13:23:17
[created_at] => 2020-03-19 13:23:17
[updated_at] => 2020-03-19 13:23:17
[notification_pet] =>
)
However, I have a record in pets table with id = 4, already. So the relationship should not be empty.
What am I doing wrong?
Change:
protected $casts = [
'data' => 'json'
];
To:
protected $casts = [
'data' => 'array'
];

Cakephp3 multiple join table by Model

I have problem with my code. At this moment I have code view like this:
...Table.php
public function containBasic(){
return [
//Keywords
'CandidatesKeywords',
'CandidatesKeywords.Keywords',
//User
'CandidatesUser',
'CandidatesUser.User',
];
}
...Controller.php
$this->loadModel('Candidates');
$candidates = $this->Candidates->find()
->contain($this->Candidates->containBasic())
->where([
'CandidatesKeywords.Keywords.id'=>5
])
->all();
I include all other Models via contain. This method its works but when I try to search data in this code I have error like:
Unknown column 'CandidatesKeyword.id' in 'where clause
I don't know, how I can get column CandidatesKeywords -> Keywords -> Id from database :/
When I get (debug) all rows without where condition I get data like this:
'items' => [
(int) 0 => object(Cake\ORM\Entity) {
'id' => (int) 4,
.........
,
'candidates_user' => null,
'candidates_keyword' => object(App\Model\Entity\CandidatesKeyword) {
'id' => (int) 1,
..................
'keyword' => object(App\Model\Entity\Keyword) {
'id' => (int) 5,
.............
And I need to get rows with only keyword.id = 5.

cakephp query find_in_set on single column with multiple searched keywords not working

I want to find all the records from column who have any keyword match with column data:
It works fine if searching single search keyword in column having comma separated values like below code: Cakephp 3.4 version
$posts = TableRegistry::get('Posts');
$search_keywords = array_filter(explode(' ', $search_string));
$option = [
'contain' => false,
'conditions' => [
"find_in_set('New', Posts.title)",
],
'order' => ['Posts.created DESC']
];
$allpost = $posts->find('all',$option)->toArray();
Note: i want all the words from string should be search with column title, its not mandatory to have comma separated records:
$search_keyword = "New car in new delhi";
so i want code to be like below :
$search_keyword = "New car in new delhi";
$search_keywords = array_filter(explode(' ', $search_string));
$option = [
'contain' => false,
'conditions' => [
"find_in_set({$search_keywords}, `Posts`.title)",
],
'order' => ['Posts.created DESC']
];
$allpost = $posts->find('all',$option)->toArray();
Great Thanks in advance!!!
I found the solution:
First make column fulltext index then add below code:
$search_string = "New car in new delhi";
$option = [
'contain' => false,
'conditions' => [
"MATCH (title) AGAINST ('$search_string')"
],
'order' => ['Posts.created DESC']
];
$allpost = $posts->find('all',$option)->toArray();

CakePHP 3: How to automatically get fields from leftJoin?

I have two tables. Cars and tires. Tires can(!) belong to a car. My tables looks like:
Tires:
id | car_id
-------------
1 | 17
2 | NULL
Cars:
id | name
-------------
17 | BMW
18 | Mercedes
From my understanding, if I want to get all(!) tires (including the car they belong to, if available) I can't create a inner join (so I can't use contain). I need to use a left join. But that way I have no idea how to automatically select all fields on table cars.
Query I do:
$query = $this->Tires->find('all');
$query->leftJoin(
['Cars' => 'cars'],
['Cars.id = Tires.car_id']
);
// brings this SQL query
SELECT Tires.id AS `Tires__id`, Tires.car_id AS `Tires__car_id`
FROM tires Tires
LEFT JOIN cars Cars ON Cars.id = Tires.car_id
But how do I automatically get all fields from cars as well?
UPDATE
burzum actually gave me the solution which I quickly want to detail out since I don't think it is well solved by cake...
In order to achieve what I tried to do, I need to add the following code:
$query
// you need to pass each model you want to get fields for
->select($this->Tires)
->select($this->Tires->Cars);
The car in its tire looks like this:
...
'Cars' => [
'id' => '17',
'name' => 'BMW'
]
...
If I did a contain, it would look like this:
...
'car' => object(App\Model\Entity\Car) {
'id' => (int) 17,
'name' => 'BMW',
'[new]' => false,
'[accessible]' => [
'*' => true
],
'[dirty]' => [],
'[original]' => [],
'[virtual]' => [],
'[errors]' => [],
'[invalid]' => [],
'[repository]' => 'Cars'
}
...
So, I can work with that. Still, I don't understand the different output...
http://book.cakephp.org/3.0/en/orm/query-builder.html#selecting-all-fields-from-a-table
Example taken from the above URL:
// Only all fields from the articles table including
// a calculated slug field.
$query = $articlesTable->find();
$query
->select(['slug' => $query->func()->concat(['title', '-', 'id'])])
->select($articlesTable); // Select all fields from articles
So in your case you need to pass an instance of the cars table to a select() call.

foreignKey in model based on condition in cakephp

I am struck with one issue related to foreignKey concept.
I have two table users & user_relations.
users user_relations
id username id user_id friend_id status
1 abc 1 1 2 Accepted
2 def 2 2 3 Accepted
3 ghi 3 1 3 Accepted
here the friend_id is the foreign_key and my user_relations model looks like
public $belongsTo = array(
'Friend' => array(
'className' => 'User',
'foreignKey' => 'friend_id'
)
);
My conditions will be like
'conditions' => array(
"OR" => array(
'UserRelation.user_id' => $iLoggedUserId,
'UserRelation.friend_id' => $iLoggedUserId,
),
'ViewerRelationship.status' => 'Accepted'
)
Now when user "1" is logged in then he will get the info of users "2" & "3" based on foreignKey friend_id.
If user "2" gets logged in then, he is getting the info of users "2" & "3". But here I need to get the info of users "1" & "3". i.e., in one case it need to take the info based on the user_id not the friend_id
If I can keep the foreignKey in a condition I can get the result based on user_id or friend_id.
Any help please..!
I dont know how it is effective for you.
But it will solve your problem.
$respone = $this->UserRelation->find('all',
array('conditions'=> array(
'OR'=>array(
'UserRelation.user_id' => $iLoggedUserId,
'UserRelation.friend_id' => $iLoggedUserId
)
),
'fields' => array('UserRelation.*')
));
$reqFriendsId = array();
foreach($respone as $key => $val){
if($val['UserRelation']['friend_id'] == $iLoggedUserId){
array_push($reqFriendsId, $val['UserRelation']['user_id']);
}else{
array_push($reqFriendsId, $val['UserRelation']['friend_id']);
}
}
//For logged in user 1
Array
(
[0] => 2
[1] => 3
)
//For logged in user 2
Array
(
[0] => 1
[1] => 3
)