CoderFunda
  • Home
  • About us
    • Contact Us
    • Disclaimer
    • Privacy Policy
    • About us
  • Home
  • Php
  • HTML
  • CSS
  • JavaScript
    • JavaScript
    • Jquery
    • JqueryUI
    • Stock
  • SQL
  • Vue.Js
  • Python
  • Wordpress
  • C++
    • C++
    • C
  • Laravel
    • Laravel
      • Overview
      • Namespaces
      • Middleware
      • Routing
      • Configuration
      • Application Structure
      • Installation
    • Overview
  • DBMS
    • DBMS
      • PL/SQL
      • SQLite
      • MongoDB
      • Cassandra
      • MySQL
      • Oracle
      • CouchDB
      • Neo4j
      • DB2
      • Quiz
    • Overview
  • Entertainment
    • TV Series Update
    • Movie Review
    • Movie Review
  • More
    • Vue. Js
    • Php Question
    • Php Interview Question
    • Laravel Interview Question
    • SQL Interview Question
    • IAS Interview Question
    • PCS Interview Question
    • Technology
    • Other

30 March, 2021

Laravel Eloquent Power Joins Package

 Programing Coderfunda     March 30, 2021     Laravel, php     No comments   

 If you have some experience using databases, it is very likely you have used joins at least once in your career. Joins can be used for a bunch of different reasons, from selecting data from other tables to limiting the matches of your query.

I'm going to give a few examples on this post, so, in order to contextualize the examples, imagine we have the following database/models structure.

User -> hasMany -> Post
Post -> hasMany -> Comment
Post -> morphMany -> Image

On Laravel, using eloquent, joining the posts table would look something like this:

User::select('users.*')->join('posts', 'posts.user_id', '=', 'users.id');

In case you want to join the posts and the comments table, your query would look something like this:

User::select('users.*')
->join('posts', 'posts.user_id', '=', 'users.id')
->join('comments', 'comments.post_id', '=', 'posts.id');

This is fine and we can understand, but we can do better. We already have all these relationships defined in our models, but we are repeating some of the implementation details when we write the join statements. So, instead of doing this, wouldn't be cool if you could just do the following?

// example 1
User::joinRelationship('posts');

// example 2
User::joinRelationship('posts.comments');

This is less code to read, and more importantly, easier code to read. It also hides any implementation details on how your relationships work. So, if your relationship changes, your joins will be automatically updated.

Introducing the Eloquent Power Joins package

We felt the way we did joins in our applications wasn't really the “Laravel way”, so we decided to introduce some of the Laravel fine touch into the way we do joins.

joinRelationship is a method introduced by the Eloquent Power Joins package. It works with any type of the existing Laravel relationships.

The installation of the package is as simple as just running the following composer command, and you should already have access to everything that will be mentioned on this post.

composer require kirschbaum-development/eloquent-power-joins

On any model you want to be able to use the methods described below, you should use the following trait:

use Kirschbaum\PowerJoins\PowerJoins;

class User extends Model
{
use PowerJoins;
}

Joining polymorphic relationships

The joinRelationship method also works polymorphic relationships. Besides performing the regular join, it also performs the {morph}_type == Model::class check, as you can see below.

Post::joinRelationship('images')->toSql();

// select * from posts
// inner join images on images.imageable_id = posts.id AND images.imageable_id = 'App\\Post'

Joining nested relationships

And, it also works with nested relationships.

User::joinRelationship('posts.images')->toSql();

// select * from users
// inner join posts on posts.user_id = users.id
// inner join images on images.imageable_id = posts.id AND images.imageable_id = 'App\\Post'

It works with any relationship

The package will work with any of the native relationship types provided from Laravel.

BelongsToMany will make 2 joins considering the pivot table as well. HasManyThrough also makes the 2 necessary joins.

Eloquent Power Joins also applies any soft deletes clauses in case the related model uses the SoftDeletes trait.

But, the package also provides you with a few other very useful features, as you can see below.

Applying extra conditions to the joins

You can apply any extra condition you need to the joins, as well.

User::joinRelationship('posts', function ($join) {
$join->where('posts.published', true);
});

For nested calls, and/or BelongsToMany or HasManyThrough relationships, you need to pass an array with the relationship as the key.

User::joinRelationship('posts.images', [
'posts' => function ($join) {
$join->where('posts.published', true);
},
'images' => function ($join) {
$join->where('images.cover', true);
},
]);

Using model scopes inside the callbacks 🤯

We consider this one of the most useful features of this package. Let's say, you have a published scope on your Post model:

public function scopePublished($query)
{
$query->where('published', true);
}

When joining relationships, you can use the scopes defined in the model being joined. How cool is this?

User::joinRelationshio('posts', function ($join) {
// the $join instance here can access any of the scopes defined in the Post model 🤯
$join->published();
});

Querying relationship existence

Querying relationship existence is a very powerful and convenient feature of Eloquent. However, it uses the where exists syntax which is not always the best and more performant choice, depending on how many records you have or the structure of your table.

This package also implements almost all Laravel methods for querying relationship existence using joins instead of where exists.

Performance

First thing to be aware here, is that the below example is one use-case where using joins over where exists is a lot more performant. You shouldn't assume this is true for every query, and you should use tools like Laravel Debugbar , Laravel Telescope or any tool of your choice to figure out what's best for YOUR use-case.

That said, below you can see one example of the MySQL CPU usage after deploying a change to use powerJoinHas instead of has, in one of our client's application. MySQL was running on RDS, and this image was took from AWS CloudWatch.

MySQL CPU Usage Graph

Show me the code

Below, you can see the methods this package implements and also the Laravel equivalent.

Laravel Native Methods

User::has('posts');
User::has('posts.comments');
User::has('posts', '>', 3);
User::whereHas('posts', function ($query) {
$query->where('posts.published', true);
});
User::doesntHave('posts');

Package implementations using joins

User::powerJoinHas('posts');
User::powerJoinHas('posts.comments');
User::powerJoinHas('posts.comments', '>', 3);
User::powerJoinWhereHas('posts', function ($query) {
$query->where('posts.published', true);
});
User::powerJoinDoesntHave('posts');

Sorting your query results

Another useful feature os to sort your query results using a column from another table using the orderByPowerJoins method.

User::orderByPowerJoins('profile.city')->toSql();
// select "users".* from "users"
// inner join "user_profiles" on "user_profiles"."user_id" = "users"."id"
// order by "user_profiles"."city" asc

You can also sort your results by aggregations (COUNT, SUM, AVG, MIN or MAX).

For instance, to sort users with the highest number of posts, you would do this:

$users = User::orderByPowerJoinsCount('posts.id', 'desc')->get();

Or, to get the list of posts sorted by the ones with comments which contain the highest average of votes.

$posts = Post::orderByPowerJoinsAvg('comments.votes', 'desc')->get();

And you also have methods for SUM, MIN and MAX:

Post::orderByPowerJoinsSum('…');
Post::orderByPowerJoinsMin('…');
Post::orderByPowerJoinsMax('…');

Joins, the Laravel way

IMO, one of the advantages of the package is being able to write code in a more “Laravel way”. So, below you can see a few examples of how much better the code looks after using it. Any examples described here produces the EXACT same result.

Example 1

BuilderFile::select('builder_detail_builder_file.*')
->join('builder_detail_builder_file', 'builder_files.id', '=', 'builder_detail_builder_file.builder_file_id')
->join('builder_details', 'builder_details.id', '=', 'builder_detail_builder_file.builder_detail_id')
->join('documents', 'builder_details.document_id', '=', 'ces_documents.id');

With Eloquent Power Joins

BuilderFile::joinRelationship('details.document');

Example 2

CesDocument::query()
->join('term_relations', function ($join) {
$join
->on('term_relations.relationable_id', '=', 'ces_documents.id')
->where('term_relations.relationable_type', '=', CesDocument::class);
})
->join('terms', 'term_relations.term_id', '=', 'terms.id')
->join('vocabularies', 'terms.vocabulary_id', '=', 'vocabularies.id')
->get();

With Eloquent Power Joins

CesDocument::query()
->joinRelationship('related.terms')
->joinRelationship('related.vocabulary')
->get();

That's it. Hopefully this package is going to be as useful to you as it is to us. Happy joining!

Resources: laravel-news.com

  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Email ThisBlogThis!Share to XShare to Facebook
Newer Post Older Post Home

0 comments:

Post a Comment

Thanks

Meta

Popular Posts

  • Generate Migrations from an Existing Database With the Migration Generator Package
    Laravel Migration Generator Migration Generator for Laravel is a package by Bennett Treptow to generate migrations from existing database ...
  • Tailwindcss best practices for responsive design
    Tailwind CSS provides powerful utilities for responsive design out of the box. To use it effectively and maintain clean, scalable code, here...
  • Search Through Models with Laravel Searchable
      Laravel Searchable   is a package by   Spatie   to search through models and other sources pragmatically. Using this package, you can get ...
  • Laravel Razorpay Integration | Payment gateway integration Laravel in 30 mins | Laravel Razorpay
    1 Integration of Razorpay with Laravel. In this tutorial, I have taught how to integrate payment gateway with laravel with mini-project. If...
  • Vue.js Render functions
        Vue.js Render functions Vue.js recommends us to use templates to build HTML. Here, we can use the render function as a closer-to-the-co...

Categories

  • Ajax (26)
  • Bootstrap (30)
  • DBMS (42)
  • HTML (12)
  • HTML5 (45)
  • JavaScript (10)
  • Jquery (34)
  • Jquery UI (2)
  • JqueryUI (32)
  • Laravel (1017)
  • Laravel Tutorials (23)
  • Laravel-Question (6)
  • Magento (9)
  • Magento 2 (95)
  • MariaDB (1)
  • MySql Tutorial (2)
  • PHP-Interview-Questions (3)
  • Php Question (13)
  • Python (36)
  • RDBMS (13)
  • SQL Tutorial (79)
  • Vue.js Tutorial (69)
  • Wordpress (150)
  • Wordpress Theme (3)
  • codeigniter (108)
  • oops (4)
  • php (853)

Social Media Links

  • Follow on Twitter
  • Like on Facebook
  • Subscribe on Youtube
  • Follow on Instagram

Pages

  • Home
  • Contact Us
  • Privacy Policy
  • About us

Blog Archive

  • ►  2026 (3)
    • ►  07/26 - 08/02 (2)
    • ►  06/28 - 07/05 (1)
  • ►  2025 (4)
    • ►  07/06 - 07/13 (2)
    • ►  06/29 - 07/06 (2)
  • ►  2024 (486)
    • ►  09/15 - 09/22 (30)
    • ►  09/08 - 09/15 (35)
    • ►  09/01 - 09/08 (35)
    • ►  08/11 - 08/18 (2)
    • ►  08/04 - 08/11 (33)
    • ►  07/28 - 08/04 (30)
    • ►  07/07 - 07/14 (11)
    • ►  06/30 - 07/07 (35)
    • ►  06/23 - 06/30 (5)
    • ►  06/02 - 06/09 (31)
    • ►  05/26 - 06/02 (20)
    • ►  05/05 - 05/12 (29)
    • ►  04/28 - 05/05 (26)
    • ►  04/07 - 04/14 (10)
    • ►  03/31 - 04/07 (34)
    • ►  03/24 - 03/31 (10)
    • ►  03/03 - 03/10 (35)
    • ►  02/25 - 03/03 (15)
    • ►  02/04 - 02/11 (22)
    • ►  01/28 - 02/04 (30)
    • ►  01/07 - 01/14 (8)
  • ►  2023 (484)
    • ►  12/31 - 01/07 (35)
    • ►  12/24 - 12/31 (10)
    • ►  12/03 - 12/10 (33)
    • ►  11/26 - 12/03 (20)
    • ►  11/05 - 11/12 (35)
    • ►  10/29 - 11/05 (20)
    • ►  10/22 - 10/29 (9)
    • ►  10/15 - 10/22 (7)
    • ►  10/08 - 10/15 (9)
    • ►  10/01 - 10/08 (10)
    • ►  09/24 - 10/01 (9)
    • ►  09/17 - 09/24 (9)
    • ►  09/10 - 09/17 (7)
    • ►  09/03 - 09/10 (9)
    • ►  08/27 - 09/03 (9)
    • ►  08/20 - 08/27 (8)
    • ►  08/13 - 08/20 (8)
    • ►  08/06 - 08/13 (8)
    • ►  07/30 - 08/06 (8)
    • ►  07/23 - 07/30 (7)
    • ►  07/16 - 07/23 (8)
    • ►  07/09 - 07/16 (7)
    • ►  07/02 - 07/09 (8)
    • ►  06/25 - 07/02 (7)
    • ►  06/18 - 06/25 (7)
    • ►  06/11 - 06/18 (7)
    • ►  06/04 - 06/11 (11)
    • ►  05/28 - 06/04 (7)
    • ►  05/21 - 05/28 (8)
    • ►  05/14 - 05/21 (11)
    • ►  05/07 - 05/14 (7)
    • ►  04/30 - 05/07 (7)
    • ►  04/23 - 04/30 (8)
    • ►  04/16 - 04/23 (9)
    • ►  04/09 - 04/16 (7)
    • ►  04/02 - 04/09 (4)
    • ►  03/26 - 04/02 (21)
    • ►  03/19 - 03/26 (2)
    • ►  03/12 - 03/19 (9)
    • ►  03/05 - 03/12 (26)
    • ►  02/26 - 03/05 (25)
    • ►  01/15 - 01/22 (7)
    • ►  01/08 - 01/15 (1)
  • ►  2022 (1037)
    • ►  12/11 - 12/18 (13)
    • ►  12/04 - 12/11 (1)
    • ►  11/27 - 12/04 (40)
    • ►  11/06 - 11/13 (1)
    • ►  10/16 - 10/23 (13)
    • ►  09/04 - 09/11 (5)
    • ►  08/21 - 08/28 (24)
    • ►  08/14 - 08/21 (24)
    • ►  07/03 - 07/10 (9)
    • ►  06/19 - 06/26 (3)
    • ►  05/29 - 06/05 (3)
    • ►  05/22 - 05/29 (3)
    • ►  05/15 - 05/22 (109)
    • ►  05/01 - 05/08 (7)
    • ►  04/24 - 05/01 (7)
    • ►  04/17 - 04/24 (64)
    • ►  04/10 - 04/17 (115)
    • ►  04/03 - 04/10 (73)
    • ►  03/27 - 04/03 (77)
    • ►  03/13 - 03/20 (2)
    • ►  03/06 - 03/13 (25)
    • ►  02/27 - 03/06 (18)
    • ►  02/20 - 02/27 (153)
    • ►  02/13 - 02/20 (187)
    • ►  01/30 - 02/06 (45)
    • ►  01/23 - 01/30 (15)
    • ►  01/16 - 01/23 (1)
  • ▼  2021 (412)
    • ►  10/24 - 10/31 (2)
    • ►  07/25 - 08/01 (1)
    • ►  07/11 - 07/18 (10)
    • ►  06/13 - 06/20 (29)
    • ►  05/23 - 05/30 (1)
    • ►  05/02 - 05/09 (24)
    • ►  04/25 - 05/02 (24)
    • ►  04/18 - 04/25 (112)
    • ►  04/11 - 04/18 (1)
    • ►  04/04 - 04/11 (6)
    • ▼  03/28 - 04/04 (86)
      • Translate Laravel Languages with Google Sheets
      • Laravel Process Stamps Logs the Process Used to Up...
      • Laravel Google Translate
      • Junges Laravel ACL Packages
      • Laravel Money
      • MailEclipse: Laravel Mail Editor Package
      • Laravel Blade Filters Package
      • Eloquent Cloner Package
      • Laravel Search String
      • Laravel Custom Casts Package
      • Aire Form Builder Package for Laravel
      • Add Social Reactions to Model with Laravel Love
      • PHP Array Redactor
      • Advanced State Support for Laravel Models
      • Laravel Geocoding
      • API Logger Package
      • ClamAV Scanner for Flysystem
      • Mask Sensitive Data With the PHP Masked Package
      • Laravel Stats 2.0 is Here
      • Laravel Scopes Generator
      • Laravel Fireable Attributes
      • Sign In With Apple for Laravel Socialite
      • Send Notifications for Exceptions with the Notifia...
      • Mute and Unmute Model Observers With Unobserve
      • Useful Laravel Validation Rule Packages
      • A REST Client Inside Your Laravel Projects
      • HTTP Client That Handles Retries and Logging
      • Laravel REST API Response Builder
      • Laravel Validator Object-Oriented Wrapper
      • Send Users a Welcome Notification to Set an Initia...
      • Automate App Setup with Laravel Initializer
      • Laravel Translation Scanner
      • Ably Broadcast Driver for Laravel
      • Laravel Package to Work With Paddle.com
      • Laravel Shift Blueprint
      • Laravel Exchange Rates API Package
      • Canvas: A Laravel Publishing Platform
      • Store Extra Columns as JSON With Laravel Overflow
      • Customizable Feedback Component for Laravel
      • Laravel Shared Data Package
      • Laravel Populated Factory
      • PHP Spellchecker Library
      • Encrypt Database Values in Laravel with DB Encrypter
      • Laravel Log Reader
      • Test Views with Laravel Mojito
      • Laravel JWT Redis
      • Server Timing Metrics for your Laravel Apps
      • Manage Invite Codes for Your Laravel Applications
      • Laravel Option Framework
      • Laravel Passwordless Login
      • Laravel Telescope Dev Toolbar Packages
      • Design Models Interactively With Laravel Schematics
      • Keep Track of Model Inventory with Laravel Stock
      • Manager Pattern Package for Laravel
      • Using Google Sheets with Eloquent
      • Terminal: An Elegant Wrapper around the Symfony Pr...
      • Class-Based Factories with Laravel Poser
      • Blade Icons Package
      • Pass Named Handler Arguments to Middleware in Laravel
      • Redaxios Fetch Wrapper With an Axios API
      • A TALL (Tailwind CSS, Alpine.js, Laravel, and Live...
      • Open Food Facts API
      • Manage Friendships, Likes and More with the Acquai...
      • Sub-Minute and Cron-less Scheduled Tasks in Laravel
      • Maravel Permissions Package for Laravel
      • Laravel Media Uploader
      • Direct Printing for Laravel Apps
      • Postgres Range Type Support for Laravel 7
      • Real-Time Chat Package for Laravel
      • Login As A Different User Quickly
      • PHP Progress Library to Track User Progress
      • Manage Job Workflows with Venture
      • Run Artisan Commands With a GUI
      • Generate and Extract Random Data with RandoPHP
      • Store Laravel Settings in a Database
      • Laravel Envoyer API Package
      • Encrypt and Decrypt Data Using Keys
      • Laravel User Activity
      • Add Spam Prevention to Laravel Apps with Honey
      • Eloquent State Machines
      • Socialite Implementation for Laravel Jetstream
      • Simplifying Service Providers With Laravel Package...
      • OpenAPI Initializer
      • Laravel SMTP Crack
      • Laravel Eloquent Power Joins Package
      • laravel with and where
    • ►  03/21 - 03/28 (19)
    • ►  03/14 - 03/21 (2)
    • ►  03/07 - 03/14 (10)
    • ►  02/28 - 03/07 (1)
    • ►  02/21 - 02/28 (29)
    • ►  02/14 - 02/21 (13)
    • ►  02/07 - 02/14 (12)
    • ►  01/31 - 02/07 (6)
    • ►  01/17 - 01/24 (2)
    • ►  01/10 - 01/17 (8)
    • ►  01/03 - 01/10 (14)
  • ►  2020 (376)
    • ►  12/27 - 01/03 (37)
    • ►  12/20 - 12/27 (92)
    • ►  12/13 - 12/20 (29)
    • ►  12/06 - 12/13 (37)
    • ►  11/29 - 12/06 (4)
    • ►  11/15 - 11/22 (14)
    • ►  11/08 - 11/15 (8)
    • ►  11/01 - 11/08 (2)
    • ►  10/18 - 10/25 (14)
    • ►  10/11 - 10/18 (16)
    • ►  10/04 - 10/11 (10)
    • ►  09/20 - 09/27 (10)
    • ►  09/06 - 09/13 (19)
    • ►  08/30 - 09/06 (26)
    • ►  08/23 - 08/30 (4)
    • ►  08/16 - 08/23 (2)
    • ►  07/12 - 07/19 (48)
    • ►  05/17 - 05/24 (2)
    • ►  01/05 - 01/12 (2)
  • ►  2019 (74)
    • ►  07/07 - 07/14 (6)
    • ►  06/16 - 06/23 (6)
    • ►  02/10 - 02/17 (17)
    • ►  01/13 - 01/20 (37)
    • ►  01/06 - 01/13 (8)
  • ►  2018 (376)
    • ►  12/30 - 01/06 (24)
    • ►  12/16 - 12/23 (8)
    • ►  12/09 - 12/16 (98)
    • ►  12/02 - 12/09 (16)
    • ►  11/18 - 11/25 (36)
    • ►  11/04 - 11/11 (18)
    • ►  10/28 - 11/04 (10)
    • ►  10/21 - 10/28 (26)
    • ►  10/14 - 10/21 (52)
    • ►  10/07 - 10/14 (4)
    • ►  09/30 - 10/07 (2)
    • ►  09/23 - 09/30 (68)
    • ►  09/16 - 09/23 (4)
    • ►  09/09 - 09/16 (4)
    • ►  08/26 - 09/02 (6)

Data Publish News

Loading...

Al Jazeera – Breaking News, World News and Video from Al Jazeera

Loading...

Laravel News

Loading...

Copyright © CoderFunda | Powered by Blogger
Design by Coderfunda | Blogger Theme by Coderfunda | Distributed By Coderfunda