Pregunta

Tengo un modelo de audio y una audiocategoría modelo.
Cuando guarde el objeto de audio, quiero validar que hay al menos 1 audiocategoría adjunta a ella.

He creado un validador personalizado para eso.
Intenté usar los $ Audio-> GetTrelated () en el validador, pero sigue intentando recuperarse en la base de datos para la información. Dado que la validación ocurre antes de guardar (lo que es genial), entonces recibo una lista vacía, por lo que mi validador siempre devuelve False.

Cuando imprimo el objeto de audio sin guardar, puedo ver mi audiocategoría en el campo _Relado del objeto de audio (print_r ($ audio);) [_Relado: protegido]=> Array
( [Audiocategory]=> Array
(
[0]=> GRQ \ Audio \ Audiocategory Objeto ([...])
[1]=> GRQ \ Audio \ Audiocategory Objeto ([...])
)
)

Si intento imprimir $ Audio-> Audiocategory directamente, recibo un aviso:
Acceso a la propiedad indefinida GRQ \ Audio \ Audio :: AudiCategory
y nada es devuelto.

Si llamo $ AUDIO-> getTrelated (), obtengo un objeto de tipo Phalcon \ MVC \ Model \ ResustSet \ Simple con un vacío _Result. (Que es lógica, ya que fue y buscó en la base de datos ...)


Por lo tanto, mi pregunta es:

¿Cómo puedo obtener y validar los campos relacionados antes de guardarlos?


Aquí está mi prueba de controlador (acortado):

    $audioCategory = new AudioCategory();
    $audioCategory->categoryId = 1;
    $arAudioCategory[0] = $audioCategory; 

    $audioCategory = new AudioCategory();
    $audioCategory->categoryId = 2;
    $arAudioCategory[1] = $audioCategory;

    $audio = new Audio();
    [...other fields initialization...]
    $audio->audiocategory = $arAudioCategory;
    $audio->save();

Aquí está el modelo de audio (acortado):

namespace GRQ\Audio;
use GRQ\Validator\PresenceOfRelationValidator;
class Audio extends \Phalcon\Mvc\Model {
/**
 * @Primary
 * @Identity
 * @Column(type="integer", nullable=false)
 */
public $id = 0; 
/**
 * @Column(type="integer", nullable=false)
 */
public $createdAt = 0;

[...other fields all reflecting the database...]

public function initialize() {
    $this->setSource ( "audio" );

    // table relationships
    $this->hasMany ( "id", "GRQ\Audio\AudioCategory", "audioId", array(
            'alias' => 'audiocategory'
    ) );
}

public function validation() {      
    [...other validations...]

    $this->validate ( new PresenceOfRelationValidator ( array (
            "field" => "audiocategory" 
    ) ) );

    return $this->validationHasFailed () != true;
}
}

Aquí está el modelo (acortado) de la categoría de audio:

namespace GRQ\Audio;    
class AudioCategory extends \Phalcon\Mvc\Model {
/**
 * @Primary
 * @Identity
 * @Column(type="integer", nullable=false)
 */
public $id = 0; 
/**
 * @Column(type="integer", nullable=false)
 */
public $audioId = 0;    
/**
 * @Column(type="integer", nullable=false)
 */
public $categoryId = 0;

public function initialize(){
    $this->setSource("audiocategory");
    //table relationships
    $this->belongsTo("audioId", "GRQ\Audio\Audio", "id", array(
            'alias' => 'audio'
    ));
}
}

Aquí está mi validador personalizado (que no funciona y siempre devuelve FALSO):

namespace GRQ\Validator;

use Phalcon\Mvc\Model\Validator;
use Phalcon\Mvc\Model\ValidatorInterface;

class PresenceOfRelationValidator extends Validator implements ValidatorInterface {
public function validate($model){
    $field = $this->getOption('field');
    $message = $this->getOption('message');
    if (!$message) {
        $message = 'The required relation '.$field.' was not found';
    }

    $value = $model->getRelated($field);

    if (count($value) == 0) {
        $this->appendMessage(
                $message,
                $field,
                "PresenceOfRelation"
        );
        return false;
    }
    return true;
}
}

¿Fue útil?

Solución

Entonces, encontré una forma de lograr esto.No estoy seguro de que sea la mejor manera, pero funciona:

Dado que los valores están protegidos, tuve que exponerlos de mi objeto.
Así que creé un modelo base desde el cual se extiende a mí mismo:

Modelo base:

namespace GRQ;
class BaseModel extends \Phalcon\Mvc\Model {

/**
 * This function should be used to get the data in the _related field directly.
 * It is very useful if you need to validate the presence of a relation BEFORE saving in the database.
 * To initialize the field with the database content, use $this->getRelated().
 */
public function getInternalRelated(){
    return $this->_related;
}   
}

Luego cambié mi clase de audio para extender desde mi modelo base:

Modelo de audio (simplificado):

namespace GRQ\Audio;

use Phalcon\Mvc\Model\Validator\Numericality;
use GRQ\Validator\MinValueValidator;
use GRQ\Validator\PresenceOfRelationValidator;

class Audio extends \GRQ\BaseModel {
/**
 * @Primary
 * @Identity
 * @Column(type="integer", nullable=false)
 */
public $id = 0;

/**
 * @Column(type="string", length=255, nullable=false)
 */
public $title = '';

public function initialize() {
    $this->setSource ( "audio" );

    // table relationships
    $this->hasMany ( "id", "GRQ\Audio\AudioCategory", "audioId", array(
            'alias' => 'audiocategory'
    ) );
}

public function validation() {              
    $this->validate ( new PresenceOfRelationValidator ( array (
            "field" => "audiocategory" 
    ) ) );

    return $this->validationHasFailed () != true;
}
}

Mi modelo de audiocategoría (simplificado) se mantuvo casi igual:

namespace GRQ\Audio;

use Phalcon\Mvc\Model\Message;

class AudioCategory extends \GRQ\BaseModel {
/**
 * @Primary
 * @Identity
 * @Column(type="integer", nullable=false)
 */
public $id = 0;

/**
 * @Column(type="integer", nullable=false)
 */
public $audioId = 0;

/**
 * @Column(type="integer", nullable=false)
 */
public $categoryId = 0;

public function initialize()
{
    $this->setSource("audiocategory");
    //table relationships
    $this->belongsTo("audioId", "GRQ\Audio\Audio", "id", array(
            'alias' => 'audio'
    ));
}
}

y mi validador ahora usa el método GetInternalRelado para validar:

namespace GRQ\Validator;

use Phalcon\Mvc\Model\Validator;
use Phalcon\Mvc\Model\ValidatorInterface;

class PresenceOfRelationValidator extends Validator implements ValidatorInterface {
public function validate($model){
    $field = $this->getOption('field');
    $message = $this->getOption('message');
    if (!$message) {
        $message = 'The required relation '.$field.' was not found';
    }

    $value = $model->getInternalRelated();

    if (count($value[$field]) == 0) {
        $this->appendMessage(
                $message,
                $field,
                "PresenceOfRelation"
        );
        return false;
    }
    return true;
}
}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top