Phalcon: come ottenere / convalidare / convalidare gli oggetti correlati prima di salvare?

StackOverflow https://stackoverflow.com//questions/23021023

  •  21-12-2019
  •  | 
  •  

Domanda

Ho un modello Audio e un modello Audiocategoria.
Quando salvo l'oggetto audio, voglio convalidare che ci sia almeno 1 audiocategoria allegata ad esso.

Ho creato un validatore personalizzato per quello.
Ho provato a utilizzare $ Audio-> Getralato () nel validatore, ma continua a cercare di recuperare nel database per le informazioni. Poiché la convalida si verifica prima del salvataggio (che è grande), quindi ricevo un elenco vuoto, quindi il mio validatore restituisce sempre falso.

Quando stampa l'oggetto audio senza salvare, posso vedere la mia audiocategoria nel campo _related dell'oggetto audio (stampa_R ($ Audio);):
[_RELATO: Protetto]=> Array
( [Audiocategoria]=> array
(
. [0]=> GRQ \ Audio \ Audiocategy Object ([...])
[1]=> GRL \ Audio \ Audiocategy Object ([...])
)
. )

Se provo a stampare $ audio-> Audiocategoria direttamente, ottengo un avviso:
Accesso a proprietà indefinita GRL \ Audio \ Audio :: Audiocategoria
e nulla viene restituito.

Se chiamo $ Audio-> Getrelated (), ottengo un oggetto di tipo Phalcon \ MVC \ Model \ Resultset \ Semplice con un vuoto _result. (Che è la logica, dal momento che è andato e cercato nel database ...)


.

Pertanto, la mia domanda è:
Come posso ottenere e convalidare i campi correlati prima di salvarli?


.

Ecco il mio test del controller (abbreviato):

    $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();
.

Ecco il modello audio (abbreviato):

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;
}
}
.

Ecco la categoria audio (abbreviata) Modello:

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'
    ));
}
}
.

Ecco il mio validatore personalizzato (che non funziona e restituisce sempre 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;
}
}
.

È stato utile?

Soluzione

Allora, ho trovato un modo per raggiungerlo.Non sono sicuro che sia il modo migliore, ma funziona:
Poiché i valori sono protetti, dovevo esporli dal mio oggetto.
Quindi ho creato un modello base da cui estendere me stesso:

Modello di 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;
}   
}
.

Poi ho cambiato la mia classe audio per estendere dal mio modello di base:

Modello audio (semplificato):

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;
}
}
.

Il mio modello Audiocategy (semplificato) è rimasto subito lo stesso:

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'
    ));
}
}
.

E il mio validatore ora utilizza il metodo GetInternalreatod per convalidare:

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;
}
}
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top