Eloquent Relationships hasMany use loop - php

I have a database with multiple address records of a user. When I do "pluck()" and "join()" in the foreach path, I get results. But when I type $user->getAddress->address in structures like hasOne, I get the result I want. In short, can I return the loop in hasMany more practically?
Following my code:
user Table
id | name | lastname |
--- -------------- ----------
1 | Rahuel | lastnameRahuel
2 | Dalton Miller | lastnameDalton
adress Table
user_id | address
-------- ---------
1 | 740 Brown Greens Suite
1 | 9906 Cleora Wall Apt.
2 | 53977 Kip Center Apt
UserModel
public function getAddress()
{
return $this->hasMany(Address::class);
}
Controller
$users = User::with('getAddress')->get();
foreach ($users as $user){
echo $user->name;
echo $user->lastname;
echo $user->getAdress->pluck('address')->join(',');
}

You can use the Collection 's implode method to make it look a bit less verbose.
echo $user->getAdress->implode('address', ',');

Related

Laravel relationship HasMany

I keep multiple address records belonging to a user. but when i write with dd i can't access other table's data.
Following my code:
user Table
id | name | country |
--- -------------- ----------
7 | Mr. Lenny Bins| Belgium
2 | Dalton Miller | Swaziland
address Table
user_id | address
-------- ---------
7 | 740 Brown Greens Suite
7 | 9906 Cleora Wall Apt.
2 | 53977 Kip Center Apt
UserModel
public function getAddress()
{
return $this->hasMany(Address::class);
}
UserController
$users = User::where('id' ,7)->with('getAddress')->get();
dd($users->toArray());
// The output of this is below
dd($users->getAddress->toArray());
I get an error when I try like this.
Property [getAddress] does not exist on this collection instance.
Firstly you are using get that will return collection, In Following you will get all users with their addresses.
$users = User::where('id' ,7)->with('getAddress')->get();
You can use first() instead of get() as you are finding only one user
$user = User::where('id' ,7)->with('getAddress')->first();
If You want only address of that user use
dd($user->getAddress)
Or If you want only in form of array use
dd($user->getAddress->toArray())
User Model
public function getAddress()
{
return $this->hasMany('App\Address');
}
Get User(s)
$users = \App\User::with('getAddress')->where('id' ,7)->get();
Iterate and read data
foreach ($users as $user) {
echo '<pre>' , var_dump($user->getAddress()->first()['address']) , '</pre>';
}
$users = User::with('getAddress')->where('id' ,7)->first();
dd($users);

Laravel Relationships - Questions, Answers and userAnswers

I have some problem, i have 3 tables:
questions
id | text
answers
id | question_id | text
user_answers
id | user_id | question_id | text
Example records:
questions
1 | Gender
2 | Age (input type, answers not exist in answers table)
3 | What kind of pets do you have?
answers
1 | 1 | Male
2 | 2 | Female
3 | 3 | Cat
4 | 3 | Dog
5 | 3 | Parrot
user_answers
1 | 100 | 1 | 1
2 | 100 | 2 | 30
3 | 100 | 3 | 4
3 | 100 | 3 | 5
So, I wonder if exists the way to do relationships without RAW SQL (with joins etc.) in models. For example, something like this:
$questions = Question::with('userAnswer')->where('user_id', 100);
foreach($questions as $q)
{
echo $question->text;
foreach($question->userAnswers as $ans)
{
echo $ans->text
}
}
And result:
Gender
- male
Age
- 30
What kind of pets do you have?
- dog
- parrot
You know what I mean? Some ideas? :)
Thank You for Your attention!
EDITED:
This not work (relation stdAnswer is empty),
$questions = LucidStandardQuestion::with('userAnswers.stdAnswer')->find(x);
this work:
LucidStandardQuestion::with('userAnswers')->find(x)
and in model LucidStandarQuestion:
public function userAnswers()
{
$uid = 1576;
return $this->hasMany(LucidUserAnswer::Class, 'question_id')->where('user_id' , $uid);
}
and in model LucidUserAnswer:
public function stdAnswer()
{
return $this->belongsTo(LucidStandardAnswer::class, 'question_id');
}
It's a simple hasMany relation:
class Question extends Model
{
public function userAnswer()
{
return $this->hasMany(LucidUserAnswer::class,'question_id');
}
}
Now your code may look like:
$questions = Question::with(['userAnswer' => function($query)
{
$query->where('user_id', 100)->with('answer');
}])->get();
and in LucidUserAnswer model you should make the relation
class LucidUserAnswer extends Model
{
public function answer()
{
return $this->belongsTo(Answer::class,'text');
}
}

Laravel 5.6 - How to fetch last X guest names for room deal?

I can't figure out how to structure an efficient Eloquent query for the following scenario.
Users can stay in many locations like rooms, apartments, homes, so we have a polymorphic stayable_locations table, but we're only focusing on the room stayable_type of this table. When the staff clicks a room, we want to display all available room deals (if any are available from the room_deals table) and also the last 3 guests for each room deal (if any).
Trying to get this output from the following tables via eloquent:
Room 111 (desired output for room deals and guests below)
- Room Deal #1 -> Able, Kane, Eve
- Room Deal #2 -> Eve, Adam
------------------------------------------
$room = Room::where('id',111)->first(); // room 111
// Eloquent query, not sure how to setup model relations correctly
// To get last 3 guest names per room deal [if any] in an efficient query
$room->roomDeals()->withSpecificRoomDealLast3RoomGuestNamesIfAny()->get();
Here is the table structure:
stayable_locations table [polymorphic]:
id | stayable_id | stayable_type | room_deal_id | room_guest_id
----------------------------------------------------------------
1 | 111 | room | 0 | 3 (Steve no room deal)
2 | 111 | room | 1 | 1 (Adam room deal)
3 | 111 | room | 1 | 2 (Eve room deal)
4 | 111 | room | 1 | 4 (Kane room deal)
5 | 111 | room | 1 | 5 (Able room deal)
6 | 111 | room | 2 | 1 (Adam room deal)
7 | 111 | room | 2 | 2 (Eve room deal)
room_deals table:
id | room_id | room_deal
-----------------------
1 | 111 | Deal A
2 | 111 | Deal B
users table:
id | name
------------
1 | Adam
2 | Eve
3 | Steve
4 | Kane
5 | Able
UPDATE: Showing respective models
User Model:
class User extends Authenticatable {
public function stayableLocations() {
return $this->morphMany('App\StayableLocation', 'stayable');
}
}
RoomDeal Model:
class RoomDeal extends Model {
public function room() {
return $this->belongsTo('App\Room');
}
public function guests() {
return $this->belongsToMany('App\User', 'stayable_locations', 'room_deal_id', 'room_guest_id');
}
}
StayableLocation Model:
class StayableLocation extends Model {
public function stayable() {
return $this->morphTo();
}
public function room() {
return $this->belongsTo('App\Room', 'stayable_id');
}
}
Room Model:
class Room extends Model {
public function stayableLocations() {
return $this->morphMany('App\StayableLocation', 'stayable');
}
public function roomDeals() {
return $this->hasMany('App\RoomDeal');
}
}
Any idea how to get the desired output via an efficient eloquent query?
I figured it out from the helping comments in my question. Here we go:
Laravel does not have this out of the box (see here) so we'll have to use a third party package.
Install the staudenmeir/eloquent-eager-limit package per link directions and follow usage example.
This is what needed to change above [still used same defined relationship above for below ...], just added the use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;:
class User extends Authenticatable {
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
...
}
class RoomDeal extends Model {
use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;
...
}
Working query with nested limit via eloquent, thanks to the commenters and package help:
$room = Room::find(111);
$deals3Guests = $room->roomDeals() // query deals
->with(['guests' => function($query) { // eager load guests
$query->orderBy('stayable_locations.id', 'desc') // get latest guests
->limit(3); // limit to 3
}])
->get();

How to fetch data from multiple tables using Join and where clause

I have written a simple symfony controller where I have two table known as specialtyarea and physician.
this is the basic structure of the table
specialtyarea
-----------------
id | name |
-----------------
1 | dentist |
2 | physician |
Physician table is related to specialtyarea as shown:
Physician
--------------------
id | name | specfk |
--------------------
1 | John | 1 |
2 | Doe | 2 |
3 | Ann | 2 |
I am trying to fetch all the physician where specialty area is 2
This is my snippet of code
public function getAllPhysicianAction($specId)
{
$id = $this->getDoctrine()->getRepository('Bundle:SpecArea')
->find($specId); //assuming that this returns all the id from the specialty table
$allPhysician = $id->getPhysician()->... //kind of lost here
}
How can I retrieve all the records from the physician table using the specialty Id?
I believe that you can just call findBy on your physician repository.
/**
* #Route("/physicians/{specId}", name="getAllPhysician")
*/
public function getAllPhysicianAction($specId)
{
$allPhysician = $this->getDoctrine()
//call the repository of your physician table
->getRepository('Bundle:physician')
->findBy(['specfk' => $specId]);
var_dump($allPhysician);
}
Use the findBy() method of the "physician" repository:
(You didn't post your actual entities so I'm guessing the field/entity names.)
$spec = $this->getDoctrine()->getRepository('Bundle:SpecArea')->find($specId);
$physicians = $this->getDoctrine()->getRepository('Bundle:Physician')->findBy(['spec' => $spec]);
You can also use $specId ID directly instead of fetching the entire entity from database:
$physicians = $this->getDoctrine()->getRepository('Bundle:Physician')->findBy(['spec' => $specId]);
See: Working with Objects - Querying - By Simple Conditions

Laravel sum() method on collection returning results for all items in table

Given the following table
gallery
+----+---------------+--------------+---------+
| id | gallery_title | viewcount | user_id |
+----+---------------+--------------+---------+
| 1 | Animals | 10 | 1 |
| 2 | Cars | 5 | 1 |
| 3 | Houses | 2 | 2 |
+----+---------------+--------------+---------+
user
+----+----------+
| id | username |
+----+----------+
| 1 | Bob |
| 2 | James |
+----+----------+
and the following classes
class Gallery extends Model
....
public function user()
{
return $this->belongsTo('App\User');
}
and
class User extends Model
....
public function galleries()
{
return $this->hasMany('App\Gallery');
}
calling $galleryCollections= Auth::user()->galleries; returns an array of collections in which I can iterate through
foreach ($galleryCollections as $galleryCollection)
{
$viewcount += $galleryCollection->viewcount;
}
print $viewcount; #returns 15
and so far everything works as expected, correctly up until this point.
However if I accidentally called $galleryCollection->sum('viewcount'), which is the last value from the iteration, the returned value is 17, as it's simply running the following SQL select sum('viewcount') as aggregate from 'gallery'.
I'm struggling to understand what exactly what is happening here. It's almost as if it's calling the 'sum()' method on the gallery class itself without passing in any 'where' values. I'd at least expect it to call the sum() method on the Collection, but instead it's going back to the database.
Is it because my Gallery class does not implement a 'sum()' method, and therefore it uses the Parent Model class and ignores the Gallery class?
If you want to count through sql, then:
Auth::user()->galleries()->sum('viewCount');
But, Auth::user()->galleries->sum('viewCount'); will sum on the collection Auth::user()->galleries.
Auth::user()->galleries() is a queryBuilder whereas Auth::user()->galleries is a collection of galleries of that user.

Categories