Con Eloquent puedes construir un sistema de calificaciones flexible y escalable sin duplicar lógica. Aquí verás cómo las relaciones polimórficas permiten que una sola tabla pivot conecte múltiples modelos, cómo estructurar la migración, el modelo Rating y dos traits reutilizables: CanRate y CanBeRated. El resultado: un único flujo para puntuar productos, páginas o categorías con pruebas que pasan.
¿Qué resuelven las relaciones polimórficas en Eloquent?
Las relaciones polimórficas permiten que un modelo pertenezca a más de un tipo de modelo. Con un ejemplo de rating, un usuario o invitado puede puntuar un producto, una página o una categoría con una sola relación. Así evitas múltiples tablas intermedias y repeticiones.
¿Cómo funciona el concepto de morph en Eloquent?
Un par de columnas define la relación: <nombre>_id y <nombre>_type.
Con morphs('ratable') y morphs('qualifier') identificas quién es calificado y quién califica.
Se usa una única tabla pivot para todos los tipos relacionados.
¿Qué roles intervienen en el rating?
Ratable: la entidad que recibe la calificación, por ejemplo, un producto.
Qualifier: la entidad que califica, por ejemplo, un usuario.
Score: el valor de la calificación almacenado en la tabla pivot.
¿Cómo se implementa el sistema de rating con morphs?
Primero se crea la migración para la tabla intermedia y luego el modelo Rating que extiende Pivot. Esto habilita timestamps, score y los tipos polimórficos.
¿Cómo crear la migración de ratings con morphs?
Ejecuta el comando: php artisan make:migration para crear la tabla.
Define id, timestamps, score y los morphs para las dos entidades.
php artisan make:model Rating: genera el modelo para la tabla intermedia.
¿Cómo usar traits para calificar y ser calificado?
Para mantener el diseño flexible, se usan traits: uno para quienes califican (CanRate) y otro para quienes son calificados (CanBeRated). Allí se centraliza la relación morphToMany, alias, timestamps, columnas pivot y filtros por tipo.
¿Cómo implementar el trait CanRate con morphToMany?
La relación ratings($model = null) arma dinámicamente la clase objetivo con get_class o getMorphClass.
Usa morphToMany con: clase relacionada, nombre de la relación, tabla ratings, qualifier_id y ratable_id.
Define alias con as('rating'), agrega withTimestamps() y columnas pivot: score y ratable_type.
Filtra por ratable_type y qualifier_type para asegurar consistencia.
Expone métodos rate($model, $score) y hasRated($model) para operar y validar no calificar dos veces.