referencedColumnName: Name of the primary key identifier that is used for joining of this relation.
/**
* @OneToOne(targetEntity="\Core\Entities\Delivery\BoxberryTtn", mappedBy="ttn_boxberry", cascade={"persist", "remove"})
* @JoinColumn(name="order_code", referencedColumnName="id")
*/
protected $boxberry_ttn;
/**
* @Entity
* @Table(name="`ttn_boxberry`")
*/
class BoxberryTtn
{
/**
* @Id
* @Column(type="string")
* @GeneratedValue(strategy="NONE")
*/
protected $id;
public function __construct(string $id)
{
$this->id = $tid;
}
}
order_code
/**
* @Entity
* @Table(name="`order`")
*/
class Order
{
/**
* @Id
* @Column(type="integer")
*/
protected $order_code;
/**
* @OneToOne(targetEntity="\Core\Entities\Delivery\BoxberryTtn", mappedBy="ttn_boxberry", cascade={"persist", "remove"})
* @JoinColumn(name="order_code", referencedColumnName="order_code")
*/
protected $boxberry_ttn;
}
/**
* @Entity
* @Table(name="`order`")
*/
class Order
{
/**
* @Id
* @Column(type="integer")
*/
protected $order_id;
/**
* @Id
* @Column(type="integer")
*/
protected $order_code;
/**
* @Column(type="integer")
*/
protected $warehouse_id;
/**
* @OneToOne(targetEntity="\Core\Entities\Delivery\BoxberryTtn", cascade={"persist", "remove"})
* @JoinColumn(referencedColumnName="order_code")
*/
protected $boxberry_ttn;
public function __construct(int $order_id, string $order_code)
{
$this->order_id = $order_id;
$this->order_code = $order_code;
}
}
/**
* @Entity
* @Table(name="`ttn_boxberry`")
*/
class BoxberryTtn
{
/**
* @Id
* @Column(type="string")
* @GeneratedValue(strategy="NONE")
*/
protected $order_code;
/**
* @Column(type="string")
*/
protected $ttn_num;
/**
* @Column(type="float", scale=2)
*/
protected $delivery_cost;
public function __construct(Order $order)
{
$this->order_code = $order->getOrderCode();
}
}
public function __toString()
{
return $this->name;
}
\Symfony\Component\Form\Extension\Core\Type\ColorType
в котором, судя по всему, ваша сущность кастится в строку.\App\Form\ColorType
метод getBlockPrefix
и все заработает:public function getBlockPrefix()
{
return 'app_color';
}
new User()
вместо вашего кодаpublic function getUser($credentials, UserProviderInterface $userProvider)
{
return new User();
}
stateless: true
ContextListener manages the SecurityContext persistence through a session.
!$this->isGranted('IS_AUTHENTICATED_REMEMBERED');
$reflectionExtractor = new ReflectionExtractor();
$phpDocExtractor = new PhpDocExtractor();
$propertyTypeExtractor = new PropertyInfoExtractor([$reflectionExtractor], [$phpDocExtractor, $reflectionExtractor], [$phpDocExtractor], [$reflectionExtractor], [$reflectionExtractor]);
$normalizer = new ObjectNormalizer(null, null, null, $propertyTypeExtractor);
$arrayNormalizer = new ArrayDenormalizer();
$serializer = new Serializer([$arrayNormalizer, $normalizer]);
return $serializer->denormalize($array, ContragentDto::class);
firewalls:
main:
guard:
authenticators:
- App\Security\TokenAuthenticator
entry_point
- используется для начала процесса аутентификации. В вашем случае он не нужен, т.к. у вас api # config/services.yaml
services:
DependencyInterface: '@RealDependency'
# config/services_test.yaml
services:
DependencyInterface: '@FakeDependency'
// \App\Kernel
protected function initializeContainer()
{
if ($_ENV['APP_ENV'] === 'dev') {
$container = $this->buildContainer();
$container->setParameter('container.build_id', 'id');
$container->setParameter('container.build_hash', 'hash');
$container->set('kernel', $this);
$container->compile(true);
$this->container = $container;
} else {
parent::initializeContainer();
}
}
smart-core/accelerator-cache-bundle
, возможно другие бандлы тоже несовместимы с таким режимом.{{ render(controller(
AppBundle:Article:recentArticles',
{ 'max': 3 }
)) }}
{{ articles(3) }}
{{ app_version }}
app
, к примеру, тот же инстанс залогиненого пользователя{{ app.user.username }}
$form = $this->container->get('form.factory')
->createNamed(
'account_'. $account->getId(),
AccountType::class,
$account
)
;
public function indexAction(Request $request)
{
$accounts = $this
->getDoctrine()
->getRepository('AppBundle:Account')
->findActive();
$forms = [];
foreach ($accounts as $key => $account){
$form = $this->container->get('form.factory')->createNamed('account_'. $account->getId(), AccountType::class, $account);
// Не надо добавлять кнопки сабмита, их рекомендуется добавлять непосредственно в шаблоне обычным html
// $form->add('submit', SubmitType::class);
$form->handleRequest($request);
// Не надо инжектить форму в сущность, легче просто передать формы в шаблон
// $account->setForm($form);
// $account->setFormView($formView);
if($form->isSubmitted() && $form->isValid()){
// Объекты передаются по ссылке, нет смысла в получение $account повторно
// $data = $form->getData();
$this->addFlash('success', 'Saved');
$em = $this->getDoctrine()->getManager();
// Это актуально только для создания сущности, при редактировании - это не нужно
// $em->persist($data);
$em->flush();
return $this->redirectToRoute('account_list');
} else {
$forms[$account->getId()] = $form->createView();
}
}
return [
'forms' => $forms,
'accounts' => $accounts,
];
}
{# {{ form_row(account.formView) }} #}
{{ form_start(forms[account.id]) }}
{{ form_widget(forms[account.id]) }}
<button>Submit</button>
{{ form_end(forms[account.id]) }}
class TaskController
{
/**
* @var ProducerInterface
*/
private $producer;
public function __construct(ProducerInterface $producer)
{
$this->producer = $producer;
}
public function indexAction($name)
{
$this->producer->publish('test');
return new Response();
}
}
# services.yaml
services:
App\Controller\TaskController:
arguments:
- '@old_sound_rabbit_mq.task_producer'
# services.yaml
services:
OldSound\RabbitMqBundle\RabbitMq\ProducerInterface: '@old_sound_rabbit_mq.task_producer'
$query = $em->createQuery(
'SELECT NEW ArticleDTO(ar.title, ar.imagePath, ar.publishedAt, CONCAT(au.firstName, ' ', au.lastName))
FROM Article ar JOIN ar.author au');
$articles = $query->getResult(); // array of ArticleDTO
AnnotationClassLoader
, задачей которого преобразовывать аннотации в роуты. Абстрактный класс есть в компоненте, вам надо только определить метод configureRoute
. За основу можно взять код из фреймворкаnamespace App\Router;
use Symfony\Component\Routing\Loader\AnnotationClassLoader as BaseLoader;
use Symfony\Component\Routing\Route;
class AnnotationClassLoader extends BaseLoader
{
protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot)
{
if ('__invoke' === $method->getName()) {
$route->setDefault('_controller', $class->getName());
} else {
$route->setDefault('_controller', $class->getName().'::'.$method->getName());
}
}
}
use App\Router\AnnotationClassLoader;
use Doctrine\Common\Annotations\AnnotationReader;
use Doctrine\Common\Annotations\AnnotationRegistry;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader;
use Symfony\Component\Routing\Loader\AnnotationFileLoader;
use Symfony\Component\Routing\Router;
$autoloader = require_once __DIR__ . '/../vendor/autoload.php';
AnnotationRegistry::registerLoader(array($autoloader, 'loadClass'));
$reader = new AnnotationReader();
$annotationClassLoader = new AnnotationClassLoader($reader);
$fileLocator = new FileLocator([__DIR__]);
$loaderResolver = new LoaderResolver([
new AnnotationFileLoader($fileLocator, $annotationClassLoader),
new AnnotationDirectoryLoader($fileLocator, $annotationClassLoader),
]);
$loader = new DelegatingLoader($loaderResolver);
$router = new Router($loader, __DIR__ . '/../src/Controller');
dump($router->getRouteCollection());
$params = $request->request->all();
$files = $request->files->all();
$data = array_replace_recursive($params, $files);
$form->submit($data);
submit
как показано выше$rules = new Assert\Collection([
"items" => new Assert\Required([
new Assert\NotBlank(),
new Assert\Callback(function ($value, ExecutionContextInterface $context) {
$validator = $context->getValidator();
$violations = $validator->validate($value, new Assert\Type('array'));
if ($violations->count() > 0) {
/** @var ConstraintViolationInterface $violation */
foreach ($violations as $violation) {
$context
->buildViolation($violation->getMessage(), $violation->getParameters())
->atPath('items')
->addViolation()
;
}
return;
}
$violations = $validator->validate($value, new Assert\All([
new Assert\Type('array'),
new Assert\Collection([
"id" => new Assert\NotBlank(),
"quantity" => new Assert\NotBlank(),
])
]));
/** @var ConstraintViolationInterface $violation */
foreach ($violations as $violation) {
$context
->buildViolation($violation->getMessage(), $violation->getParameters())
->atPath('items'. $violation->getPropertyPath())
->addViolation()
;
}
}),
]),
]);
$validator = Validation::createValidator();
$data = [
'items' => [
[
'id' => 'id',
'quantity' => 'quantity',
],
],
];
dump($validator->validate($data, $rules)); // Ok
$data = [
'items' => 1,
];
dump($validator->validate($data, $rules)); // Ko
$data = [
'items' => [
[
'id' => 'id',
'quantity' => 'quantity',
],
[
'id2' => 'id',
'quantity2' => 'quantity',
]
],
];
dump($validator->validate($data, $rules)); // Ko
ObjectNormalizer
имеет несколько больше зависимостей для полноценной его работыpublic function submitAction(SerializerInterface $serializer, Request $request)
{
if ($request->isXmlHttpRequest()) {
$data = $request->getContent();
$result = $serializer->deserialize($data, SiteCreateDto::class, 'json');
var_dump($result); exit;
}
}
ObjectNormalizer
не помог, то надо будет написать свой: https://symfony.com/doc/current/serializer/custom_...