Просто интересно, можно ли использовать только некоторые части обработки формы symfony. Например, при создании CRUD-действий через generate:doctrine:crud
я получаю что-то в своем контроллере (для обработки созданных запросов пользователей POST), который выглядит так:
$entity = new User(); $form = $this->createForm(new UserType(), $entity, array( 'action' => $this->generateUrl('user_create'), 'method' => 'POST', )); $form->handleRequest($request); //Here I have a filled Entity
Но я хочу, чтобы это было в более многоразовом решении. В настоящее время у меня есть моя бизнес-логика в сервисе UserModel
. Здесь я также хочу, чтобы метод create создавал, проверял и сохранял новый объект. Жесткий UserModel
также должен быть вызван из некоторых сценариев команд через консоль, поэтому у меня, вероятно, не всегда будет Request
или Form
.
Итак, теперь из приведенного выше кода я знаю, что Symfony уже каким-то образом UserType
данные в Entity в соответствии с определением UserType
, но как я могу сделать это вручную, не имея Form
или Request
а вместо этого просто некоторый массив данных?
Так что мне не нужно заботиться о настройке свойств самостоятельно.
Изменить: проверка не является проблемой для заполнения объекта, я использую validator
позже для заполненного объекта, прежде чем продолжать данные.
И также важным для меня было бы то, что переданные related entity ids
будут обрабатываться / загружаться автоматически.
вы все равно можете использовать компонент формы, но вместо использования handleRequest
вы должны использовать непосредственно submit
.
Если вам интересно, вы должны найти код в github для handleRequest
и того, что он на самом деле делает ; вы увидите, что он просто выполняет некоторую проверку, берет данные из Request
и затем использует метод submit
формы.
Таким образом, вы можете использовать только метод submit
с данными, которые вы хотите использовать. Он даже проверяет вашу сущность. 🙂
ОБНОВИТЬ
И для того, чтобы создавать / обновлять связанные объекты, если ваше отношение имеет каскад persist / update, оно должно выходить из себя, если вы не делаете ничего, кроме persist + flush на вашей основной сущности.
Если вы не беспокоитесь о том, как обращаться с валидацией, как с вещами, вы можете сделать что-то вроде того, что я сделал.
Вы можете определить признак или включить функцию fromArray в классы сущностей.
trait EntityHydrationMethod { public function fromArray($data = array()) { foreach ($data as $property => $value) { $method = "set{$property}"; $this->$method($value); } } }
Если вы определили черту, вы можете использовать ее в своих объектах, таких как:
class User{ use EntityHydrationMethod; }
Затем из вашей пользовательской модели вы можете определить свою функцию создания:
public function create($data = array()) { $entity = new User(); $entity->fromArray($data); return $entity; }
По мере обновления вашего вопроса. вы можете достичь этого, определив признак или включите функцию createFromArray в своих классах EntityRepository.
trait RepositoryCreateMethod { public function createFromArray($data) { $class = $this->getClassName(); $object = new $class(); $meta = $this->getClassMetadata(); foreach ($data as $property => $value) { $v = $value; if(!empty($value) && $meta->hasAssociation($property)) { $map = $meta->getAssociationMapping($property); $v = $this->_em->getRepository($map['targetEntity'])->find($value); if(empty($v)){ throw new \Exception('Associate data not found'); } } $method = "set{$property}"; $object->$method($v); } return $object; } }
Если вы определили черту, вы можете использовать ее в своем репозитории, например:
class UserRepository{ use RepositoryCreateMethod; }
Затем вы можете использовать это как вызов от контроллера:
$user = $this->getDoctrine() ->getRepository('YourBundle:User') ->createFromArray($data);