Limit fields in result of Propel v2 query with left join - php

I'm using Propel ORM v2 to retrieve records from a table which is linked to records of another table using foreign key. I'd like to return only certain fields from both the parent table and the child table.
What is the best way to do this?
My table structure looks like this:
Table: User
- Id
- Name
- Age
- MaritalStatus
Table: Profile
- UserId (FK->User.Id)
- Street
- City
- State
- Country
- TelephoneNumber
I have tried the following but the query does not return the desired User object with children Profile objects and only the selected fields of Id, Name for the User object and TelephoneNumber for the Profile child objects:
\UserQuery()::create
->select(array('Id', 'Name', 'Profile.Telephonenumber'))
->leftJoinWithProfile()
->find()
->toArray();
Any advise is greatly appreciated

just took a quick look over Propel.
This select returns what you have asked for, ('Id', 'Name', 'Profile.Telephonenumber').
\UserQuery::create()
->join('Profile')
->select(array('Id', 'Name', 'Profile.Telephonenumber'))
->find()
->toArray();
//returns an array with values for 'Id','Name', 'Profile.Telephonenumber'
If you want all the entries of the 'User' table and entries from 'Profile' as a child array try this:
\UserQuery::create()
->join('User.Profile')
->find()
->toArray();
//returns an array with all the entries from 'User' table and an child array with entries from 'Profile' table.
Sorry if i made any mistakes, is my first answer on Stackoverflow.
Have a nice day,
M.I.

You should probably use withColumn(), e.g.
\UserQuery()::create()
->leftJoinWithProfile()
->withColumn('Profile.TelephoneNumber', 'TelephoneNumber')
->select(['Id', 'Name', 'TelephoneNumber'])
->find()
->toArray();

Related

Laravel: How to subselect two columns from another table in a query

Say I have the following tables:
event_relationships
id
user_id
relationship
primary_event_id
secondary_event_id
events
id
user_id
name
color
In my user model, I have my relationship setup like:
$this->hasMany(EventRelationships::class, 'user_id');
And each event relationship belongs to one user.
How can I use Laravel Eloquent to get a list of all the event relationships, but also get each event's name and color? Matching on the primary_event_id and secondary_event_id.
Is this possible with one query?
In pure eloquent, in the laravel way, that would be :
$eventRelationships = EventRelationships::with('primaryEvent', 'secondaryEvent')->get();
foreach($eventRelationships as $eventRelationship){
$primary_event_name = $eventRelationship->primaryEvent->name;
$secondary_event_name = $eventRelationship->secondaryEvent->name;
}
but it's in 2 queries. If you want only one query, you have to use a join :
$eventRelationships = EventRelationships::query()
->join('events as primary_events', 'events.id', 'event_relationships.primary_event_id')
->join('events as secondary_events', 'events.id', 'event_relationships.secondary_event_id')
->select('event_relationships.*', 'primary_events.name as primary_event_name', 'secondary_events.name as secondary_event_name')
->get();
foreach($eventRelationships as $eventRelationship){
$primary_event_name = $eventRelationship->primary_event_name;
$secondary_event_name = $eventRelationship->secondary_event_name;
}
It might be easier to use the first one as you manipulate eloquent object

How to select all the values from a table except the values which are in foreign table?

I have three tables:tbl_borrower, tbl_clientandtbl_guarantor
tbl_Client:
id|name|address|email|
tbl_Guarantor:
id|clientid(fk)|Guaranteed_date|borrower_id(fk from borrower table)
I want to retrieve all the values of client table except the values which are present in guarantor table in the controller of Laravel 5.5.
Once you have the models and relationships set up, you should just do:
Client::doesntHave('guarantor')->get()
https://laravel.com/docs/5.6/eloquent-relationships#querying-relationship-absence
If you're using the query builder, it would be:
$clients = DB::table('tbl_clients')
->join('tbl_guarantor', 'tbl_clients.id', '=', 'tbl_guarantor.clientid')
->select('tbl_clients.*')
->whereNull('tbl_guarantor.clientid')
->get();
https://laravel.com/docs/5.5/queries
With the premise of using a left join and testing for NULL on the 2nd table id based on this answer. https://stackoverflow.com/a/4076157/3585500
Try this :
DB::table('tbl_Client')
->groupBy('tbl_Client.id')
->leftjoin('tbl_Guarantor', 'tbl_Client.id', '=', 'tbl_Guarantor.clientid')
->get([
'tbl_Client.*'
]);

laravel query builder: join dependent on primary content

I'm using luman and Database Query Builder to fetch full user info from database.
First, Please Take a lock at my database structure:
I have a table called users and a series of other tables that are related to user groups (Ex: secretaries, patients, doctors and admins) which stores additional information about the users.
Also To determine user access, I have a level column on user table which can have one of this value as enum: 'admin', 'doctor', 'secretary', 'patient'.
So, I want to get this information using one query by join and select.
My training code is something like this:
$userInfo = User::where("userID", $userID)
->limit(1)
->join('[GROUP_TABLE_NAME]', function ($join) {
$join->on('user.userID', '=', '[GROUP_TABLE_NAME]' .'.'.
'[GROUP_NAME]' . 'ID');
})
->get();
The GROUP_NAME comes from level column on user table and the GROUP_TABLE_NAME can be built based on the GROUP_NAME value(Ex: ['secretary' => 'secretaries' , 'patient' => 'patients' , ...]).
Any idea to handle the join structure using laravel query builder?
First you should be aware of the fact that this code architecture is not convenient and not easy to understand for other developers.
SQL
You can achieve your goal by using union and join.
Just convert this query for laravel builder or use it directly with DB::statement: select users.*, infos.info from users left join (( select secretaries.* from secretaries ) UNION (select doctors.* from doctors)) infos ON users.id = infos.user_id where users.id=?.
But
The easiest way to do it is to fetch info in two queries, both indexed and fast: user from users by primary key and then info by indexed field user_id in it. Create Doctorinfo, Admininfo models and correspondent migrations. So user class can be smth like this:
public function getInfo() {
switch($this->level) {
'doctor':
return $this->doctorinfo;
...
}
}
private function doctorinfo() {
$this->hasOne('App\Doctorinfo');
}
Builder
You can use left join to join all sub tables as well. The following builder selects info column.
User::where("userID", $userID)->limit(1)
->leftJoin('patients', 'users.id', '=', 'patients.user_id')
->leftJoin('doctors', 'users.id', '=', 'doctors.user_id')
->leftJoin('admins', 'users.id', '=', 'admins.user_id')
->select('users.*', DB::raw('IF(users.level="admin", admins.info, (IF users.level="doctors", doctors.info, patients.info))'))

Laravel selectRaw with joined table data

I am using the following to sum a total column:
$hive_count = Hive::where('active','true')
->groupBy('hive_type_id')
->selectRaw('sum(total) as sum, hive_type_id')
->pluck('sum','hive_type_id');
But rather than using the hive_type_id for the array key, I would like to access the hive_type name from the hive_types table (column 'name'). I have tried hive_type_id.name but this did not work.
Models: Hive & HiveType
Thanks for your help.
I would like to access the hive_type name from the hive_types table (column 'name').
You've to join the table hive_types in your query so you can access the name :
$hive_count = DB::table('hives')
->where('active','true')
->join('hive_types', 'hives.hive_type_id', '=', 'hive_types.id')
->groupBy('hive_type_id','hive_types.name')
->selectRaw('sum(total) as sum, hive_types.name as name')
->pluck('sum','name');

Laravel 5 - how to perform left join on same table

In my application, there's two tables at the moment: users and employees. The latter is simply a profile table for the boilerplate users table that ships with Laravel.
I have two foreign keys inside of employees, one is user_id that points to id on users table. So basically, the profile data of the registered user. The second foreign key in employees is manager_id. That is the id of the person who is the manager of an employee. Some users are managers and have a blank manager_id field.
I want to retrieve the row from my Employee model where the user_id matches the manager_idand then send them all to my view, where they will see the first_name and last_name of the manager. At the moment I see the manager ID instead of their name.
Sample LeftJoin =>
DB::connection('testing')->table('table1 as t1')
->select('t1.column, t2.column')
->leftJoin('table2 as t2','t2.client_id','=','t1.id')
->get();
Try some thing like this:
$users = DB::table('users t1')
->join('users t2', 't1.id', '=', 't2.user_id')
->select('your column list')
->get();
// here we are creating 2 aliases for users table which make it self join
In your Employees model add the following method:
public function manager()
{
return $this->hasOne('App\User', 'id', 'manager_id');
}
You can then get the name of the Manager like this:
$employee = \App\Employee::find(1);
$manager = $employee->manager()->first();
$manager_name = $manager->name;

Categories