feat: ✨ [NEW FEATURE]Create relation between Item and Event, Item and Place, Place and Event #499
Conversation
[skip ci]
…ion was done for api_log in place
|
…relation_between_Item_and_Event_Item_and_Place_Place_and_Event
|
lduf
left a comment
There was a problem hiding this comment.
This should work, but I would prefer to use something more dynamic. There are many code similarities / repetition and adding a new type of relation won't be easy.
I explained what I was thinking to do to chatGPT and ask it to explain it in a more comprehensive way.
Here is what it said :
Explanation and Detailed Proposal
Objective:
The goal is to create a flexible and scalable system to manage relations between different models (e.g., Item, Place, Event) in a way that avoids code duplication and adheres to clean code principles.
Current Issues:
The current approach in the PR involves a lot of repetitive code to establish relationships between models. This can be improved using a more abstract and generalized approach.
Proposal:
-
Abstract Class/Interface:
- Create an abstract class or interface that defines the common behavior for all models that can have relations. This class will be called
Relationable.
- Create an abstract class or interface that defines the common behavior for all models that can have relations. This class will be called
-
Inheritance:
- Each model that needs to have relations (e.g., Item, Place, Event) will inherit from the
Relationableclass.
- Each model that needs to have relations (e.g., Item, Place, Event) will inherit from the
-
Allowed Relations:
- Define a list of allowed relations in the parent class. This list will specify which models can be related to each other.
-
Dynamic Relation Methods:
- Use dynamic methods to handle the creation and management of these relations, reducing the need for repetitive code.
Example Implementation:
1. Creating the Relationable Abstract Class:
abstract class Relationable extends Model
{
protected static $allowedRelations = [];
public function addRelation($relationType, $relatedModel)
{
if (!in_array(get_class($relatedModel), static::$allowedRelations)) {
throw new Exception("Relation not allowed");
}
// Logic to add the relation
// This is a simplified example, and you would expand on it as needed for your project.
return Link::create([
'from_id' => $this->id,
'from_type' => get_class($this),
'to_id' => $relatedModel->id,
'to_type' => get_class($relatedModel),
'relation_type' => $relationType,
]);
}
public function getRelations($relationType)
{
// Logic to get the relations
}
}2. Extending Models from Relationable:
class Item extends Relationable
{
protected static $allowedRelations = [Place::class, Event::class, Item::class];
}
class Place extends Relationable
{
protected static $allowedRelations = [Event::class];
}
class Event extends Relationable
{
protected static $allowedRelations = [Event::class];
}3. Using the New Structure:
$item = Item::find(1);
$place = Place::find(2);
$event = Event::find(3);
$item->addRelation('location', $place); // Allowed
$item->addRelation('participation', $event); // Allowed
$place->addRelation('host', $event); // Allowed
$event->addRelation('related', $event); // Allowed
$place->addRelation('residence', $item); // Throws exception (not allowed)Detailed Example:
-
Defining a Relation:
- In the
Itemmodel, we can define that it can have relations with otherItems,Places, andEvents. - In the
Placemodel, we define that it can have relations withEvents only. - In the
Eventmodel, we define that it can have relations with otherEvents.
- In the
-
Handling Relations:
- The
addRelationmethod in theRelationableclass checks if the relation is allowed before creating it. - This ensures that you cannot create invalid relations, maintaining the integrity of your data.
- The
Benefits:
- Reduced Code Duplication: By centralizing the relation logic in the
Relationableclass, you avoid repetitive code across different models. - Flexibility: You can easily add or remove allowed relations by modifying the
$allowedRelationsarray in each model. - Scalability: This approach is scalable and can easily accommodate new models and relations in the future.
This structure ensures a clean, maintainable, and scalable way to manage relations between different models in your project.
PS : you might need to refactor many models and migration.
I think you should add from_type and to_type columns to support polymorphic relationships to links table. This allows any model to be related to any other model.
| return $this->hasOne(ApiLog::class, 'id', 'apiLog_id'); | ||
| } | ||
|
|
||
| public static function getAllPlacesNames() { |
There was a problem hiding this comment.
Use pluck instead :
public static function getAllPlacesNames() {
return self::pluck('name', 'id');
}There was a problem hiding this comment.
Don't re specify 'edit' and all that stuff, use the one from src/resources/lang/en/common.php
There was a problem hiding this comment.
Don't re specify 'edit' and all that stuff, use the one from src/resources/lang/en/common.php
There was a problem hiding this comment.
Don't re specify 'edit' and all that stuff, use the one from src/resources/lang/en/common.php
There was a problem hiding this comment.
Don't re specify 'edit' and all that stuff, use the one from src/resources/lang/en/common.php
There was a problem hiding this comment.
Don't re specify 'edit' and all that stuff, use the one from src/resources/lang/en/common.php
There was a problem hiding this comment.
Don't re specify 'edit' and all that stuff, use the one from src/resources/lang/en/common.php
lduf
left a comment
There was a problem hiding this comment.
Add tests to make sure everything is working 😉



Original issue description
Description of the desired solution
• Instead of manually adding which event a person was in, a relation must be created between the person and the event. Avoids having an item in multiple events.
• An item can have a localization, so a relation between place and item is necessary
• A event can have a localization, so a relation between place and event is necessary
closes #496
closes #498