Skip to content

Commit b977610

Browse files
committed
Improve DX for dynamically adding relationships
This improves the developer experience for dynamically adding relationships to an external model when extending the model. Previously the developer would have to set the relation property directly themselves by merging their additions with the existing definitions and usually they wouldn't include any error checking logic.
1 parent 0af5c16 commit b977610

1 file changed

Lines changed: 160 additions & 1 deletion

File tree

src/Database/Concerns/HasRelationships.php

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ trait HasRelationships
134134
'hasManyThrough'
135135
];
136136

137-
138137
//
139138
// Relations
140139
//
@@ -785,4 +784,164 @@ protected function setRelationValue($relationName, $value)
785784
{
786785
$this->$relationName()->setSimpleValue($value);
787786
}
787+
788+
/**
789+
* Dynamically add the provided relationship configuration to the local properties
790+
*
791+
* @throws InvalidArgumentException if the $type is invalid or if the $name is already in use
792+
*/
793+
protected function addRelation(string $type, string $name, array $config): void
794+
{
795+
if (!in_array($type, static::$relationTypes)) {
796+
throw new InvalidArgumentException(
797+
sprintf('Cannot add the "%s" relation to %s, %s is not a valid relationship type.',
798+
$name,
799+
get_class($this),
800+
$type
801+
)
802+
);
803+
}
804+
805+
if ($this->hasRelation($name) || isset($this->{$name})) {
806+
throw new InvalidArgumentException(
807+
sprintf('Cannot add the "%s" relation to %s, it conflicts with an existing relation, attribute, or property.',
808+
$name,
809+
get_class($this),
810+
$name
811+
)
812+
);
813+
}
814+
815+
$this->{$type} = array_merge($this->{$type}, [$name => $config]);
816+
}
817+
818+
/**
819+
* Dynamically add a HasOne relationship
820+
*
821+
* @throws InvalidArgumentException if the provided relationship is already defined
822+
*/
823+
public function addHasOneRelation(string $name, array $config): void
824+
{
825+
$this->addRelation('hasOne', $name, $config);
826+
}
827+
828+
/**
829+
* Dynamically add a HasMany relationship
830+
*
831+
* @throws InvalidArgumentException if the provided relationship is already defined
832+
*/
833+
public function addHasManyRelation(string $name, array $config): void
834+
{
835+
$this->addRelation('hasMany', $name, $config);
836+
}
837+
838+
/**
839+
* Dynamically add a BelongsTo relationship
840+
*
841+
* @throws InvalidArgumentException if the provided relationship is already defined
842+
*/
843+
public function addBelongsToRelation(string $name, array $config): void
844+
{
845+
$this->addRelation('belongsTo', $name, $config);
846+
}
847+
848+
/**
849+
* Dynamically add a BelongsToMany relationship
850+
*
851+
* @throws InvalidArgumentException if the provided relationship is already defined
852+
*/
853+
public function addBelongsToManyRelation(string $name, array $config): void
854+
{
855+
$this->addRelation('belongsToMany', $name, $config);
856+
}
857+
858+
/**
859+
* Dynamically add a MorphTo relationship
860+
*
861+
* @throws InvalidArgumentException if the provided relationship is already defined
862+
*/
863+
public function addMorphToRelation(string $name, array $config): void
864+
{
865+
$this->addRelation('morphTo', $name, $config);
866+
}
867+
868+
/**
869+
* Dynamically add a MorphOne relationship
870+
*
871+
* @throws InvalidArgumentException if the provided relationship is already defined
872+
*/
873+
public function addMorphOneRelation(string $name, array $config): void
874+
{
875+
$this->addRelation('morphOne', $name, $config);
876+
}
877+
878+
/**
879+
* Dynamically add a MorphMany relationship
880+
*
881+
* @throws InvalidArgumentException if the provided relationship is already defined
882+
*/
883+
public function addMorphManyRelation(string $name, array $config): void
884+
{
885+
$this->addRelation('morphMany', $name, $config);
886+
}
887+
888+
/**
889+
* Dynamically add a MorphToMany relationship
890+
*
891+
* @throws InvalidArgumentException if the provided relationship is already defined
892+
*/
893+
public function addMorphToManyRelation(string $name, array $config): void
894+
{
895+
$this->addRelation('morphToMany', $name, $config);
896+
}
897+
898+
/**
899+
* Dynamically add a MorphedByMany relationship
900+
*
901+
* @throws InvalidArgumentException if the provided relationship is already defined
902+
*/
903+
public function addMorphedByManyRelation(string $name, array $config): void
904+
{
905+
$this->addRelation('morphedByMany', $name, $config);
906+
}
907+
908+
/**
909+
* Dynamically add an AttachOne relationship
910+
*
911+
* @throws InvalidArgumentException if the provided relationship is already defined
912+
*/
913+
public function addAttachOneRelation(string $name, array $config): void
914+
{
915+
$this->addRelation('attachOne', $name, $config);
916+
}
917+
918+
/**
919+
* Dynamically add an AttachMany relationship
920+
*
921+
* @throws InvalidArgumentException if the provided relationship is already defined
922+
*/
923+
public function addAttachManyRelation(string $name, array $config): void
924+
{
925+
$this->addRelation('attachMany', $name, $config);
926+
}
927+
928+
/**
929+
* Dynamically add a(n) HasOneThrough relationship
930+
*
931+
* @throws InvalidArgumentException if the provided relationship is already defined
932+
*/
933+
public function addHasOneThroughRelation(string $name, array $config): void
934+
{
935+
$this->addRelation('HasOneThrough', $name, $config);
936+
}
937+
938+
/**
939+
* Dynamically add a(n) HasManyThrough relationship
940+
*
941+
* @throws InvalidArgumentException if the provided relationship is already defined
942+
*/
943+
public function addHasManyThroughRelation(string $name, array $config): void
944+
{
945+
$this->addRelation('HasManyThrough', $name, $config);
946+
}
788947
}

0 commit comments

Comments
 (0)