PHALCON: Как получить / подтвердить связанные объекты перед сохранением?
-
21-12-2019 - |
Вопрос
У меня есть модель аудио и модель аудиокатегории.
Когда я сохраню аудиообъект, я хочу подтвердить, что к нему прилагается не менее 1 аудиокатегории.
Я создал пользовательский валидатор для этого.
Я пытался использовать Audio-> GetRelated () в Validator, но он продолжает пытаться получить в базе данных для информации. Поскольку валидация происходит перед сохранением (что является здорово), то я получаю пустой список, при этом мой валидатор всегда возвращает false.
Когда я печатаю аудиообъект без сохранения, я вижу мою аудиокатегорию в поле _RELELICED AUDIO Object (print_r ($ audio);):
[_Related: Protected]=> Array
(
[Audiocategory]=> Array
(
[0]=> GRQ \ AUDIO \ AUDIOCATEGORY ELACTOR ([...])
[1]=> grq \ audio \ audiocateory объект ([...])
)
)
Если я попытаюсь печатать $ audio-> audiocategory напрямую, я получаю уведомление:
Доступ к неопределенной недвижимости GRQ \ AUDIO \ AUDIO :: Audiocategory
И ничего не возвращается.
Если я звоню $ audio-> getrelated (), я получаю объект типа phalcon \ mvc \ model \ thasseet \ Simple с пустым _result. (Который является логикой, так как он пошел и искал в базе данных ...)
Следовательно, мой вопрос:
Как я могу получить и подтвердить соответствующие поля, прежде чем их сохранить?
Вот мой (сокращенный) тест контроллера:
$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();
.
Вот (сокращенная) модель аудио:
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;
}
}
.
Вот (сокращенная) модель аудио категории:
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'
));
}
}
.
Вот мой пользовательский валидатор (который не работает и всегда возвращает false):
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;
}
}
. Решение
Итак, я нашел способ достижения этого.Не уверен, что это лучший способ, но это работает:
Поскольку значения защищены, мне пришлось разоблачить их от моего объекта.
Итак, я создал базовую модель, из которой можно простираться:
Базовая модель:
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;
}
}
.
Тогда я изменил свой аудио класс для продления с моей базы модели:
Audio Model (упрощенная):
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;
}
}
.
Моя модель аудиокатегории (упрощенная) осталась почти такой же:
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'
));
}
}
.
и мой валидатор теперь использует метод getinternAlrelated для проверки:
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;
}
}
.