The Laravel magic you know, now applied to joins.
Joins are very useful in a lot of ways. If you are here, you most likely know about and use them. Eloquent is very powerful, but it lacks a bit of the "Laravel way" when using joins. This package make your joins in a more Laravel way, with more readable with less code while hiding implementation details from places they don't need to be exposed.
A few things we consider is missing when using joins which are very powerful Eloquent features:
You can read a more detailed explanation on the problems this package solves on this blog post.
You can install the package via composer:
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;
}
This package provides a few features.
Let's say you have a User
model with a hasMany
relationship to the Post
model. If you want to join the tables, you would usually write something like:
User::select('users.*')->join('posts', 'posts.user_id', '=', 'users.id');
This package provides you with a new joinRelationship()
method, which does the exact same thing.
User::joinRelationship('posts');
Both options produce the same results. In terms of code, you didn't save THAT much, but you are now using the relationship between the User
and the Post
models to join the tables. This means that you are now hiding how this relationship works behind the scenes (implementation details). You also don't need to change the code if the relationship type changes. You now have more readable and less overwhelming code.
But, it gets better when you need to join nested relationships. Let's assume you also have a hasMany
relationship between the Post
and Comment
models and you need to join these tables, you can simply write:
User::joinRelationship('posts.comments');
So much better, wouldn't you agree?! You can also left
or right
join the relationships as needed.
User::leftJoinRelationship('posts.comments');
User::rightJoinRelationship('posts.comments');
Let's imagine, you have a Image
model that is a polymorphic relationship (Post -> morphMany -> Image
). Besides the regular join, you would also need to apply the where imageable_type = Image::class
condition, otherwise you could get messy results.
Turns out, if you join a polymorphic relationship, Eloquent Power Joins automatically applies this condition for you. You simply need to call the same method.
Post::joinRelationship('images');
Applying conditions & callbacks to the joins
Now, let's say you want to apply a condition to the join you are making. You simply need to pass a callback as the second parameter to the joinRelationship
method.
User::joinRelationship('posts', function ($join) {
$join->where('posts.approved', true);
})->toSql();
For nested calls, you simply need to pass an array referencing the relationship names.
User::joinRelationship('posts.comments', [
'posts' => function ($join) {
$join->where('posts.published', true);
},
'comments' => function ($join) {
$join->where('comments.approved', true);
}
]);
For belongs to many calls, you need to pass an array with the relationship, and then an array with the table names.
User::joinRelationship('groups', [
'groups' => [
'groups' => function ($join) {
// ...
},
// group_members is the intermediary table here
'group_members' => function ($join) {
$join->where('group_members.active', true);
},
]
]);
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::joinRelationship('posts', function ($join) {
// the $join instance here can access any of the scopes defined in Post ��
$join->published();
});
When using model scopes inside a join clause, you can't type hint the $query
parameter in your scope. Also, keep in mind you are inside a join, so you are limited to use only conditions supported by joins.
Sometimes, you are going to need to use table aliases on your joins because you are joining the same table more than once. One option to accomplish this is to use the joinRelationshipUsingAlias
method.
Post::joinRelationshipUsingAlias('category.parent')->get();
In case you need to specify the name of the alias which is going to be used, you can do in two different ways:
Post::joinRelationshipUsingAlias('category', 'category_alias')->get();
as
function inside the join callback.Post::joinRelationship('category.parent', [
'category' => function ($join) {
$join->as('category_alias');
},
'parent' => function ($join) {
$join->as('category_parent');
},
])->get()
When making joins, using select * from ...
can be dangerous as fields with the same name between the parent and the joined tables could conflict. Thinking on that, if you call the joinRelationship
method without previously selecting any specific columns, Eloquent Power Joins will automatically include that for you. For instance, take a look at the following examples:
User::joinRelationship('posts')->toSql();
// select users.* from users inner join posts on posts.user_id = users.id
And, if you specify the select statement:
User::select('users.id')->joinRelationship('posts')->toSql();
// select users.id from users inner join posts on posts.user_id = users.id
When joining any models which uses the SoftDeletes
trait, the following condition will be also automatically applied to all your joins:
and "users"."deleted_at" is null
In case you want to include trashed models, you can call the ->withTrashed()
method in the join callback.
UserProfile::joinRelationship('users', function ($join) {
$join->withTrashed();
});
You can also call the onlyTrashed
model as well:
UserProfile::joinRelationship('users', function ($join) {
$join->onlyTrashed();
});
If you have extra conditions in your relationship definitions, they will get automatically applied for you.
class User extends Model
{
public function publishedPosts()
{
return $this->hasMany(Post::class)->published();
}
}
If you call User::joinRelationship('publishedPosts')->get()
, it will also apply the additional published scope to the join clause. It would produce an SQL more or less like this:
select users.* from users inner join posts on posts.user_id = posts.id and posts.published = 1
If your model have global scopes applied to it, you can enable the global scopes by calling the withGlobalScopes
method in your join clause, like this:
UserProfile::joinRelationship('users', function ($join) {
$join->withGlobalScopes();
});
There's, though, a gotcha here. Your global scope cannot type-hint the Eloquent\Builder
class in the first parameter of the apply
method, otherwise you will get errors.
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 may not be the more performant choice, depending on how many records you have or the structure of your tables.
This packages implements the same functionality, but instead of using the where exists
syntax, it uses joins. 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 equivalent, but using joins
User::powerJoinHas('posts');
User::powerJoinHas('posts.comments');
User::powerJoinHas('posts.comments', '>', 3);
User::powerJoinWhereHas('posts', function ($join) {
$join->where('posts.published', true);
});
User::powerJoinDoesntHave('posts');
You can also sort your query results using a column from another table using the orderByPowerJoins
method.
User::orderByPowerJoins('profile.city');
If you need to pass some raw values for the order by function, you can do like this:
User::orderByPowerJoins(['profile', DB::raw('concat(city, ", ", state)']);
This query will sort the results based on the city
column on the user_profiles
table. 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 can do this:
$users = User::orderByPowerJoinsCount('posts.id', 'desc')->get();
Or, to get the list of posts where the comments contain the highest average of votes.
$posts = Post::orderByPowerJoinsAvg('comments.votes', 'desc')->get();
You also have methods for SUM
, MIN
and MAX
:
Post::orderByPowerJoinsSum('comments.votes');
Post::orderByPowerJoinsMin('comments.votes');
Post::orderByPowerJoinsMax('comments.votes');
In case you want to use left joins in sorting, you also can:
Post::orderByLeftPowerJoinsCount('comments.votes');
Post::orderByLeftPowerJoinsAvg('comments.votes');
Post::orderByLeftPowerJoinsSum('comments.votes');
Post::orderByLeftPowerJoinsMin('comments.votes');
Post::orderByLeftPowerJoinsMax('comments.votes');
Please see CONTRIBUTING for details.
If you discover any security related issues, please email luis@kirschbaumdevelopment.com or nathan@kirschbaumdevelopment.com instead of using the issue tracker.
Development of this package is sponsored by Kirschbaum Development Group, a developer driven company focused on problem solving, team building, and community. Learn more about us or join us!
The MIT License (MIT). Please see License File for more information.
This package was generated using the Laravel Package Boilerplate.
Eloquent: Relationships Introduction Defining Relationships One To One One To Many Many To Many Has Many Through Polymorphic Relations Many To Many Polymorphic Relations Querying Relations Eager Loadi
简介 Laravel 自带的 Eloquent ORM 为您的数据库提供了一个优雅的、简单的 ActiveRecord 实现。每一个数据库的表有一个对应的 "Model" 用来与这张表交互。 在开始之前,确认已在 app/config/database.php 文件中配置好数据库连接。 基本用法 首先,创建一个 Eloquent 模型。模型通常在 app/models 目录,但是您可以自由地把它们
What is Join? --------------------- •In a straightforward a join is a query that combines rows from two or more tables, views, or materialized views. •Oracle Database performs a join whenever multiple
(渣翻译,娱乐向,消遣读物,感谢有道词典,百度翻译等). 原文:传送门 ELOQUENT JAVASCRIPT Written by Marijn Haverbeke 介绍: 这是一本让计算机变成类似于’你的女仆‘一样存在的书,让它做你想让它做的事情 →_→。 现在,计算机变的越来越和螺丝刀一样平常了,但是它们依然
Powerjson 是由 JSON 改进而成的数据交换格式,它将 JSON 支持了部分 JavaScript 语法,使其更加高效可用,并且解决了许多 JSON 历史遗留下来的问题。 它支持 单引号字符串, 多行字符串, 注释, 运算符, 导入文件, 导入其它 PJSON 文件 等。 Simple Demo { // 字符串 helloText: 'hello world', Mu
Power*Architect 是一个数据建模工具,主要用在数据仓库和数据集市的模型设计。 It allows the designer to open multiple concurrent source database connections, create and explore profiles of the source data, discover differences betwe
PowerPlot是一个iOS可视化类库,可以用于科学和商业领域的可视化图表绘制。可以绘制柱状图、折线图等等,是一个可以高度定制化的类库,满足开发者大部分可视化绘制需求。 [Code4App.com]
station-power 是方便于springboot的爱好者的开发权限拦截。 用安全管理框架就是为了方便,其实每个人都可以自己写那些基础的拦截,在shiro和security中都会有各自的session,在实际的项目中总会碰到各种互相干扰的因素,尤其是在配置启动的时候,在shiro用cache的时候,就无法用spring的cacheable的机制,所以自己弄一个完全基于spring的sessi
ORM written in Typescript, inspired by Laravel Eloquent, supports Mongodb/Mongoose. Warning: This is a documentation for v0.4.x, if you are using v0.3.x please checkout readme for v0.3.x in here. If y
Sortable behaviour for Eloquent models This package provides a trait that adds sortable behaviour to an Eloquent model. The value of the order column of a new record of a model is determined by the ma