latest() helper function in laravel - laravel

I'm building a small application where I'm having many to many relationship between two models something like this:
class Contact extends Model
{
public function company()
{
return $this
->belongsToMany('App\Company', 'company_contact', 'company_id', 'contact_id')->withTimestamps();
}
}
Now while retrieving this I want only the latest model through the pivot table or you may say relational table, for this I'm trying to implement:
public function getData()
{
$allData = Contact::all();
foreach($allData as $data)
{
$getCompany = $data->company()->latest()->first();
$data->company = $getCompany;
}
return response()->json(['model' => $allData], 200);
}
But I'm unable to retrieve the latest table it is showing the same old value or the first value.
Guide me how can I achieve this.

You can try this :
latest() is a function defined in Illuminate\Database\Query\Builder Class.
public function latest($column = 'created_at')
{
return $this->orderBy($column, 'desc');
}
So, It will just orderBy with the column you provide in descending order with the default column will be created_at
OR
public function getData()
{
$allData = Contact::all();
foreach($allData as $data)
{
$getCompany = $data->company()->orderBy('created_at', 'desc')->first();
$data->company = $getCompany;
}
return response()->json(['model' => $allData], 200);
}

So basically idea is if you are finding the relational data from many to many relation like $data->company() in this question and try to sort this with latest it will sort the company table with created_at sorting desc in order to get relational latest data you need to sort through pivot tables i.e.
$getCompany = $data->company()->withPivot('created_at')->orderBy('pivot_cr‌​eated_at', 'desc')->first();
This is how I achieved the latest relational table.
Note: You must have pivot table in your relation, in this answer created_at is the pivot field I'm using.

Related

Get max count from laravel eloquent relationship

I have a model Topic which has hasMany relationship with Game model.
//Topic.php
public function Games() {
return $this->hasMany(Game::class);
}
//Game.php
public function Topic() {
return $this->belongsTo(Topic::class);
}
What I need is getting the Topic which has the max count (also the count value) of Games based on 'created_at' today,this week,this month etc. I tried the following code, but the nested whereBetween query does not work, instead it is showing all the related topic->games created ever
$top_topic_month = Topic::with('games')->get()->sortBy(function($q)
{
return $q->games->whereBetween('created_at',[today()->startOfMonth, today()])->count();
})->first();
$top_topic_month_count = ?
try this
use withCount to generate games_count
$top_topic_month = Topic::withCount('games')->whereHas('games',function($q) use($startMonth){
$q->whereBetween('created_at', [$startMonth, today()]);
})->orderByDesc('games_count')->first();
$top_topic_month_count = $top_topic_month->count()

How to order by column in nested level relationship in Laravel and get first order by?

I have two model.finance has many price.i want to get just one price (last record according to time) for every finance.so used function and order by and first of each orderby.but this just works for first finance and the other i get null in the with relation.
public function prices()
{
return $this->hasMany(Price::class, 'finance_id');
}
public function finances()
{
return $this->belongsTo(Finance::class, 'finance_id');
}
$finances = Finance::with(['prices' => function ($query) {
$query->orderBy('created_at', 'desc')->first();
}])->get();
Create new relationship in your Finance model to get latest price:
public function latestPrice()
{
return $this->hasOne(Price::class)->latest();
}
Change your query as below:
$finances = Finance::with('latestPrice')->get();

Paginate with Eloquent but without instantiation Models

We have two Models:
SimpleModel (id, country, code)
ComplexRelatedModel (id, name, address)
SimpleModel has many ComplexRelatedModel, then
class Product extends Model
{
protected $fillable = [
'name'
];
/* hasOne */
public function complexRelatedChild()
{
return $this->hasOne(self::class, 'parent_id', 'id');
}
}
If we do
$simples = SimpleModel
->with('complexRelatedChild')
->simplePaginate(100000 /* a lot! */);
And we need only do
foreach ($simples as $simple) {
echo $simple->complexRelatedChild->name;
}
Any ComplexChild has hydratated and ready. This takes a lot of memory in my case. And we need just one field without any funciton or feature of Model.
It's possible use some data field from related object or with eloquent this isn't possible?
Not sure I completely understand your question. You want to only load one field from the complexRelatedChild relation to keep memory limit down?
You could do:
$simples = SimpleModel::with(['complexRelatedChild' => function($query){
return $query->select(['id', 'name']);
})
->simplePaginate(100000);
Which can be simplified to:
$simples = SimpleModel::with('complexRelatedChild:id,name')
->simplePaginate(100000);
However if I were you, I would try to paginate less items than 100000.
Update:
You could use chunk or cursor functions to process small batches of SimpleModel and keep memory limit down.
SimpleModel::chunk(200, function ($simples) {
foreach ($simples as $simple) {
}
});
or
foreach (SimpleModel::cursor() as $simple) {
}
See the documentation for more information

Laravel ORM should return Relation

Is it possible to return an value for an hasOne relation directly with an Model?
For example:
$List = Element::orderBy('title')->get();
The Element has a "hasOne" Relation to an column:
public function type()
{
return $this->hasOne('App\Type', 'id', 'type_id');
}
How can i now return automatically the "type" for the Model?
At the Moment i am looping through all Elements, and build my own "Array" of Objects, including the Key of "type" in this example. But ill prefer to do this only in my Model.
Ill know how to add a "normal" property, but can it be someone from an relation?
public function getTypeAttribute($value)
{
return // how ?
}
protected $appends = array('type');
Is this possible?
Edit:
A workaround could be to use DB:: to return the correct value - but ill dont thing thats a good workaround: like:
public function getTypeAttribute($value)
{
// make a query with $this->type_id and return the value of the type_name
}
protected $appends = array('type');
you need to eager load your relations when getting the Element:
$list = Element::with('type')->orderBy('title')->get();
then access the type using
foreach ($list as $item) {
echo $item->type->type_name;
}
where type_name would be the name of a column in the types table
Make a query scope and in that scope, join your attributes from other tables.
http://laravel.com/docs/5.1/eloquent#query-scopes
http://laravel.com/docs/5.1/queries#joins

Laravel eloquent query (one to one)

I have two tables, tracks and echonestrecords. Tracks have one record in the echonestrecords table with information about the track.
tracks has these columns:
id, title, artist, created_at, updated_at
echonestrecords has these columns:
id, track_id, tempo, mode, key
The track object has the hasOne()-function to return the echonestrecord.
The echonestrecord object has the belongsTo()-function to return the track.
I want to make an Eloquent-query to get all tracks which have an empty row in the echonestrecords-table. That is, a row there the tempo is null.
I can do it like this with the raw query, which doesn't return Track objects.
$tracks = DB::table('tracks')
->select('tracks.*')
->join('echonestrecords','echonestrecords.track_id','=','tracks.id')
->where('echonestrecords.tempo',null,'NULL')
->get();
But I can't figure out how to do this with Eloquent. I figured it must be something like:
$tracks = (array('echonestrecord' => function($query) {
$query->where('tempo', null, 'NULL');
}))->get();
But this returns all tracks! I'm confused.
Can you help me?
I solved it. Yahooo..
The answer was using whereHas:
$tracks = Track::whereHas('EchoNestRecord', function($q)
{
$q->whereNull('tempo');
})->paginate(3);
What you probably need is to create a relation and filter it a little bit more:
class EchoNestRecord extends Eloquent {
protected $table = 'echonestrecords';
}
class Track extends Eloquent {
protected $table = 'tracks';
public function RecordsWithNoTempo()
{
return $this->hasOne('EchoNestRecord')->whereNull('tempo');
}
}
Then you should be able to:
$track = Track::find(1);
foreach($track->recordsWithNoTempo as $record)
{
echo $record->name;
}
Use
dd(DB::getQueryLog());
To check the generated query.

Resources