user2694306
user2694306

Reputation: 4050

Laravel Eloquent - Is it inefficient

I'm looking at developing a new site with Laravel. I was reading a tutorial on http://vegibit.com/laravel-eloquent-orm-tutorial/, regarding using Eloquent to join tables and retrieve data. In the last example they are essentially trying to do a join but still Eloquent is executing two queries instead of one. Is Eloquent inefficient or is this simply a poor example? It seems that this could have simply been done with a single left join query. Can anyone provide some insight on this? Is there a better way to execute this query? The specific example is:

Route::get('/', function()
{
    $paintings = Painting::with('painter')->get();

    foreach($paintings as $painting){
        echo $painting->painter->username;
        echo ' painted the ';
        echo $painting->title;
        echo '<br>';
    }

});

Results in the following queries:

string ‘select * from paintings‘ (length=25)
string ‘select * from painters where painters.id in (?, ?, ?)’ (length=59)
Leonardo Da Vinci painted the Mona Lisa
Leonardo Da Vinci painted the Last Supper
Vincent Van Gogh painted the The Starry Night
Vincent Van Gogh painted the The Potato Eaters
Rembrandt painted the The Night Watch
Rembrandt painted the The Storm on the Sea of Galilee

Upvotes: 1

Views: 1070

Answers (3)

Amo
Amo

Reputation: 2944

The simple answer to your question: No. It is not inefficient.

Using Eloquent in the way described by Jorge really defeats its purpose as an ORM.

Whilst you can write joins as in the example given, an ORM really isn't designed with that in mind.

The example you've given isn't an n+1 query (where there's an additional query run for each item in the loop - the worst type of query).

Using two queries as reported by your output isn't a huge overhead, and I think you'd be fine to use that in production. Your use of Eloquent's 'with' eager loading is precisely what you should use in this context.

An example of an n+1 query (which you want to avoid) is as follows:

foreach (Book::all() as $book)
{
    echo $book->author->name;
}

If 20 books are returned by Book::all(), then the loop would execute 21 queries in total. 1 to get all of the books, and 1 for each iteration of $book to get the author's name.

Using Eloquent with eager loading, combined with caching would be enough to minimise any performance issues.

Upvotes: 0

Alexandru Muresan
Alexandru Muresan

Reputation: 115

Eloquent is extremely useful for building something quickly and also has query caching that it's really easy to use however it might not be ideal for big projects that need to scale over time, my approach is to use Repository pattern with contracts that way I can still use the power of Eloquent and have a system that will allow me to easily change the implementation if needed.

Upvotes: 3

envynoiz
envynoiz

Reputation: 348

If what you want is to get all the data in a single query to use joins, then you must specify it as:

Painting::join('Painter as p', 'p.IdPainter', '=', 'Painting.IdPainting')->get()

And if you need some conditional then:

Painting::join('Painter as p', 'p.IdPainter', '=', 'Painting.IdPainting')->where('cond1', '=', 'value')->get();

Personally Eloquent is inefficient, i prefer Doctrine in this regard.

Upvotes: 0

Related Questions