How to save a Nested Relation with Entity on API Platform - php

I have two entities, Question and Alternative where Question has a OneToMany relation with Alternative and I'm trying to send a JSON with a nested document of Alternative on it via POST to Question API Platform.
The API Platform returns that error below :
Nested documents for "alternatives" attribute are not allowed. Use IRIs instead.
Searching about it I've found some people saying that is only possible using IRIs and some other people saying that is possible to use Denormalization and Normalization contexts to solve this problem but I can't find some example or tutorial about it.
TL;DR;
Is there a way to send a nested relation into an entity POST on API Platform without using IRIs?
UPDATE:
As asked, please see below the two mappings of Question and Alternative entities.
Question
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\QuestionRepository")
* #ApiResource()
*/
class Question implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Token", inversedBy="questions")
* #ORM\JoinColumn(nullable=false)
* #Assert\NotBlank()
*/
private $token;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Question", inversedBy="question_versions")
*/
private $question;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Question", mappedBy="question")
*/
private $question_versions;
/**
* #ORM\Column(type="integer")
* #Assert\NotBlank()
*/
private $version;
/**
* #ORM\Column(type="string", length=100)
* #Assert\Length(max="100")
* #Assert\NotBlank()
*
*/
private $name;
/**
* #ORM\Column(type="integer")
* #Assert\NotBlank()
*/
private $type;
/**
* #ORM\Column(type="text", length=65535)
* #Assert\NotBlank()
* #Assert\Length(max="65535")
*/
private $enunciation;
/**
* #ORM\Column(type="string", length=255, nullable=true)
* #Assert\Length(max="255")
*/
private $material;
/**
* #ORM\Column(type="text", length=65535, nullable=true)
* #Assert\Length(max="65535")
*/
private $tags;
/**
* #ORM\Column(type="boolean")
* #Assert\NotNull()
*/
private $public;
/**
* #ORM\Column(type="boolean")
* #Assert\NotNull()
*/
private $enabled;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $createdAt;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $updatedAt;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Alternative", mappedBy="question")
*/
private $alternatives;
/**
* #ORM\OneToMany(targetEntity="App\Entity\QuestionProperty", mappedBy="question")
*/
private $properties;
/**
* #ORM\OneToMany(targetEntity="App\Entity\QuestionAbility", mappedBy="question")
*/
private $abilities;
/**
* #ORM\OneToMany(targetEntity="QuestionCompetency", mappedBy="question")
*/
private $competencies;
}
Alternative
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\AlternativeRepository")
* #ORM\Table(name="alternatives")
* #ApiResource()
*/
class Alternative implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Question", inversedBy="alternatives")
* #ORM\JoinColumn(nullable=false)
* #Assert\NotBlank()
*/
private $question;
/**
* #ORM\Column(type="text", length=65535)
* #Assert\NotBlank()
* #Assert\Length(max="65535")
*/
private $enunciation;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $createdAt;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
*/
private $updatedAt;
/**
* #ORM\OneToMany(targetEntity="App\Entity\AlternativeProperty", mappedBy="alternatives")
*/
private $properties;
}

you can try implement Denormalization
Question:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\QuestionRepository")
* #ApiResource(
* denormalizationContext={"groups"={"post"}}
* )
*/
class Question implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Token", inversedBy="questions")
* #ORM\JoinColumn(nullable=false)
* #Assert\NotBlank()
* #Groups({"post"})
*/
private $token;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Question", inversedBy="question_versions")
* #Groups({"post"})
*/
private $question;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Question", mappedBy="question")
* #Groups({"post"})
*/
private $question_versions;
/**
* #ORM\Column(type="integer")
* #Assert\NotBlank()
* #Groups({"post"})
*/
private $version;
/**
* #ORM\Column(type="string", length=100)
* #Assert\Length(max="100")
* #Assert\NotBlank()
* #Groups({"post"})
*/
private $name;
/**
* #ORM\Column(type="integer")
* #Assert\NotBlank()
* #Groups({"post"})
*/
private $type;
/**
* #ORM\Column(type="text", length=65535)
* #Assert\NotBlank()
* #Assert\Length(max="65535")
* #Groups({"post"})
*/
private $enunciation;
/**
* #ORM\Column(type="string", length=255, nullable=true)
* #Assert\Length(max="255")
* #Groups({"post"})
*/
private $material;
/**
* #ORM\Column(type="text", length=65535, nullable=true)
* #Assert\Length(max="65535")
* #Groups({"post"})
*/
private $tags;
/**
* #ORM\Column(type="boolean")
* #Assert\NotNull()
* #Groups({"post"})
*/
private $public;
/**
* #ORM\Column(type="boolean")
* #Assert\NotNull()
* #Groups({"post"})
*/
private $enabled;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
* #Groups({"post"})
*/
private $createdAt;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
* #Groups({"post"})
*/
private $updatedAt;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Alternative", mappedBy="question")
* #Groups({"post"})
*/
private $alternatives;
/**
* #ORM\OneToMany(targetEntity="App\Entity\QuestionProperty", mappedBy="question")
* #Groups({"post"})
*/
private $properties;
/**
* #ORM\OneToMany(targetEntity="App\Entity\QuestionAbility", mappedBy="question")
* #Groups({"post"})
*/
private $abilities;
/**
* #ORM\OneToMany(targetEntity="QuestionCompetency", mappedBy="question")
* #Groups({"post"})
*/
private $competencies;
}
Alternative:
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity(repositoryClass="App\Repository\AlternativeRepository")
* #ORM\Table(name="alternatives")
* #ApiResource()
*/
class Alternative implements CreatedAtEntityInterface, UpdatedAtEntityInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Question", inversedBy="alternatives")
* #ORM\JoinColumn(nullable=false)
* #Assert\NotBlank()
* #Groups({"post"})
*/
private $question;
/**
* #ORM\Column(type="text", length=65535)
* #Assert\NotBlank()
* #Assert\Length(max="65535")
* #Groups({"post"})
*/
private $enunciation;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
* #Groups({"post"})
*/
private $createdAt;
/**
* #ORM\Column(type="datetime")
* #Assert\DateTime()
* #Groups({"post"})
*/
private $updatedAt;
/**
* #ORM\OneToMany(targetEntity="App\Entity\AlternativeProperty", mappedBy="alternatives")
* #Groups({"post"})
*/
private $properties;
}
Now you can this send JSON to POST/PUT without IRI:
{
"token": "/api/tokens/1",
"question": "string",
"version": "string",
"name": "string",
"type": 0,
"enunciation": "string",
"public": true,
"enabled": true,
"alternatives": [
{
"enunciation": "String",
"createdAt": "2018-01-01 11:11:11",
"updatedAt": "2018-01-01 11:11:11"
}
]
}

For anyone who has a problem with the error cascade persist you have to add it in the OneToMany property.That is, for our question:
#ORM\OneToMany(targetEntity="App\Entity\Alternative", mappedBy="question", cascade={"persist"})

Related

How to get a list of all the brands of my product entity?

I am new to both Symfony and API platform and trying to understand how to get all unique brands and product types of my products in a list so that I can use them later to display a list of filters to use in my frontend.
I'm a bit lost as to how to do this. I want to have a custom endpoint products/filters that would return me the list.
I would like to have it in this form:
{
brands: [
"Agilent",
"Comtr"
"Anot
],
types:[
"Accelerometer",
"Sonometer",
"Micro-amplifier"
]
}
Both brand and type are nested properties of my entity Product, they come from my entity ProductModel. I am using Api platform for my api that is why there is a lot of annotations.
class Product
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"product_get", "product_list"})
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity=ProductModel::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"product_get", "product_list"})
*/
private $idProductModel;
/**
* #ORM\Column(type="string", length=50)
* #Groups({"product_get", "product_list"})
* #Assert\NotBlank(message="The field serial number is mandatory.")
*/
private $serialNumber;
/**
* #ORM\Column(type="text", nullable=true)
* #Groups({"product_get"})
*/
private $comment;
/**
* #ORM\Column(type="datetime")
* #Groups({"product_get", "product_list"})
*/
private $createdAt;
/**
* #ORM\Column(type="datetime", nullable=true)
* #Groups({"product_get", "product_list"})
*/
private $updatedAt;
/**
* #ORM\Column(type="datetime", nullable=true)
* #Groups({"product_get"})
*
*/
private $deletedAt;
/**
* #ORM\Column(type="boolean")
* #Groups({"product_get", "product_list"})
* #Assert\NotBlank(message="The field confidential is mandatory.")
*
*/
private $confidential;
/**
* #ORM\ManyToOne(targetEntity=Storage::class, cascade={"persist"})
* #Groups({"product_get", "product_list"})
*/
private $idStorage;
/**
* #ORM\ManyToOne(targetEntity=User::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"product_get", "product_list"})
*/
private $idUser;
/**
* #ORM\ManyToOne(targetEntity=User::class, cascade={"persist"})
* #Groups({"product_get"})
*/
private $idUserDelete;
/**
* Many products can have many products
* #ORM\ManyToMany(targetEntity=Product::class, mappedBy="myProducts")
*/
private $partOfthisProduct;
/**
* Many products can have many products
* #ORM\ManyToMany(targetEntity=Product::class, inversedBy="partOfthisProduct")
* #JoinTable(name="product_has_product",
* joinColumns={#JoinColumn(name="product_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="related_product_id", referencedColumnName="id")}
* )
* #Groups({"product_get", "product_list"})
*/
private $myProducts;
/**
* #ORM\OneToMany(targetEntity=Sensor::class, mappedBy="product", cascade={"persist"})
* #Groups({"product_get", "product_list"})
* #ApiSubresource()
*/
private $sensors;
<?php
namespace App\Entity;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Annotation\ApiSubresource;
use App\Repository\ProductModelRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\Mapping\ManyToMany;
use Symfony\Component\Serializer\Annotation\Groups;
use Doctrine\ORM\Mapping\JoinTable;
use Doctrine\ORM\Mapping\JoinColumn;
/**
* #ORM\Entity(repositoryClass=ProductModelRepository::class)
* #ApiResource(
* itemOperations={"get"},
* collectionOperations={"get"},
* normalizationContext={
* "groups"={"read"}}
* )
*/
class ProductModel
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
* #Groups({"read", "product_get", "product_list"})
*/
private $id;
/**
* #ORM\Column(type="string", length=50)
* #Groups({"read", "product_get", "product_list"})
*/
private $modelName;
/**
* #ORM\ManyToOne(targetEntity=ProductType::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"read", "product_get", "product_list"})
*/
private $idProductType;
/**
* #ORM\ManyToOne(targetEntity=Unit::class)
*/
private $idInputUnit;
/**
* #ORM\ManyToOne(targetEntity=Unit::class)
*/
private $idOutputUnit;
/**
* #ORM\ManyToOne(targetEntity=Brand::class, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
* #Groups({"read", "sensor_get", "product_list"})
*/
private $idBrand;
/**
* #ORM\ManyToMany(targetEntity=TestType::class)
* #Groups({"read", "sensor_get", "product_get"})
*/
private $idTestsTypes;
/**
* #ORM\Column(type="integer", nullable=true)
* #Groups({"read", "sensor_get"})
*/
private $periodicity;
/**
* #ORM\Column(type="float", nullable=true)
* #Groups({"read", "sensor_get", "product_get"})
*/
private $nominalSensitivity;
/**
* #ORM\ManyToOne(targetEntity=TestType::class)
* #Groups({"read", "sensor_get", "product_get"})
*/
private $periodicityTest;
/**
* Many ProductModel have Many SensorModel.
* #ManyToMany(targetEntity="SensorModel")
* #JoinTable(name="productModel_sensorModels",
* joinColumns={#JoinColumn(name="Product_model_id", referencedColumnName="id")},
* inverseJoinColumns={#JoinColumn(name="Sensor_Model_id", referencedColumnName="id", unique=true)}
* )
* #Groups({"read", "sensor_get", "product_get"})
*/
private $sensorModels;
What would be the way to do this ? Thank you for your help.
Think the best way to do it is with a custom action that calls a method from the entity's repository.
First you add a custom operation to your #ApiResource definition, in the collectionOperations part in this case.
/**
* #ApiResource(
* itemOperations={"get","put","delete"},
* collectionOperations={
* "get","post",
* "types"={
* "method"="GET",
* "path"="/product_models/brands",
* "controller"=DistinctBrandsAction::class,
* "openapi_context"={
* "parameters"={}
* },
* "read"=false,
* }
* }
* )
* #ORM\Entity(repositoryClass=Repository::class)
*/
Then you add a method to your entity's repository (it would be ProductModelRepository in your case).
This method will query the collection and get the distinct values of the desired column. You'll have to modify this a bit to get the exact output you want (add the product types etc.):
//..blah blah.. use statements etc.
class ProductModelRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Report::class);
}
//this is the method you're adding:
//for symfony 3+ you use groupBy() instead of distinct() to get distinct values for a column
public function getDistinctBrands() {
return $this->createQueryBuilder('r')
->select('r.idBrand')
->groupBy('r.idBrand')
->getQuery()
->getResult();
}
}
Then you need to create a controller for your configured action that calls the method you added to the repository and then outputs it. (This would go in src/Controller/Action/DistinctBrandsAction.php if you're using autowiring)
<?php
namespace App\Controller\Action;
use App\Entity\Report;
use App\Repository\ProductModelRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
/**
* Class DistinctBrandsAction
*/
final class DistinctBrandsAction extends AbstractController
{
/**
* #param ProductModelRepository $productRepository
* #return Array
*/
public function __invoke(ProductModelRepository $productRepository): Array
{
return $productRepository->getDistinctBrands();
}
}
You can use the console to see what your resulting route is. It should be grouped with your ProductModel routes when running php bin/console debug:router
Further reading:
https://api-platform.com/docs/core/pagination/#custom-controller-action

Symfony / php : avoid query to give nested json objects from one to many relation

I have entities; Command, User, GiftCheck, and GiftCheckType :
GiftCheck
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\GiftCheckRepository")
*/
class GiftCheck
{
/**
* #ORM\Id()
* #ORM\Column(type="integer", length=255)
*#ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=255, columnDefinition="ENUM('Cadeau', 'Anniversaire', ' NĂ´el', 'Saint Valentain ')")
*/
private $theme;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="giftChecks")
*/
private $User;
/**
* #ORM\Column(type="string", length=255)
*/
private $uniqueSerialId;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Command", inversedBy="giftChecks")
* #ORM\JoinColumn(nullable=false)
*/
private $command;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\GiftCheckType", inversedBy="gift")
*/
private $giftCheckType;
User
<?php
namespace App\Entity;
use FOS\UserBundle\Model\User as BaseUser;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\UserInterface;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* #ORM\Entity
* #ORM\Table(name="fos_user")
* #UniqueEntity("email")
* #UniqueEntity("username")
* #UniqueEntity("tel")
*/
class User extends BaseUser
{
/**
* #ORM\Id
*#ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $firstname;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Command", mappedBy="user")
*/
private $commands;
/**
* #ORM\OneToMany(targetEntity="App\Entity\GiftCheck", mappedBy="User")
*/
private $giftChecks;
Command
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\CommandRepository")
*/
class Command
{
/**
* #ORM\Id()
* #ORM\Column(type="string", length=255)
*/
private $id;
/**
* #ORM\Column(type="float")
*/
private $price;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="commands")
* #ORM\JoinColumn(nullable=true, onDelete="CASCADE")
*/
private $user;
/**
* #ORM\OneToMany(targetEntity="App\Entity\CommandLine", mappedBy="command")
*/
private $commandLines;
/**
* #ORM\Column(type="string", length=255)
*/
private $status;
/**
* #ORM\OneToMany(targetEntity="App\Entity\GiftCheck", mappedBy="command")
*/
private $giftChecks;
GiftCheckType
<?php
namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="App\Repository\GiftCheckTypeRepository")
*/
class GiftCheckType
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $designation;
/**
* #ORM\OneToMany(targetEntity="App\Entity\GiftCheck", mappedBy="giftCheckType")
*/
private $gift;
/**
* #ORM\Column(type="string", length=255)
*/
private $type;
I found my self faced to a problem, When I try to fetch my command data I got a nested json object ( like children / parent / children structure of the same object ) which contain giftchecks array, every giftcheck contain user object which have the same giftchecks list, the two images bellow describe the status of this nested JSON in the browser console log when a fetch the result with angular :
is that problem about missing serialization on my entities or coming from other side ? are my entities relations correctly coded ?
please change User entity as
/**
* #ORM\OneToMany(targetEntity="App\Entity\Command", mappedBy="user", fetch="LAZY")
*/
private $commands;
/**
* #ORM\OneToMany(targetEntity="App\Entity\GiftCheck", mappedBy="User", fetch="LAZY")
*/
private $giftChecks;
you can change other entities too if you wish
https://www.doctrine-project.org/projects/doctrine-orm/en/2.7/reference/annotations-reference.html#onetomany
also see EXTRA_LAZY for performance
https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/tutorials/extra-lazy-associations.html#extra-lazy-associations

The target-entity cannot be found in 'AppBundle\Entity\User#bitcoinWallet'

I am using Symfony 3 and want to map Entity Userto have many BitcoinWallet
My AppBundle\Entity\User.php looks like that:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
/**
* #ORM\Entity
* #ORM\Table(name="user")
*/
class User extends BaseUser
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #var string
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $firstName;
/**
* #var string
* #ORM\Column(type="string", length=255, nullable=true)
*/
protected $lastName;
/**
* #ORM\Column(type="string", length=255, nullable=true)
* #Assert\File(maxSize="2048k")
* #Assert\Image(mimeTypesMessage="Please upload a valid image.")
*/
protected $profilePicture;
/**
* #Assert\Email(
* message = "The email '{{ value }}' is not a valid email.",
* checkMX = true
* )
*/
protected $email;
protected $emailCanonical;
/**
* #ORM\ManyToOne(targetEntity="BitcoinBundle\Entity\BitcoinWallet")
* #ORM\JoinColumn(name="bitcoin_wallet", referencedColumnName="id")
*/
protected $bitcoinWallet;
/**
* #var \DateTime $created
*
* #Gedmo\Timestampable(on="create")
* #ORM\Column(type="datetime")
*/
private $created;
/**
* #var \DateTime $updated
*
* #Gedmo\Timestampable(on="update")
* #ORM\Column(type="datetime")
*/
private $updated;
My BitcoinBundle\Entity\BitcoinWallet is below:
<?php
namespace BitcoinBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass="BitcoinBundle\Entity\BitcoinWalletRepository")
* #ORM\Table(name="bitcoin_wallet")
* #ORM\HasLifecycleCallbacks
*/
class BitcoinWallet
{
/**
* in use = The address is being used for some reason
* available = the address is free
*/
const STATE_IN_USE = 0;
const STATE_AVAILABLE = 1;
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column
* #ORM\GeneratedValue(strategy="NONE")
* #ORM\Column(type="string", length=34, unique=true)
*/
private $address;
/**
* #ORM\Column(name="state", type="smallint")
*/
private $state;
/**
* #ORM\Column(name="balance", type="decimal", precision=16, scale=8)
*/
private $balance = 0;
/**
* #ORM\Column(name="updated_at", type="datetime")
*/
private $updated_at;
After I run php bin/console doctrine:schema:update --force database was updated successfully, but now I am getting this message:
The target-entity BitcoinBundle\Entity\BitcoinWallet cannot be found in 'AppBundle\Entity\User#bitcoinWallet'.
It looks like entity declaration was incorrect.
In BitcoinBundle\Entity\BitcoinWallet should be ManyToOne statment:
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="bitcoin_wallet")
*/
protected $id;
And ManyToOne statment in AppBundle\Entity\User.php is wrong one.

Doctrine ORM Bind Product to Multiple Entities

I have businesses, categories and products. Categories are assigned to businesses and products are assigned to categories and businesses.
Reason being, one product can be assigned to different categories in different businesses.
Business and Category entities are working fine, but I am not sure how to write a Product entity to achieve what I need...
Business Entity:
namespace Raiel\AFMage\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
* #ORM\Table(name="businesses")
*/
class Business {
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer", name="id")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=64)
*/
private $name;
/**
*
* #ORM\ManyToMany(targetEntity="Category", inversedBy="businesses")
* #ORM\JoinTable(
* name="business_categories",
* joinColumns={
* #ORM\JoinColumn(name="business_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
* }
* )
*/
private $categories;
/**
* Default constructor, initializes collections
*/
public function __construct() {
$this->categories = new ArrayCollection();
}
}
Category Entity:
<?php
namespace Raiel\AFMage\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* #Gedmo\Tree(type="nested")
* #ORM\Table(name="categories")
* #ORM\Entity(repositoryClass="Gedmo\Tree\Entity\Repository\NestedTreeRepository")
*/
class Category {
/**
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue
*/
private $id;
/**
*
* #ORM\ManyToMany(targetEntity="Business", mappedBy="categories")
*/
private $businesses;
/**
* #Gedmo\TreePath
* #ORM\Column(name="path", type="string", length=3000, nullable=true)
*/
private $path;
/**
* #ORM\Column(name="title", type="string", length=64)
*/
private $title;
/**
* #Gedmo\TreeLevel
* #ORM\Column(name="lvl", type="integer")
*/
private $lvl;
/**
* #Gedmo\TreeLeft
* #ORM\Column(name="lft", type="integer")
*/
private $lft;
/**
* #Gedmo\TreeRight
* #ORM\Column(name="rgt", type="integer")
*/
private $rgt;
/**
* #Gedmo\TreeRoot
* #ORM\Column(name="root", type="integer", nullable=true)
*/
private $root;
/**
* #Gedmo\TreeParent
* #ORM\ManyToOne(targetEntity="Category", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $parent;
/**
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent")
* #ORM\OrderBy({"lft" = "ASC"})
*/
private $children;
/**
* Constructor
*/
public function __construct() {
$this->children = new ArrayCollection();
$this->businesses = new ArrayCollection();
}
}
Also, $business->addCategory works fine but $category->addBusiness doesn't save to DB.
Your product entity will probably look something like:
namespace Raiel\AFMage\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity()
* #ORM\Table(name="products")
*/
class Product {
/**
* #ORM\Id()
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer", name="id")
*/
private $id;
/**
* #ORM\Column(name="name", type="string", length=64)
*/
private $name;
/**
*
* #ORM\ManyToMany(targetEntity="Category", inversedBy="products")
* #ORM\JoinTable(
* name="product_categories",
* joinColumns={
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
* }
* )
*/
private $categories;
/**
*
* #ORM\ManyToMany(targetEntity="Business", inversedBy="products")
* #ORM\JoinTable(
* name="product_businesses",
* joinColumns={
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
* },
* inverseJoinColumns={
* #ORM\JoinColumn(name="business_id", referencedColumnName="id")
* }
* )
*/
private $businesses;
}
So more or less what you have for your Business entity but with the ManyToMany relation using a different join table.
And to make $category->addBusiness() work then you'll probably want to add a cascade option to category, thusly:
/**
*
* #ORM\ManyToMany(targetEntity="Business", mappedBy="categories", cascade="persist")
*/
private $businesses;
This informs Doctrine that anything new added to the $businesses array collection should be persisted, take a look at the documentation for details.

Doctrine Extensions Symfony2

I install Doctrine Extensions like here How to install Doctrine Extensions in a Symfony2 project
This is my Entity Class
<?php
namespace My\NewsBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
/**
* News
*
* #ORM\Table()
* #ORM\Entity
*/
class News
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=150)
*/
protected $title;
/**
* #ORM\Column(type="text")
*/
protected $content;
/**
* #ORM\Column(type="text")
*/
protected $description;
/**
* #ORM\Column(type="string", length=150)
*/
protected $keywords;
/**
* #Gedmo\Slug(fields={"title"})
* #ORM\Column(length=128, unique=true)
*/
private $slug;
/**
* #Gedmo\Timestampable(on="create")
* #ORM\Column(name="created_at", type="datetime")
*/
private $created_at;
/**
* #ORM\Column(name="updated_at", type="datetime")
* #Gedmo\Timestampable(on="update")
*/
private $updated_at;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
}
php app/console doctrine:generate:entities My
gives me a a error
[Doctrine\Common\Annotations\AnnotationException]
[Semantical Error] The annotation "#Gedmo\Mapping\Annotation\Slug" in property My\NewsBundle\Entity\News::$slug does not exist, or could not be auto -loaded.
Should i add something in config or someting else? Thanks for help.

Categories