Laravel eloquent how to order collection by accessor in appends array

19,710

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ч)');
}}
Share:
19,710
gurkov
Author by

gurkov

Updated on June 15, 2022

Comments

  • gurkov
    gurkov almost 2 years

    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