Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor #5

Merged
merged 19 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3395cf2
Refactor BelongsToArrayColumn constructor
MrPunyapal Dec 11, 2023
b5893f9
Refactor mapToDictionary in HasManyArrayColumn.php
MrPunyapal Dec 11, 2023
1efa27e
Fix formatting in BelongsToArrayColumn and HasManyArrayColumn
MrPunyapal Dec 11, 2023
f5eedae
Refactor HasManyKeys class to use typed properties
MrPunyapal Dec 11, 2023
78fd498
Refactor relationship methods in HasExtendedRelationships trait
MrPunyapal Dec 11, 2023
f50a18d
Remove debug.log and refactor HasManyKeys constructor
MrPunyapal Dec 11, 2023
203970c
Refactor addConstraints and addEagerConstraints methods in HasManyArr…
MrPunyapal Dec 11, 2023
043582f
Refactor BelongsToArrayColumn class constructor and methods
MrPunyapal Dec 11, 2023
84e8dc5
Update BelongsToArrayColumn constructor signature
MrPunyapal Dec 11, 2023
f969c61
Refactor BelongsToManyKeys class to use typed properties
MrPunyapal Dec 11, 2023
98513d1
Refactor relation classes
MrPunyapal Dec 11, 2023
4a8c209
Add Laravel preset and enable strict types
MrPunyapal Dec 11, 2023
d43be4c
Add strict types declaration to PHP files
MrPunyapal Dec 11, 2023
acd1404
Refactor relatedNewQuery method in HasExtendedRelationships trait
MrPunyapal Dec 11, 2023
9ce1b3e
Refactor BelongsToManyKeys constructor signature
MrPunyapal Dec 11, 2023
088348a
Refactor BelongsToArrayColumn constructor signature
MrPunyapal Dec 11, 2023
0b7b602
Refactor constructor in HasManyKeys class
MrPunyapal Dec 11, 2023
ace4808
Refactor addConstraints method in Relations classes
MrPunyapal Dec 11, 2023
ddf63f7
Fix return type declaration in match() methods
MrPunyapal Dec 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config/extended-relationships.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

// config for Mrpunyapal/LaravelExtendedRelationships
return [

Expand Down
1 change: 0 additions & 1 deletion debug.log

This file was deleted.

8 changes: 8 additions & 0 deletions pint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"preset": "laravel",
"rules": {
"declare_strict_types": true,
"strict_param":true,
"strict_comparison":true
}
}
35 changes: 14 additions & 21 deletions src/HasExtendedRelationships.php
Original file line number Diff line number Diff line change
@@ -1,46 +1,39 @@
<?php

declare(strict_types=1);

namespace Mrpunyapal\LaravelExtendedRelationships;

use Illuminate\Contracts\Database\Query\Builder;
use Mrpunyapal\LaravelExtendedRelationships\Relations\BelongsToArrayColumn;
use Mrpunyapal\LaravelExtendedRelationships\Relations\BelongsToManyKeys;
use Mrpunyapal\LaravelExtendedRelationships\Relations\HasManyArrayColumn;
use Mrpunyapal\LaravelExtendedRelationships\Relations\HasManyKeys;

trait HasExtendedRelationships
{
/**
* @param string|null $foreignKey
* @param string[]|null $relations
*/
public function belongsToManyKeys(string $related, string $foreignKey, array $relations): BelongsToManyKeys
public function belongsToManyKeys(string $related, ?string $foreignKey, ?array $relations): BelongsToManyKeys
{
$instance = new $related();

return new BelongsToManyKeys($instance->newQuery(), $this, $foreignKey, $relations);
return new BelongsToManyKeys($this->relatedNewQuery($related), $this, $foreignKey, $relations);
}

/**
* @param string[]|null $relations
*/
public function hasManyKeys(string $related, ?array $relations = null, ?string $localKey = null): HasManyKeys
public function hasManyKeys(string $related, ?array $relations, ?string $localKey): HasManyKeys
{
$instance = new $related();

return new HasManyKeys($instance->newQuery(), $this, $relations, $localKey);
return new HasManyKeys($this->relatedNewQuery($related), $this, $relations, $localKey);
}

public function hasManyArrayColumn(string $related, ?string $foreignKey, ?string $localKey): HasManyArrayColumn
{
$instance = new $related();

return new HasManyArrayColumn($instance->newQuery(), $this, $foreignKey, $localKey);
return new HasManyArrayColumn($this->relatedNewQuery($related), $this, $foreignKey, $localKey);
}

public function belongsToArrayColumn(string $related, ?string $foreignKey, ?string $localKey, $isString = false): BelongsToArrayColumn
public function belongsToArrayColumn(string $related, ?string $foreignKey, ?string $localKey, bool $isString = false): BelongsToArrayColumn
{
$instance = new $related();
return new BelongsToArrayColumn($this->relatedNewQuery($related), $this, $foreignKey, $localKey, null, $isString);
}

return new BelongsToArrayColumn($instance->newQuery(), $this, $foreignKey, $localKey, null, $isString);
protected function relatedNewQuery($related): Builder
{
return (new $related())->newQuery();
}
}
58 changes: 20 additions & 38 deletions src/Relations/BelongsToArrayColumn.php
Original file line number Diff line number Diff line change
@@ -1,61 +1,47 @@
<?php

declare(strict_types=1);

namespace Mrpunyapal\LaravelExtendedRelationships\Relations;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class BelongsToArrayColumn extends BelongsTo
{
/**
* Indicates whether the value is a string.
*
* @var bool
*/
protected $isString;

/**
* Create a new belongs to relationship instance.
*
* @param string $foreignKey
* @param string $ownerKey
* @param string $relationName
* @param bool $isString
* @return void
* Create a new belongs to array Column relationship instance.
*/
public function __construct(Builder $query, Model $child, $foreignKey, $ownerKey, $relationName, $isString = false)
public function __construct(Builder $query, Model $child, string $foreignKey, string $ownerKey, ?string $relationName, protected bool $isString = false)
{
$this->isString = $isString;
parent::__construct($query, $child, $foreignKey, $ownerKey, $relationName);
}

/**
* Set the base constraints on the relation query.
*
* @return void
*/
public function addConstraints()
public function addConstraints(): void
{
if (static::$constraints) {
$query = $this->getBaseQuery();
if (! static::$constraints) {
return;
}
$query = $this->getBaseQuery();

$query->when($this->isString, function ($q) {
$q->whereJsonContains($this->ownerKey, (string) $this->getParentKey());
}, function ($q) {
$q->whereJsonContains($this->ownerKey, $this->getParentKey());
});
$query->when($this->isString, function ($q) {
$q->whereJsonContains($this->ownerKey, (string) $this->getParentKey());
}, function ($q) {
$q->whereJsonContains($this->ownerKey, $this->getParentKey());
});

$query->whereNotNull($this->ownerKey);
}
$query->whereNotNull($this->ownerKey);
}

/**
* Set the constraints for an eager load of the relation.
*
* @return void
*/
public function addEagerConstraints(array $models)
public function addEagerConstraints(array $models): void
{
$ids = $this->getEagerModelKeys($models);
$this->query->where(function ($q) use ($ids) {
Expand All @@ -72,18 +58,16 @@ public function addEagerConstraints(array $models)
/**
* Match the eagerly loaded results to their many parents.
*
* @param \Illuminate\Database\Eloquent\Collection $results
* @param string $relation
* @return array
*/
public function match(array $models, $results, $relation)
public function match(array $models, Collection $results, $relation): array
{
$owner = $this->getOwnerKeyName();
foreach ($models as $model) {
$id = $model->getAttribute($this->foreignKey);
$collection = collect();
foreach ($results as $data) {
if (in_array($id, $data->{$owner})) {
if (in_array($id, $data->{$owner}, true)) {
$collection->push($data);
}
}
Expand All @@ -95,10 +79,8 @@ public function match(array $models, $results, $relation)

/**
* Get the results of the relationship.
*
* @return mixed
*/
public function getResults()
public function getResults(): mixed
{
return $this->query->get();
}
Expand Down
70 changes: 33 additions & 37 deletions src/Relations/BelongsToManyKeys.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

namespace Mrpunyapal\LaravelExtendedRelationships\Relations;

use Illuminate\Database\Eloquent\Builder;
Expand All @@ -12,63 +14,51 @@ class BelongsToManyKeys extends Relation
/**
* The local keys of the parent model.
*
* @var string[]
* @var array<string>
*/
protected $localKeys;
protected array $localKeys;

/**
* The local keys of the parent model.
*
* @var string[]
*/
protected $relations;

/**
* The foreign key of the related model.
*
* @var string
* @var array<string>
*/
protected $foreignKey;
protected array $relations;

/**
* Create a new has one or many relationship instance.
*
* @param array $localKeys
* @return void
*/
public function __construct(Builder $query, Model $parent, string $foreignKey, array $relations)
public function __construct(Builder $query, Model $parent, protected string $foreignKey, array $relations)
{
$this->localKeys = array_keys($relations);
$this->foreignKey = $foreignKey;
$this->relations = $relations;
parent::__construct($query, $parent);
}

/**
* Set the base constraints on the relation query.
* Note: Used to load relations of one model.
*
* @return void
*/
public function addConstraints()
public function addConstraints(): void
{
if (static::$constraints) {
$this->query->where(function ($query) {
foreach ($this->localKeys as $localKey) {
$query->orWhere(function ($query) use ($localKey) {
$query->where($this->foreignKey, '=', $this->getParentKey($localKey))
->whereNotNull($this->foreignKey);
});
}
});
if (! static::$constraints) {
return;
}
$this->query->where(function ($query) {
foreach ($this->localKeys as $localKey) {
$query->orWhere(function ($query) use ($localKey) {
$query->where($this->foreignKey, '=', $this->getParentKey($localKey))
->whereNotNull($this->foreignKey);
});
}
});
}

/**
* Set the constraints for an eager load of the relation.
* Note: Used to load relations of multiple models at once.
*/
public function addEagerConstraints(array $models)
public function addEagerConstraints(array $models): void
{
$localKeys = $this->localKeys;
$foreignKey = $this->foreignKey;
Expand All @@ -83,9 +73,8 @@ public function addEagerConstraints(array $models)
* Initialize the relation on a set of models.
*
* @param string $relation
* @return array
*/
public function initRelation(array $models, $relation)
public function initRelation(array $models, $relation): array|Collection
{
foreach ($models as $model) {
$model->setRelation($relation, $this->related->newCollection());
Expand All @@ -94,7 +83,10 @@ public function initRelation(array $models, $relation)
return $models;
}

public function match(array $models, Collection $results, $relation)
/**
* Match the related models with the given models based on the local keys.
*/
public function match(array $models, Collection $results, $relation): array
{
$dictionary = $this->buildDictionary($results);

Expand All @@ -112,7 +104,10 @@ public function match(array $models, Collection $results, $relation)
return $models;
}

public function buildDictionary(Collection $models)
/**
* Build a dictionary using the given models.
*/
public function buildDictionary(Collection $models): array|Collection
{
$dictionary = [];
foreach ($models as $model) {
Expand All @@ -122,17 +117,18 @@ public function buildDictionary(Collection $models)
return $dictionary;
}

public function getParentKey($localKey)
/**
* Get the parent key value for the given local key.
*/
public function getParentKey(string $localKey): mixed
{
return $this->parent->getAttribute($localKey);
}

/**
* Get the results of the relationship.
*
* @return mixed
*/
public function getResults()
public function getResults(): mixed
{
if (! static::$constraints) {
return $this->query->get();
Expand Down
Loading