Calificación de Libros con Validación en PHP y Yii Framework

Clase 31 de 35Curso de Desarrollo Web con PHP y Yii2

Contenido del curso

Modelos, vistas y controladores

Enlaces, navegación y tablas intermedias

Resumen

Construir un sistema de calificación de libros desde cero implica conectar varias piezas: una tabla nueva, un modelo con validaciones, un controlador con acciones separadas y una vista con formularios activos. Todo esto se resuelve en pocos pasos gracias a la estructura que ofrece el framework Yii2, donde cada capa tiene responsabilidades claras y el flujo de datos sigue un patrón predecible.

¿Cómo crear el modelo BookScore con validaciones?

El punto de partida es la tabla book_scores, que almacena tres datos esenciales: el user ID, el book ID y una calificación del uno al cinco [0:06]. La tabla incluye campos created_at y modified_at, además de una restricción de unicidad que impide que un mismo usuario califique dos veces el mismo libro.

El modelo BookScore se crea tomando como base otro modelo existente, en este caso Author, y se adapta con el nombre de tabla y la llave primaria correspondiente [0:42]. Lo más relevante es la función rules(), que define las reglas de validación:

  • El campo score se marca como required para que no llegue vacío.
  • Se valida como integer para asegurar que sea un número entero.
  • El bookId se configura como safe para que el modelo no lo filtre al recibir datos del formulario [7:30].

php public function rules() { return [ ['score', 'required'], ['score', 'integer'], ['bookId', 'safe'], ]; }

Sin estas reglas, el método save() falla silenciosamente. Este es un error común: cuando no hay validaciones definidas, el modelo no sabe qué atributos aceptar del usuario y simplemente no guarda nada [6:21].

¿Cómo separar la lógica entre acciones del controlador?

Una decisión de diseño importante es que la acción que muestra el formulario no es la misma que lo procesa. En actionDetail se crea un objeto BookScore vacío, un placeholder, y se le asigna el bookId del libro actual antes de enviarlo a la vista [1:06]. Este sobre vacío viaja a la vista para que el formulario tenga un modelo al cual bindear sus campos.

La acción actionScore recibe los datos por POST, crea un nuevo BookScore, lo carga con load(), valida y guarda [3:22]. Si todo sale bien, redirige al detalle del libro con un flash message de éxito.

php public function actionScore() { $bs = new BookScore(); $bs->userId = Yii::$app->user->identity->id; if ($bs->load(Yii::$app->request->post()) && $bs->validate()) { $bs->save(); Yii::$app->session->setFlash('success', 'Gracias por tu calificación'); return $this->redirect(['book/detail', 'id' => $bs->bookId]); } }

Un detalle clave es que el user ID se asigna desde el servidor con Yii::$app->user->identity->id, no desde el formulario [8:15]. Esto se hace antes de validar por si alguna regla dependiera de ese valor.

¿Cómo apuntar el formulario a una acción diferente?

El ActiveForm en la vista necesita saber a dónde enviar los datos. Esto se configura con el parámetro action, que recibe un arreglo con la ruta del controlador [7:10]:

php $form = ActiveForm::begin([ 'id' => 'new-score', 'action' => ['book/score'], ]);

¿Cómo construir el formulario con dropdown y campos ocultos?

En la vista se utiliza un dropdown list para que el usuario seleccione su calificación de una a cinco estrellas [2:42]. La estructura del dropdown usa llaves numéricas como valores que se almacenan en la base de datos y las estrellas como labels visibles.

php echo $form->field($bookScore, 'score')->dropdownList([ 1 => '⭐', 2 => '⭐⭐', 3 => '⭐⭐⭐', 4 => '⭐⭐⭐⭐', 5 => '⭐⭐⭐⭐⭐' ]);

El bookId se envía como un hidden input para que no sea visible al usuario, y su label se oculta con ->label(false) [5:20]. Un detalle importante en las vistas de Yii2: algunos precompiladores como Twig son más estrictos y no permiten la coma final en el último elemento de un arreglo, algo que PHP sí acepta [3:52].

¿Qué tareas complementan este ejercicio?

Dos retos quedan planteados para reforzar lo aprendido:

  • Reemplazar el dropdown list por una serie de radio buttons, algo que Yii2 facilita enormemente.
  • Usar el evento onChange de HTML para hacer el submit automático del formulario al seleccionar una opción [5:46].
  • Agregar una validación que restrinja el score estrictamente entre uno y cinco.

Con la calificación guardada correctamente en la base de datos, se confirma que el flujo completo funciona: formulario, envío por POST a otra acción, validación del modelo, asignación del usuario desde el servidor y redirección con mensaje de éxito. ¿Has implementado sistemas de calificación similares? Comparte tu experiencia y las variantes que hayas probado.