Skip to content

Commit

Permalink
Use WeakMap instead of dynamic property + Add cloneWithJoinRelBuilder…
Browse files Browse the repository at this point in the history
… macro
  • Loading branch information
lgtaxn committed Feb 21, 2024
1 parent dc30322 commit bef618e
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 7 deletions.
6 changes: 6 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Changelog
=========

3.3.0 (2024-02-21)
------------------

- Use WeakMap instead of dynamic property to store JoinRelBuilder instance and avoid deprecation notice
- Add cloneWithJoinRelBuilder macro

3.2.0 (2023-02-20)
------------------

Expand Down
28 changes: 27 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Note that the default order is automatically disabled if you manually set `ORDER

This is the most important feature of this package: you can do joins using Eloquent relationships!

WARNING: only BelongsTo, HasOne, HasMany, MorphOne and MorphMany relations are supported.
**WARNING:** only BelongsTo, HasOne, HasMany, MorphOne and MorphMany relations are supported.
So, if you want to use BelongsToMany, you have to go with the HasMany/BelongsTo relations
to/from the pivot table.

Expand Down Expand Up @@ -158,6 +158,32 @@ class User extends Model
}
```

**WARNING:** an instance of JoinRelBuilder is created and attached to the Eloquent Builder instance
via WeakMap to handle this feature. If you ever clone the Builder instance, note that there is
no cloning of the attached JoinRelBuilder instance. This can be a problem if you use "joinRel"
on the cloned instance with a reference to an alias created in the original instance.

For example:

```php
$originalBuilder = User::joinRel('userHasRoles');

$clonedBuilder = clone $originalBuilder;

// Produces error: No model with alias "userHasRoles"
$clonedBuilder->joinRel('userHasRoles.role');
```

If you need to handle this case, use the "cloneWithJoinRelBuilder" method instead of clone:

```php
$originalBuilder = User::joinRel('userHasRoles');

$clonedBuilder = $originalBuilder->cloneWithJoinRelBuilder();

$clonedBuilder->joinRel('userHasRoles.role');
```


### Eloquent whereHasIn macro

Expand Down
4 changes: 2 additions & 2 deletions src/Eloquent/JoinRelBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function apply(Builder $query, $relationName, $alias = null, $callback =
$parentAlias = $query->getModel()->getTable();
}

if (!isset($this->models[$parentAlias])) {
if (! isset($this->models[$parentAlias])) {
throw new JoinRelException('No model with alias "'.$parentAlias.'".');
}

Expand Down Expand Up @@ -116,7 +116,7 @@ protected function addCondition(JoinClause $join, Relation $relation, $callback,
$join->where($morphType, '=', $relation->getMorphClass());
}

if (!$withTrashed && method_exists($relation->getRelated(), 'getQualifiedDeletedAtColumn')) {
if (! $withTrashed && method_exists($relation->getRelated(), 'getQualifiedDeletedAtColumn')) {
$join->whereNull($relation->getRelated()->getQualifiedDeletedAtColumn());
}

Expand Down
31 changes: 27 additions & 4 deletions src/Eloquent/Mixins/JoinRelMixin.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public function alias()
{
return function ($alias) {
$this->model->setTable($alias);

return $this->from((new $this->model)->getTable().' as '.$alias);
};
}
Expand All @@ -33,12 +33,17 @@ public function alias()
public function joinRel()
{
return function ($relationName, $alias = null, $callback = null, $type = 'inner', $withTrashed = false) {
global $_joinRelBuildersWeakMap;

if (! isset($_joinRelBuildersWeakMap)) {
$_joinRelBuildersWeakMap = new \WeakMap;
}

if (!isset($this->joinRelBuilder)) {
$this->joinRelBuilder = new JoinRelBuilder($this->model);
if (! isset($_joinRelBuildersWeakMap[$this])) {
$_joinRelBuildersWeakMap[$this] = new JoinRelBuilder($this->model);
}

$this->joinRelBuilder->apply($this, $relationName, $alias, $callback, $type, $withTrashed);
$_joinRelBuildersWeakMap[$this]->apply($this, $relationName, $alias, $callback, $type, $withTrashed);

return $this;
};
Expand Down Expand Up @@ -118,4 +123,22 @@ public function rightJoinRelWithTrashed()
return $this->joinRel($relationName, $alias, $callback, 'right', true);
};
}

/**
* Clone builder with corresponding JoinRelBuilder instance (in WeakMap).
*
* @return Builder
*/
public function cloneWithJoinRelBuilder()
{
return function () {
global $_joinRelBuildersWeakMap;

$clone = clone $this;

$_joinRelBuildersWeakMap[$clone] = clone $_joinRelBuildersWeakMap[$this];

return $clone;
};
}
}

0 comments on commit bef618e

Please sign in to comment.