I wrote a class called Categorizable
that allows for a polymorphic many to many relationship between a class that extends it and the class Category
. It works great but I noticed that if I call a method to add a Category to a categorizable object it adds the entry on the join table but my actual object isn't updated. If I try to call categories
on my object, it's not updated with what's on the database. I would like to keep my objects up to date so i don't have to query the database for it each time I add a category.
Categorizable.php
class Categorizable extends Model{
public function categories(){
return $this->morphToMany(Category::class, 'categorizable');
}
public function addCategory(\App\Category $category){
if ( $this->isValidCategory($category) ){
if ( $this->hasCategory($category) ){
return false;
}
else{
$this->categories()->save($category);
return true;
}
}
else{
return false;
}
}
public function removeCategory(\App\Category $category){
if ( $this->isValidCategory($category) ) {
if ($this->hasCategory($category)) {
$this->categories()->detach($category);
return true;
}
else {
return false;
}
}
else{
return false;
}
}
public function hasCategory(\App\Category $category){
return $this->categories->contains($category);
}
public function isValidCategory(\App\Category $category){
if ( $category->category_type === get_class( $this ) ){
return true;
}
else{
return false;
}
}
If this is not possible with Laravel 5.2 or considered bad practice, please say so. If you have any recommendations on how I could improve this, that is also welcome. Thanks.
Consider handling this in a controller as explained in https://laravel.com/docs/5.4/eloquent-relationships#updating-many-to-many-relationships
It will simplify what you want to achieve. Let's assume the categories are related to an article and the controller is ArticleController. $article is the model object and the isValidCategory() check is done. Add a category or remove one becomes:
$article->categories()->attach($category->id);
$article->categories()->detach($category->id);
Resetting all relationships of that article:
$article->categories()->detach();
$article->categories()->attach($categories); //flat array
Or do this in one line:
$article->categories()->sync($categories);
Remember, you can either use one id or an array of id's like [1, 2, 3]
Note: $category->id
is an assumption, if $category is the id, then obviously, use $category