1

I am trying to combine two features: - getting a random model - ... but only if it has at least 1 related model

my URL is entity/random and the below code works well:

    if ($entityid == 'random') {
        $random = Entity::all()->random(1);
        return Redirect::to(trans('routes.entities') . '/' . $random->id);
    }

Now, my Entity model has two relations defined:

public function comments()
{
    return $this->hasMany('App\Models\Comment', 'entity_id');
}

public function sources()
{
    return $this->hasMany('App\Models\Source', 'entity_id');
}

Having them defined, I can get the number of related comments by $object->comments->count() or sources by $object->sources->count(). My database is MySQL.

The majority of my Entities have NO comments nor sources.

Inspired by Laravel Querying Relations Model::has('relation') doesn't work i was able to get a random model with at least 2 comments:

$random = Entity::has('comments', '>=', DB::raw(2))->get()->random(1);
// produces an Entity with at least 2 comments

TO DO

How to pick a random model only if at least one of two relations count (sources OR comments) are at least 2. Maybe sth like orHas exists?

Community
  • 1
  • 1
Peter
  • 2,634
  • 7
  • 32
  • 46

1 Answers1

1

Yes, there is an orHas method.

You can use it like so:

$random = Entity::has('comments', '>=', 2)->orHas('sources', '>=', 2)->get()->random(1);

A couple other notes:

The DB::raw() syntax is not needed for the has() statements. There used to be a bug for sqlite databases that needed this syntax, but that has been resolved since Laravel 4.1.25.

Additionally, you may want to change how you get your random entity. With your current code, you're going to retrieve every record that meets the criteria, and create a full Entity object for each one. The more entity records you have, the slower this code is going to get. I would suggest something like this:

$id = Entity::has('comments', '>=', 2)->orHas('sources', '>=', 2)->lists('id')->random(1);

$random = Entity::find($id);

First, you use the lists() method to get all the ids of the entities that match the conditions. As of Laravel 5.2, lists() returns a collection. Use the random() method on that collection of ids to pick one id to get. Then, find() that one id, so only one Entity object is created.

patricus
  • 59,488
  • 15
  • 143
  • 145