Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel eloquent how to order collection by accessor in appends array

I have following Eloquent model:

class Song extends Eloquent {

protected $table = 'mg_songs';
protected $hidden = array('events');
protected $appends = array('lastDate');

public function events()
{
    return $this->belongsToMany('Event', 'song_event');
}

public function getLastDateAttribute()
{
    if (!$this->events) return null;

    return $this->events[0]->date->formatLocalized('%d.%m.%Y (%a, %Hч)');
}}

Is it possible to sort by "lastdate" field same as db field:

$songs->orderBy('title', 'asc'); - works
$songs->orderBy('lastDate', 'desc'); - doesn't works

May be exist simple answer?

EDITED:

My db structure (only needed fields), with many-to-many:

events table
event_id
date

songs table
song_id
title

song_event pivot table
id
song_id
event_id

SQL-request:

SELECT s.title, (SELECT MAX(e.date) FROM events e JOIN song_event se ON (e.id = se.event_id) WHERE se.song_id = s.id) AS s_date FROM mg_songs s ORDER BY s_date desc
like image 416
gurkov Avatar asked Sep 22 '14 13:09

gurkov


1 Answers

You can sort the resulting collection by accessor, obviously the query can't be ordered, for it's not in the db.

$songs = Song::all(); // get the result
$songs->sortByDesc('lastDate'); // sort using collection method

// or ascending:
$songs->sortBy('lastDate');

You could achieve the same using joins, if you prefer to do this in the db call (it's better in terms of performance).


Another thing: you use if( ! $this->events) which will cause trouble soon.

Check this out:

// hasOne / belongsTo / morphTo etc - single relations
$model->relation; // returns related model OR null -> evaluates to false

// BUT for hasMany / belongsToMany etc - multiple results
$model->relation; // always returns a collection, even if empty, evaluates to true

So change this if to:

public function getLastDateAttribute()
{
    if ( ! count($this->events)) return null;

    return $this->events[0]->date->formatLocalized('%d.%m.%Y (%a, %Hч)');
}}
like image 188
Jarek Tkaczyk Avatar answered Nov 10 '22 06:11

Jarek Tkaczyk