У меня есть объектный вызов Category, другой вызов Product и один посередине под названием CategoryProduct.
@ORM\OneToMany(targetEntity = "CategoryProduct", mappedBy = "Catego", fetch = "EAGER") с инвертированнымBy в классе CategoryProduct (в $ catego).@ORM\OneToOne(targetEntity = "Product", inversedBy = "Category") с инверснымBy в классе Product (в категории $).внутри моего CategoryController у меня есть такая функция:
public function getCategoryAction(Request $request)
{
$category = $this->get('doctrine.orm.entity_manager')
->getRepository('AppBundle:Category')
->findAll();
return new JsonResponse($category);
}
Возвращаемый результат дает коллекцию сущностей Category, но «суб-сущность» Product пуста. Когда я проверяю токен на предмет отладки в Symfony, я проверяю раздел Doctrine, и запрос работает отлично, данные загружаются, а в моем возвращении их просто нет. Я могу получить доступ к данным с помощью $category->getProduct() (он дает мне коллекцию ссылок продукта на категорию, как я хочу), но все же мой подкласс продукта пуст. Кто-нибудь знает почему?
Спасибо за вашу помощь.
... или doctrine:shema:update
Помимо полезного совета Карла по проверке схемы: вы уверены, что для каждого продукта может быть только один CategoryProduct? Зачем тогда вообще использовать «средний класс»? "InversedBy = " Category "" означает, что вам необходимо иметь свойство $ Category в классе вашего продукта. Но на самом деле это не категория, это CategoryProduct.
Я уже пробовал проверить / обновить схему, и там нет никаких проблем. Мне нужен класс в середине для некоторой информации, которую я не могу нигде сохранить, имя свойства не имеет значения, назовите его как хотите. В любом случае спасибо за вашу помощь






Принимая решение с самого начала, ваша текущая проблема - это типичная вещь для Доктрины гидратации.
По умолчанию Doctrine лениво загружает отношения, это означает, что изначально Doctrine предоставляет прокси-коллекцию, которая не содержит в себе никаких элементов, и загружает фактические элементы только тогда, когда к ним каким-либо образом обращаются (например, при использовании геттера, такого как getProduct ()). Вот почему ваша коллекция товаров кажется пустой.
Вы можете легко изменить это, установив для атрибута fetch в вашей ассоциации значение EAGER:
// inside Category class
/**
* @ManyToOne(targetEntity = "Product", fetch = "EAGER")
*/
private $products;
Однако в конечном итоге ваш код не заработает, потому что, когда вы пытаетесь json_encode объект с частными свойствами, в результате вы получите только пустой json. Решение вашей проблемы - использовать собственный способ сериализации вашего объекта. Самое простое (и, вероятно) лучшее решение - использовать компонент Symfony Serializer. НО вы должны знать, что простое использование $serializer->serialize($category, 'json'); вызовет исключение циклической ссылки. Это будет вызвано тем, что (как я предполагаю) вы также имеете в своем классе продукта ссылку на категорию, подобную этой:
// inside Product class
/**
* @OneToMany(targetEntity = "Category")
*/
private $category;
Как вы понимаете, Symfony попытается сериализовать категорию, в которой есть много продуктов, у которых есть категория, у которой есть много продуктов ... это круговая ссылка.
Чтобы обойти эту проблему, вы должны использовать такие группы сериализации:
// inside your controller, supposing you are using autowiring to inject services:
use Symfony\Component\Serializer\SerializerInterface;
public function getTariffsAction(Request $request, SerializerInterface $serializer)
{
$category = $this->get('doctrine.orm.entity_manager')
->getRepository('AppBundle:Category')
->findAll();
$categoryJson = $serializer->serialize($category, 'json', ['groups' => ['tariffs'] ]);
return $this->json($categoryJson);
}
Затем явно настройте атрибуты ваших объектов, вы хотели бы попасть внутрь своих сущностей следующим образом:
// Category.php
use Symfony\Component\Serializer\Annotation\Groups;
...
/**
* @ORM\Id
* @Groups({"tariffs"})
*/
protected $id;
/**
* @ORM\Column(type = "string")
* @Groups({"tariffs"})
*/
protected $name;
/**
* @ORM\ManyToOne(targetEntity = "Product")
* @Groups({"tariffs"})
*/
private $product;
// any other attribute you want to include
И, наконец, в вашем Product.php:
Product.php
/**
* @ORM\Id
* @Groups({"tariffs"})
*/
protected $id;
/**
* @ORM\Column(type = "string")
* @Groups({"tariffs"})
*/
protected $productName;
// do not include the reference to the category to avoid circular reference
/**
* @OneToMany(targetEntity = "Category")
*/
private $category;
Вы можете найти больше о компоненте сериализатора и группах сериализации в документация.
Извините за задержку, я пробовал метод, который вы мне дали, но ответ Json пуст, нет никакого свойства. Циркуляр кажется хорошей идеей, но один из моих коллег проверил и сказал, что здесь нет проблем ... В любом случае спасибо за вашу помощь. Если у вас есть другие идеи, я вас слышу! :)
Прежде всего вы должны выгрузить результат вашего запроса, чтобы увидеть, что вы действительно получаете, прежде чем сериализовать.
Если вы попытаетесь json_encode для такого объекта, вы просто получите пустой json. Циклическая ссылка будет создана при попытке сериализации с использованием компонента сериализатора. Я обновлю свой ответ, чтобы прояснить это.
Когда я попытался использовать var_dump, я увидел, что вы имели в виду, вы правы, есть круговая ссылка, но я не могу решить проблему с группами, я пробовал ...
в чем была твоя проблема?
Ничего нового, отдача такая как у этого [{"id":1,"credits":0,"product":{},"statusId":2}]. Поле продукта должно быть массивом Json, который содержит таблицу продуктов моей базы данных.
вы, вероятно, неправильно установили атрибуты своей группы
Кроме того, когда я попытался добавить строку @Groups({"tariffs"}) только к одному параметру, чтобы увидеть, дает ли она мне только эту строку, это не так ... Я скопировал / прошил строку, которую вы мне дали
1. правильно ли вы установили и использовали сериализатор Symfony? 2. вы добавили свойство аннотаций группы? например: (/ ** * @Groups ({"тарифы"}) * /) Если да, то каков результат $ serializer-> serialize (...)?
извините, я забыл возврат. Я исправляю и получаю [[]]
разместите свою строку в контроллере, где вы используете сериализатор. также просто выгружайте результаты внутри контроллера и публикуйте то, что вы получаете, а не результат ответа json
Ниже моего обновления контроллера с помощью метода, который вы мне дали.
public function getTariffsAction(Request $request, SerializerInterface $serializer)
{
$category = new Category();
$category = $this->get('doctrine.orm.entity_manager')
->getRepository('AppBundle:Category')
->findAll();
$categoryJson = $serializer->serialize($category , 'json', ['groups' => ['tariffs'] ]);
return $this->json($categoryJson);
}
и когда я сбрасываю категорию $, я получаю то, что не могу вставить, потому что это слишком много. С Postman это делает мой компьютер очень глючным (один из моих экранов выключается), мне нужно перезагрузить после этого
Является ли $ categoryJson пустым строковым массивом? Вы как-то кешируете аннотации доктрины? Может быть, попытка очистить этот кеш поможет: php bin / console doctrine: cache: clear-metadata
Проблема решена, вы были абсолютно правы, потому что это была круговая ссылка, и я решил ее с группами, как вы сказали. (Я использовал FOSRestBundle для групп проще, чем собственные методы symfony)
Попробуйте запустить
php bin/console doctrine:schema:validate --skip-syncи посмотрите, нет ли ошибок сопоставления. `