Skip to content

Commit

Permalink
Merged master into pr/104
Browse files Browse the repository at this point in the history
  • Loading branch information
luisdalmolin committed Oct 2, 2024
2 parents 58c627f + 397ef08 commit a5c8673
Show file tree
Hide file tree
Showing 29 changed files with 1,670 additions and 654 deletions.
36 changes: 26 additions & 10 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,35 @@ jobs:
strategy:
fail-fast: true
matrix:
php: [7.4, 8.0, 8.1]
laravel: [7.*, 8.*, 9.*]
php: [8.0, 8.1, 8.2, 8.3]
laravel: [8.*, 9.*, 10.*, 11.*]
include:
- laravel: 11.*
testbench: 9.*-dev
- laravel: 10.*
testbench: 8.*
- laravel: 9.*
testbench: 7.*
- laravel: 8.*
testbench: 6.*
- laravel: 7.*
testbench: 5.*
exclude:
- laravel: 9.*
php: 7.4
- laravel: 7.*
- laravel: 11.*
php: 8.0
- laravel: 11.*
php: 8.1
- laravel: 10.*
php: 8.0
- laravel: 8.*
php: 8.1
- laravel: 8.*
php: 8.2
- laravel: 9.*
php: 8.2
- laravel: 8.*
php: 8.3
- laravel: 9.*
php: 8.3


name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}

Expand All @@ -49,13 +64,14 @@ jobs:
php-version: ${{ matrix.php }}
extensions: curl, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, iconv
coverage: none
tools: composer:v1
tools: composer:v2

- name: Install dependencies
run: |
composer --version
composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest
composer require "laravel/framework:${{ matrix.laravel }}" --no-interaction --no-update
composer require "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update --dev
composer update --prefer-dist --no-interaction --no-suggest --dev
composer dump
- name: Execute tests
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ vendor
coverage
.phpunit.result.cache
.php_cs.cache
.envrc
91 changes: 39 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
![Eloquent Power Joins](screenshots/eloquent-power-joins.jpg "Eloquent Power Joins")

![Laravel Supported Versions](https://img.shields.io/badge/laravel-6.x/7.x/8.x/9.x-green.svg)
[![Actions Status](https://github.com/kirschbaum-development/eloquent-power-joins/workflows/CI/badge.svg)](https://github.com/kirschbaum-development/eloquent-power-joins/actions)
![Laravel Supported Versions](https://img.shields.io/badge/laravel-8.x/9.x/10.x/11.x-green.svg)
[![run-tests](https://github.com/kirschbaum-development/eloquent-power-joins/actions/workflows/ci.yaml/badge.svg)](https://github.com/kirschbaum-development/eloquent-power-joins/actions/workflows/ci.yaml)
[![MIT Licensed](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)
[![Latest Version on Packagist](https://img.shields.io/packagist/v/kirschbaum-development/eloquent-power-joins.svg?style=flat-square)](https://packagist.org/packages/kirschbaum-development/eloquent-power-joins)
[![Total Downloads](https://img.shields.io/packagist/dt/kirschbaum-development/eloquent-power-joins.svg?style=flat-square)](https://packagist.org/packages/kirschbaum-development/eloquent-power-joins)
Expand All @@ -17,7 +17,7 @@ A few things we consider is missing when using joins which are very powerful Elo
* Ability to query relationship existence using joins instead of where exists;
* Ability to easily sort results based on columns or aggregations from related tables;

You can read a more detailed explanation on the problems this package solves on [this blog post](https://kirschbaumdevelopment.com/news-articles/adding-some-laravel-magic-to-your-eloquent-joins).
You can read a more detailed explanation on the problems this package solves on [this blog post](https://kirschbaumdevelopment.com/insights/power-joins).

## Installation

Expand All @@ -27,19 +27,14 @@ You can install the package via composer:
composer require kirschbaum-development/eloquent-power-joins
```

## Usage

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

```php
use Kirschbaum\PowerJoins\PowerJoins;
For Laravel versions < 8, use the 2.* version:

class User extends Model
{
use PowerJoins;
}
```bash
composer require kirschbaum-development/eloquent-power-joins:2.*
```

## Usage

This package provides a few features.

### 1 - Join Relationship
Expand Down Expand Up @@ -73,35 +68,42 @@ User::rightJoinRelationship('posts.comments');

#### Joining polymorphic relationships

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.
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 = Post::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.

```php
Post::joinRelationship('images');
```

You can also join MorphTo relationships.

```php
Image::joinRelationship('imageable', morphable: Post::class);
```

Note: Querying morph to relationships only supports one morphable type at a time.

**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.

```php
User::joinRelationship('posts', function ($join) {
$join->where('posts.approved', true);
})->toSql();
User::joinRelationship('posts', fn ($join) => $join->where('posts.approved', true))->toSql();
```

You can also specify the type of join you want to make in the callback:

```php
User::joinRelationship('posts', fn ($join) => $join->left());
```

For **nested calls**, you simply need to pass an array referencing the relationship names.

```php
User::joinRelationship('posts.comments', [
'posts' => function ($join) {
$join->where('posts.published', true);
},
'comments' => function ($join) {
$join->where('comments.approved', true);
$join->left(); // you may also indicate join type using methods ->left()/->inner()
}
'posts' => fn ($join) => $join->where('posts.published', true),
'comments' => fn ($join) => $join->where('comments.approved', true),
]);
```

Expand All @@ -114,9 +116,7 @@ User::joinRelationship('groups', [
// ...
},
// group_members is the intermediary table here
'group_members' => function ($join) {
$join->where('group_members.active', true);
},
'group_members' => fn ($join) => $join->where('group_members.active', true),
]
]);
```
Expand Down Expand Up @@ -163,12 +163,8 @@ Post::joinRelationshipUsingAlias('category', 'category_alias')->get();

```php
Post::joinRelationship('category.parent', [
'category' => function ($join) {
$join->as('category_alias');
},
'parent' => function ($join) {
$join->as('category_parent');
},
'category' => fn ($join) => $join->as('category_alias'),
'parent' => fn ($join) => $join->as('category_parent'),
])->get()
```

Expand All @@ -177,12 +173,8 @@ For *belongs to many* or *has many through* calls, you need to pass an array wit
```php
Group::joinRelationship('posts.user', [
'posts' => [
'posts' => function ($join) {
$join->as('posts_alias');
},
'post_groups' => function($join) {
$join->as('post_groups_alias');
},
'posts' => fn ($join) => $join->as('posts_alias'),
'post_groups' => fn ($join) => $join->as('post_groups_alias'),
],
])->toSql();
```
Expand Down Expand Up @@ -214,17 +206,13 @@ and "users"."deleted_at" is null
In case you want to include trashed models, you can call the `->withTrashed()` method in the join callback.

```php
UserProfile::joinRelationship('users', function ($join) {
$join->withTrashed();
});
UserProfile::joinRelationship('users', fn ($join) => $join->withTrashed());
```

You can also call the `onlyTrashed` model as well:

```php
UserProfile::joinRelationship('users', function ($join) {
$join->onlyTrashed();
});
UserProfile::joinRelationship('users', ($join) => $join->onlyTrashed());
```

#### Extra conditions defined in relationships
Expand Down Expand Up @@ -252,9 +240,7 @@ select users.* from users inner join posts on posts.user_id = posts.id and posts
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:

```php
UserProfile::joinRelationship('users', function ($join) {
$join->withGlobalScopes();
});
UserProfile::joinRelationship('users', fn ($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.
Expand All @@ -265,15 +251,16 @@ There's, though, a gotcha here. Your global scope **cannot** type-hint the `Eloq

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.

Please note that although the methods are similar, you will not always get the same results when using joins, depending on the context of your query. You should be aware of the differences between querying the data with `where exists` vs `joins`.

**Laravel Native Methods**

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

Expand Down Expand Up @@ -351,7 +338,7 @@ Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

### Security

If you discover any security related issues, please email [email protected] or nathan@kirschbaumdevelopment.com instead of using the issue tracker.
If you discover any security related issues, please email security@kirschbaumdevelopment.com instead of using the issue tracker.

## Credits

Expand Down
12 changes: 5 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
}
],
"require": {
"php": "^7.1|^8.0",
"illuminate/support": "^6.0|^7.0|^8.0|^9.0",
"illuminate/database": "^6.0|^7.0|^8.0|^9.0"
"php": "^8.0",
"illuminate/support": "^8.0|^9.0|^10.0|^11.0",
"illuminate/database": "^8.0|^9.0|^10.0|^11.0"
},
"require-dev": {
"laravel/legacy-factories": "^1.0@dev",
"orchestra/testbench": "4.*|5.*|6.*|7.*",
"phpunit/phpunit": "^8.0|^9.0"
"orchestra/testbench": "^4.0|^5.0|^6.0|^7.0|^8.0|^9.0",
"phpunit/phpunit": "^8.0|^9.0|^10.0"
},
"autoload": {
"psr-4": {
Expand All @@ -40,7 +40,6 @@
"scripts": {
"test": "vendor/bin/phpunit",
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"

},
"config": {
"sort-packages": true
Expand All @@ -52,6 +51,5 @@
]
}
},

"minimum-stability": "dev"
}
7 changes: 4 additions & 3 deletions src/FakeJoinCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

namespace Kirschbaum\PowerJoins;

class FakeJoinCallback
/**
* @method static as(string $alias)
*/
class FakeJoinCallback extends PowerJoinClause
{
protected $alias = null;

protected ?string $joinType = null;

public function getAlias(): ?string
Expand Down
Loading

0 comments on commit a5c8673

Please sign in to comment.