CakePHP 3: How to automatically get fields from leftJoin? - mysql

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.

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'
];

how to id as key in mysql select return

I need return of my mysql query
from
SELECT name as id FROM table
but I need return like this in mysql (I wrote it in an array because it's easy to write)
[
20: 'Jack',//20 is id from table and Jack is name from table
40: 'Nano',
49: 'Hakase'
]
Use WHERE condition
SELECT * FROM table WHERE ID = yourId
just replace yourId for the ID number you want.
First, select all id and name using
SELECT id, name FROM table SOME CONDITIONS
this query would return a result like
$result = [
[ id => 1, name => 'name' ],
[ id => 1, name => 'name' ],
[ id => 1, name => 'name' ],
[ id => 1, name => 'name' ],
]
then arrange array
$accepted_output = array_column($result, 'id', 'name')
$accepted_output = [
[ 1 => 'name' ],
[ 1 => 'name' ],
[ 1 => 'name' ],
[ 1 => 'name' ],
]
array_column docs - https://www.php.net/manual/en/function.array-column.php
You want to return the ID and the name so you should rewrite your query to:
SELECT id,name FROM table
You should use commas to seperate field names.
For more information you can do some reading here.

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.

Query for manytomany relation (also return if empty)

I am building a popover, in which you can tick checkboxes. The options and choices are stored in a manytomany relationship inside a mysql database.
[ ] option A
[x] option B
[ ] option C
There are 3 tables. sphotos, sphoto_feedback and sphoto_has_feedbacks. sphoto_has_feedbacks stores a sphoto_id, a sphoto_feedback_id and a user_id, to reference the user that has submitted the voting.
sphoto
id | status_id | ...
1 | ...
sphoto_feedback
id | name | ...
11 | Quality |
12 | Creative |
sphoto_has_feedbacks
id | sphoto_id | sphoto_feedback_id | user_id
1 | 1 | 11 | 9999
The Input is user_id => 9999 and sphoto_id => 1. The desired output would be an array, which has all sphoto_feedback entrys, with a boolean variable, like this:
$output = [
"0" => [
"id" => 11,
"name" => "Quality",
"checked" => true
],
"1" => [
"id" => 12,
"name" => "Creative",
"checked" => false
]
]
It would look like this:
[x] Quality <-- stored in sphoto_feedback, also stored in sphoto_has_feedbacks with reference to user
[ ] Creative <-- stored in sphoto_feedback
I want to retrieve all the options from the database and check, if the user has already voted on the options or not.
I know how to do it in PHP with 2 querys, but I'd like to use just one query and would like to know if this is possible.
Use a LEFT JOIN to join the sphoto_feedback and sphoto_has_feedback tables, returning NULL for all the rows in the first table that don't have a match in the second table.
SELECT f.id, f.name, shf.id IS NOT NULL AS checked
FROM sphoto_feedback AS f
LEFT JOIN sphoto_has_feedback AS shf
ON f.id = shf.sphoto_feedback_id
AND shf.sphoto_id = 1 AND shf.user_id = 9999

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
)