Can same-table eager loads be combined in Laravel 4? - php

I have a model where I'm eager-loading two references to another table (in this case posts.created_by_id == users.id and posts.updated_by_id == users.id).
class Post {
protected $table = 'posts';
public function scopeLatest() {
return $query->with(['created_by', 'updated_by'])
->orderBy('created_at', 'desc');
}
public function createdBy() {
return $this->belongsTo('User');
}
public function updatedBy() {
return $this->belongsTo('User');
}
}
class User {
protected $table = 'users';
public function posts() {
return $this->hasMany('Post', 'created_by');
}
}
This results in something like the following queries:
SELECT * FROM tbl ORDER BY created_at DESC;
SELECT * FROM users WHERE id IN (?); (created_at)
SELECT * FROM users WHERE id IN (?); (updated_at)
This makes sense - we're loading all of the referenced records in created_by, and then updated_by - however we could optimise this to combine the ids make a single query to users.
My question is: is this something Eloquent currently supports?

Didn't work for me. It seems that the eager load works for only one instance of the table. For me only one of the relationships has been filled. Eloquent probably uses the the table name as a pointer for the eager load. It generates all the eager load queries but only one will be filled.
I had to separate the data into different tables just because of this problem (and haven't had the time to dig that deep into Eloquent code.)

I think this is what you might be looking for:
class Post {
protected $table = 'posts';
public function scopeLatest($query) {
return $query->with('createdBy', 'updatedBy')
->orderBy('created_at', 'desc');
}
public function createdBy() {
return $this->belongsTo('User','created_by_id');
}
public function updatedBy() {
return $this->belongsTo('User','updated_by_id');
}
}
class User {
protected $table = 'users';
public function postsCreated() {
return $this->hasMany('Post', 'created_by_id');
}
public function postsUpdated() {
return $this->hasMany('Post', 'updated_by_id');
}
}

Related

How to get only active element from many to many relationship with translation in laravel

I have a problem with a many to many relationship and the translations of the terms.
I have 4 tables:
products
- id, price, whatever
products_lang
- id, product_id, lang, product_name
accessori
- id, active
accessori_lang
- id, accessori_id, lang, accessori_name
I'm trying to assign accessories to products with an intermediate table named:
accessori_products
this is the model for Product:
class Product extends Model {
protected $table = 'products';
public function productsLang () {
return $this->hasMany('App\ProductLng', 'products_id')->where('lang','=',App::getLocale());
}
public function productsLangAll() {
return $this->hasMany('App\ProductLng', 'products_id');
}
public function accessori() {
return $this->belongsToMany('App\Accessori', 'accessori_products');
}
}
this is the model for productLng:
class ProductLng extends Model {
protected $table = 'products_lng';
public function products() {
return $this->belongsTo('App\Product', 'products_id', 'id');
}
}
Then I have the model for Accessori:
class Accessori extends Model {
protected $table = 'accessori';
public function accessoriLang() {
return $this->hasMany('App\AccessoriLng')->where('lang','=',App::getLocale());
}
public function accessoriLangAll() {
return $this->hasMany('App\AccessoriLng');
}
public function accessoriProducts() {
return $this->belongsToMany('App\Products', 'accessori_products', 'accessori_id', 'products_id');
}
}
And the model for AccessoriLng:
class accessoriLng extends Model {
protected $table = 'accessori_lng';
public function accessori() {
return $this->belongsTo('App\Accessori', 'accessori_id', 'id');
}
}
I get the results by this:
$products = Product::has('accessori')->with([
'productsLang ',
'accessori' => function ($accessori){
$accessori->with([
'accessoriLang'
]);
}
])->get();
return $products;
but I want to get only the active accessories something like where accessori.active = 1 but I really don't know where to put it. I've tried in different way but I'm stuck on it by 2 days.
IIRC you don't need a model for the intermediate table on your many to many relationships.
If you want to return Products where Accessori is active you can use whereHas on the Product model.
$prod = Product::whereHas('accessori', function($query) {
$query->where('active', 1);
})->get();
Where the $query param will be running on the Accessori model.
You can do the inverse as well with Accessori to Product.
$acessoris = Accessori::where('active', 1)->whereHas('accessoriProduct')->with(['accessoriLang', 'accessoriProducts.productsLang'])->get();

Laravel Eloquent eager loading, few columns related to one table

I have the Models structure from database like this:
class Player extends Model
{
protected $table = 'players';
}
related to Players (this table always have to have 5 fixed positions):
class FormationPositions
{
protected $table = 'formation_position';
public function fpos1()
{
return $this->belongsTo(Player::class, 'fpos_1');
}
public function fpos2()
{
return $this->belongsTo(Player::class, 'fpos_2');
}
public function fpos3()
{
return $this->belongsTo(Player::class, 'fpos_3');
}
public function fpos4()
{
return $this->belongsTo(Player::class, 'fpos_4');
}
public function fpos5()
{
return $this->belongsTo(Player::class, 'fpos_5');
}
}
when I try to eager load FormationPositions table like this:
FormationPositions::with(['fpos1', 'fpos2', 'fpos3', 'fpos4', 'fpos5'])
then I got 5 queries to database to load these object, maybe there is some way to combine this structure into one query with Elequent eager way SELECT * FROM table where id IN (?) and load data to that objects with one query?

Laravel 5 using pivot table with hasMany relationship

I'm making a poll system and I have two tables :
polls table : Has those fields (id,question,created_at,updated_at).
choices table : Has those fields (id,poll_id,choice).
And a pivot table named choice_poll : Has those fields (id,choice_id,poll_id,ip,name,phone, comment ,created_at,updated_at)
Poll Model :
class Poll extends Model
{
protected $table = 'polls';
protected $fillable = ['question'];
public $timestamps = true;
public function choices()
{
return $this->BelongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}
}
Choice Model :
class Choice extends Model
{
protected $table = 'choices';
protected $fillable = ['poll_id','choice'];
public $timestamps = false;
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
}
Now when I try to build this query it doesn't return the choices :
$poll->first()->choices()->get()
PS: There is many choices in the choices table associated with the first poll.
In this case you have Many To Many relationship so try to change belongsTo in :
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
To belongsToMany, and it will be :
public function poll()
{
return $this->belongsToMany('App\Poll')->withPivot('ip','name','phone','comment');
}
NOTE 1: You have to change BelongsToMany to belongsToMany note the B should be in lower case.
NOTE 2: You want the pivot table with timestapms create_at,updated_at as you mentioned in th OP so you have to use withTimestamps(); :
return $this->belongsToMany('App\Poll')
->withPivot('ip','name','phone','comment')
->withTimestamps();
//AND in the other side also
return $this->belongsToMany('App\Choice')
->withPivot('ip','name','phone','comment')
->withTimestamps();
Hope this helps.
This:
public function poll()
{
return $this->belongsTo('App\Poll')->withPivot('ip','name','phone','comment');
}
and
public function choices()
{
return $this->BelongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}
should be:
public function poll()
{
return $this->belongsToMany('App\Poll')->withPivot('ip','name','phone','comment');
}
and
public function choices()
{
return $this->belongsToMany('App\Choice')->withPivot('ip','name','phone','comment');
}

laravel 4 Cannot Retrieve ALL results ? pivot table Many to Many

I am a bit stuck on this...
I have 3 tables: photographers, languages and languages_spoken (intermediate table).
I am trying to retrieve all the languages spoken by a photographer. I defined my models like this:
class Photographer extends Eloquent {
/**
* Defining the many to many relationship with language spoken
*
*/
public function languages() {
return $this->belongsToMany('Language', 'languages_spoken', 'language_id', 'photographer_id');
}
class Language extends Eloquent {
/**
* Defining the many to many relationship with language spoken
*
*/
public function photographers() {
return $this->belongsToMany('Photographer', 'languages_spoken', 'language_id', 'photographer_id')
->withPivot('speakslanguages');
}
This is how I was trying to retrieve all the results for the logged in photographer:
$photographer = Photographer::where('user_id', '=', $user->id);
if ($photographer->count()) {
$photographer = $photographer->first();
// TEST
$spokenlang = $photographer->languages;
die($spokenlang);
// END TEST
} else {
return App::abort(404);
}
The problem is that in my db I have 4 entries for the same photographer. but when I do this I only get the last result...
[{"id":"3","language_name":"Afrikaans","updated_at":"-0001-11-30 00:00:00","created_at":"-0001-11-30 00:00:00","native_name":"Afrikaans","ISO639_1":"af","pivot":{"language_id":"3","photographer_id":"3"}}]
Any idea on what is wrong ?
Thanks a lot for your help!!!
The third parameter to belongsToMany should be the foreign key.
In the Photographer class:
public function languages() {
return $this->belongsToMany('Language', 'languages_spoken', 'language_id', 'photographer_id');
}
...should be:
public function languages() {
return $this->belongsToMany('Language', 'languages_spoken', 'photographer_id');
}
In the Language class:
public function photographers() {
return $this->belongsToMany('Photographer', 'languages_spoken', 'language_id', 'photographer_id')
->withPivot('speakslanguages');
}
Should be:
public function photographers() {
return $this->belongsToMany('Photographer', 'languages_spoken', 'language_id')
->withPivot('column1', 'column2', 'column3'); // withPivot() takes a list of columns from the pivot table, in this case languages_spoken
}
But, since you're not even using strange keys, you don't need to pass that third parameter at all.
So this is just fine:
public function languages() {
return $this->belongsToMany('Language', 'languages_spoken');
}
And:
public function photographers() {
return $this->belongsToMany('Photographer', 'languages_spoken')
->withPivot('column1', 'column2', 'column3'); // withPivot() takes a list of columns from the pivot table, in this case languages_spoken
}

Laravel querying model relations

I'm still struggeling with the laravel Models. At first I tried doing it all using the tables, but thats not smart, I'll miss out on lots of the laravel functions.
I have the following setup
ProjectTwitterStatus links the projects and the twitter statuses.
TwitterStatus has all the details of a twitter status and has a unique ID ('posted at' datetime of tweet is among the details)
TwitterRetweets has the ID of the TwitterStatus - the actual retweet - and the tweet ID of the retweeted status
TwitterReplies has the ID of the TwitterStatus - that is the actual reply - and/or the user ID if not a reply to a status but to a user.
What I want? To get for each date (DATE(datetime)) the count of the statuses, retweets and replies, using the laravel model relations.
These are the models.
class ProjectTwitterStatus extends Eloquent {
protected $table = 'project_twitter_statuses';
protected $softDelete = true;
public function twitterStatus() {
return $this->belongsTo('TwitterStatus');
}
public function project() {
return $this->belongsTo('Project');
}
}
class TwitterStatus extends Eloquent {
protected $table = 'twitter_statuses';
public function twitterRetweet() {
return $this->hasMany('TwitterRetweet');
}
public function twitterReply() {
return $this->hasMany('TwitterReply');
}
public function twitterUser() {
return $this->belongsTo('TwitterUser');
}
public function projectTwitterStatus() {
return $this->hasMany('ProjectTwitterStatus');
}
}
class TwitterRetweet extends Eloquent {
protected $table = 'twitter_retweets';
public function twitterStatus() {
return $this->belongsTo('TwitterStatus');
}
}
class TwitterReply extends Eloquent {
protected $table = 'twitter_replies';
public function twitterStatus() {
return $this->belongsTo('TwitterStatus');
}
}
I got the count of the twitterStatuses using this:
$twitterStatuses = TwitterStatus::has('projectTwitterStatus')
->groupBy(DB::raw('DATE(datetime)'))
->get(array(DB::raw('COUNT(id) AS tweets'),DB::raw('DATE(datetime) AS date')));
I tried for example this to get the retweet count added but that has no effect (a reference to the model apears in the object -> array().
$twitterStatuses = TwitterStatus::has('projectTwitterStatus')
->with(array('twitterRetweet' => function($query)
{
$query->count();
}))
->groupBy(DB::raw('DATE(datetime)'))
->take(10)
->get(array(DB::raw('COUNT(id) AS tweets'),DB::raw('DATE(datetime) AS date')));
Can anyone point me in the right direction?
Not 100% sure how your intended solution is to be used - Assuming you simply want a count of the number of retweets related to twitterStatus?
$count = $twitterStatus->twitterRetweet()->count();
where $twitterStatus is an already retrieved model - not a collection.
if $twitterStatus is a collection to iterate through you can also eager load the related model using either with() or load()
Then you can iterate through each model in the collection - depends on how you wanted to use the results

Categories