Symfony 4 : doctrine, relationships and twig - doctrine

I'm currently working on my first symfony 4 project and I'm having a problem with my twig templating.
First of all here is a UML diagram of my created objects.
And my layout should look sorta like this :
Here are my entities :
Region
<?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\RegionRepository")
*/
class Region
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $designation;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Country", mappedBy="region", orphanRemoval=true)
*/
private $countries;
/**
* #ORM\Column(type="string", length=255)
*/
private $initials;
public function __construct()
{
$this->countries = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getDesignation(): ?string
{
return $this->designation;
}
public function setDesignation(string $designation): self
{
$this->designation = $designation;
return $this;
}
/**
* #return Collection|Country[]
*/
public function getCountries(): Collection
{
return $this->countries;
}
public function addCountry(Country $country): self
{
if (!$this->countries->contains($country)) {
$this->countries[] = $country;
$country->setRegion($this);
}
return $this;
}
public function removeCountry(Country $country): self
{
if ($this->countries->contains($country)) {
$this->countries->removeElement($country);
// set the owning side to null (unless already changed)
if ($country->getRegion() === $this) {
$country->setRegion(null);
}
}
return $this;
}
public function getInitials(): ?string
{
return $this->initials;
}
public function setInitials(string $initials): self
{
$this->initials = $initials;
return $this;
}
public function __toString()
{
return $this->getInitials();
}
}
Continent
<?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\ContinentRepository")
*/
class Continent
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="string", length=255)
*/
private $code;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Country", mappedBy="continent", orphanRemoval=true)
*/
private $countries;
public function __construct()
{
$this->countries = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getCode(): ?string
{
return $this->code;
}
public function setCode(string $code): self
{
$this->code = $code;
return $this;
}
/**
* #return Collection|Country[]
*/
public function getCountries(): Collection
{
return $this->countries;
}
public function addCountry(Country $country): self
{
if (!$this->countries->contains($country)) {
$this->countries[] = $country;
$country->setContinent($this);
}
return $this;
}
public function removeCountry(Country $country): self
{
if ($this->countries->contains($country)) {
$this->countries->removeElement($country);
// set the owning side to null (unless already changed)
if ($country->getContinent() === $this) {
$country->setContinent(null);
}
}
return $this;
}
public function __toString()
{
return $this->getName();
}
}
Country
<?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\CountryRepository")
*/
class Country
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="string", length=255)
*/
private $iso;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Region", inversedBy="countries")
* #ORM\JoinColumn(name="region_id", referencedColumnName="id")
*/
private $region;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Document", mappedBy="country", orphanRemoval=true)
*/
private $documents;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Continent", inversedBy="countries")
* #ORM\JoinColumn(name="continent_id", referencedColumnName="id")
*/
private $continent;
public function __construct()
{
$this->documents = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getIso(): ?string
{
return $this->iso;
}
public function setIso(string $iso): self
{
$this->iso = $iso;
return $this;
}
public function getRegion(): ?Region
{
return $this->region;
}
public function setRegion(?Region $region): self
{
$this->region = $region;
return $this;
}
/**
* #return Collection|Document[]
*/
public function getDocuments(): Collection
{
return $this->documents;
}
public function addDocument(Document $document): self
{
if (!$this->documents->contains($document)) {
$this->documents[] = $document;
$document->setCountry($this);
}
return $this;
}
public function removeDocument(Document $document): self
{
if ($this->documents->contains($document)) {
$this->documents->removeElement($document);
// set the owning side to null (unless already changed)
if ($document->getCountry() === $this) {
$document->setCountry(null);
}
}
return $this;
}
public function getContinent(): ?Continent
{
return $this->continent;
}
public function setContinent(?Continent $continent): self
{
$this->continent = $continent;
return $this;
}
}
Document
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
use Symfony\Component\HttpFoundation\File\File;
/**
* #ORM\Entity(repositoryClass="App\Repository\DocumentRepository")
* #Vich\Uploadable()
*/
class Document
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Country", inversedBy="documents")
* #ORM\JoinColumn(name="country_id", referencedColumnName="id")
*/
private $country;
/**
* #ORM\Column(type="string")
*/
private $level;
/**
* NOTE: This is not a mapped field of entity metadata, just a simple property.
*
* #Vich\UploadableField(mapping="country_document", fileNameProperty="documentName", size="documentSize")
*
* #var File
*/
private $documentFile;
/**
* #ORM\Column(type="string", length=255)
*
* #var string
*/
private $documentName;
/**
* #ORM\Column(type="integer")
*
* #var integer
*/
private $documentSize;
/**
* #ORM\Column(type="datetime")
*
* #var \DateTime
*/
private $updatedAt;
public function getId()
{
return $this->id;
}
public function getCountry(): ?Country
{
return $this->country;
}
public function setCountry(?Country $country): self
{
$this->country = $country;
return $this;
}
public function getLevel(): ?int
{
return $this->level;
}
public function setLevel(int $level): self
{
$this->level = $level;
return $this;
}
public function setDocumentFile(?File $document = null): void
{
$this->documentFile = $document;
if (null !== $document) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
}
public function getDocumentFile(): ?File
{
return $this->documentFile;
}
public function setDocumentName(?string $documentName): void
{
$this->documentName = $documentName;
}
public function getDocumentName(): ?string
{
return $this->documentName;
}
public function setDocumentSize(?int $documentSize): void
{
$this->documentSize = $documentSize;
}
public function getDocumentSize(): ?int
{
return $this->documentSize;
}
}
I have 4 regions. These regions each have multiple countries who are affiliated to a continent and have 2 documents attributed to them.
How should I proceed to get the layout I want ?

Related

Laravel: Stop using UUID as foreign key

Laravel is trying to use uuid field as foreign key. And I want to use foreign key with the field id. Is there any option there?
Using this trait on Model. And then it is trying to use the uuid as foreign key. But still I want to use id as foreign key.
<?php
namespace App\Library;
use Ramsey\Uuid\Uuid;
trait UsesUuid
{
/**
* #return string
*/
public function getKeyName()
{
return 'uuid';
}
/**
* #return string
*/
public function getKeyType()
{
return 'string';
}
/**
* #return false
*/
public function getIncrementing()
{
return false;
}
/**
* #param $query
* #param $uuid
* #return mixed
*/
public function scopeUuid($query, $uuid)
{
return $query->where($this->getUuidName(), $uuid);
}
/**
* #return string
*/
public function getUuidName()
{
return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
}
/**
* #return string
*/
public function getRouteKeyName()
{
return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
}
/**
*
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->{$model->getUuidName()} = Uuid::uuid4()->toString();
});
}
}
There is nothing special about this trait. You can make your own trait with id instead of uuid and everything will work fine.
The issue came from methods getIncrementing() and getKeyName(). Laravel calls getKeyName() in amount of built-in functions to interacts with relationships, also other actions like delete(), route bindings, etc.
You should allow any models which uses this trait to custom the Primary key (PK), so that uuid is only common column at all.
Your trait definition is force PK column as uuid.
Below is my recommended for the trait
<?php
namespace App\Library;
use Ramsey\Uuid\Uuid;
trait UsesUuid
{
/* Override this method to set `uuid` as PK */
public function isUuidAsPrimaryKey()
{
return false;
}
/**
* #return string
*/
public function getKeyName()
{
return $this->isUuidAsPrimaryKey() ? $this->getUuidName() : $this->primaryKey;
}
/**
* #return string
*/
public function getKeyType()
{
return $this->isUuidAsPrimaryKey() ? 'string' : $this->keyType;
}
/**
* #return false
*/
public function getIncrementing()
{
return !$this->isUuidAsPrimaryKey();
}
/**
* #param $query
* #param $uuid
* #return mixed
*/
public function scopeUuid($query, $uuid)
{
return $query->where($this->getUuidName(), $uuid);
}
/**
* #return string
*/
public function getUuidName()
{
return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
}
/**
* #return string
*/
public function getRouteKeyName()
{
return property_exists($this, 'uuidName') ? $this->uuidName : 'uuid';
}
/**
*
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
$model->{$model->getUuidName()} = Uuid::uuid4()->toString();
});
}
}
If a model need to have uuid as PK, for example Book model
class Book extends Model
{
use UsesUuid;
public function isUuidAsPrimaryKey()
{
return true;
}
}
Please recheck the method isUuidAsPrimaryKey. If it may not be overridden (due to conflict), then use a property instead.

Unable to save (A new entity was found through the relationship)

Error Message:
"A new entity was found through the relationship
'AppBundle\Entity\Category#products' that was not configured to
cascade persist operations for entity:
AppBundle\Entity\Product#00000000133d712400000000104ed306. To solve
this issue: Either explicitly call EntityManager#persist() on this
unknown entity or configure cascade persist this association in the
mapping for example #ManyToOne(..,cascade={"persist"}). If you cannot
find out which entity causes the problem implement
'AppBundle\Entity\Product#__toString()' to get a clue."
/AppBundle/Entity/Product
class Product
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
*/
private $name;
/**
* #ORM\Column(type="decimal", scale=2)
*/
private $price;
/**
* #ORM\Column(type="text")
*/
private $description;
/**
* #ORM\ManyToOne(targetEntity="Category", inversedBy="products")
* #ORM\JoinColumn(name="category_id", referencedColumnName="id")
*/
private $category;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Product
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Set price
*
* #param string $price
*
* #return Product
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* Get price
*
* #return string
*/
public function getPrice()
{
return $this->price;
}
/**
* Set description
*
* #param string $description
*
* #return Product
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get description
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set category
*
* #param \AppBundle\Entity\Category $category
*
* #return Product
*/
public function setCategory(\AppBundle\Entity\Category $category = null)
{
$this->category = $category;
return $this;
}
/**
* Get category
*
* #return \AppBundle\Entity\Category
*/
public function getCategory()
{
return $this->category;
}
}
/AppBundle/Entity/Category
class Category
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var string
*
* #ORM\Column(name="name", type="string", length=255)
*/
protected $name;
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category")
*/
protected $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* #param string $name
*
* #return Category
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
/**
* Add product
*
* #param \AppBundle\Entity\Product $product
*
* #return Category
*/
public function addProduct(\AppBundle\Entity\Product $product)
{
$this->products[] = $product;
return $this;
}
/**
* Remove product
*
* #param \AppBundle\Entity\Product $product
*/
public function removeProduct(\AppBundle\Entity\Product $product)
{
$this->products->removeElement($product);
}
/**
* Get products
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProducts()
{
return $this->products;
}
}
/AppBundle/Form/CategoryType
class CategoryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name');
$builder->add('products', CollectionType::class, array(
'entry_type' => ProductType::class
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Category'
));
}
public function getName()
{
return 'category';
}
}
/AppBundle/Form/ProductType
class ProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name')
->add('price')
->add('description');
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\Product',
));
}
public function getName()
{
return 'app_bundle_product_type';
}
}
/AppBundle/Controller/CategoryController
class CategoryController extends Controller
{
/**
* #Route("/category/new", name="category_new")
*
*/
public function newAction(Request $request)
{
$category = new Category();
$product = new Product();
$category->getProducts()->add($product);
$form = $this->createForm(CategoryType::class, $category);
$form->handleRequest($request);
if ($form->isValid() && $form->isSubmitted()) {
$em = $this->getDoctrine()->getManager();
$em->persist($category);
$em->flush();
}
return $this->render('category/new.html.twig', array(
'form' => $form->createView(),
));
}
}
/category/new.html.twig
{% extends 'base.html.twig' %}
{% block body %}
{{ form_start(form) }}
{{ form_widget(form) }}
<button type="submit" class="btn btn-primary">Save</button>
{{ form_end(form) }}
{% endblock %}
You should change association in order to tell doctrine to persist all new category products
...
/**
* #ORM\OneToMany(targetEntity="Product", mappedBy="category", cascade={"persist", "remove"})
*/
protected $products;
...
or persist it manually
...
$em->persist($category);
$em->persist($product);
$em->flush();
...
Also set category for product
...
$product = new Product();
$product->setCategory($category);
...

Doctrine 2: cascade persist Oracle "IDENTITY" is returning 0 as last inserted ID

I am using doctrine 2 with oracle, the tables in the database has some triggers that generate the IDs, and my ID mapping of my tables is like the following:
/**
* #orm\Id
* #orm\Column(type="integer");
* #orm\GeneratedValue(strategy="IDENTITY")
*/
protected $id;
and I have a OneToMany relation, with cascade={"persist"} but it is not working, I tried the same code with MySQL and it is working fine, but in oracle the last insert Id seems to always return 0 instead of the real id of the inserted row... and so the cascade persist is not working... is this a bug in doctrine or am I doing something wrong? any help?
After following the code it seems that the method
Doctrine\ORM\Id\IdentityGenerator::generate
is returning 0, I don't know why it is being invoked since the sequenceName is null (there is no sequence in the deffinition!
EDIT: Here are the entities:
The Client Entity:
/**
* #ORM\Entity
* #ORM\Table(name="clients")
**/
class Client {
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
protected $id;
/** #ORM\Column(name="name",type="string",length=255,unique=true) */
protected $name;
/**
* #ORM\OneToMany(targetEntity="ContactInformation", mappedBy="client", cascade={"persist"})
**/
protected $contactInformations;
public function __construct() {
$this->contactInformations = new ArrayCollection();
}
public function getId() {
return $this->id;
}
public function getName() {
return $this->name;
}
public function setName($name) {
$this->name = $name;
return $this;
}
public function getContactInformations() {
return $this->contactInformations;
}
public function addContactInformations(Collection $contactInformations)
{
foreach ($contactInformations as $contactInformation) {
$contactInformation->setClient($this);
$this->contactInformations->add($contactInformation);
}
}
/**
* #param Collection $tags
*/
public function removeContactInformations(Collection $contactInformations)
{
foreach ($contactInformations as $contactInformation) {
$contactInformation->setClient(null);
$this->contactInformations->removeElement($contactInformation);
}
}
public function setContactInformations($contactInformations) {
$this->contactInformations = $contactInformations;
return $this;
}
}
The Contact Information Entity:
/**
* #ORM\Entity
* #ORM\Table(name="contact_informations")
**/
class ContactInformation {
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
protected $id;
/**
* #ORM\OneToOne(targetEntity="ContactInformationType")
* #ORM\JoinColumn(name="type_id", referencedColumnName="id")
**/
protected $type;
/** #ORM\Column(type="text") */
protected $value;
/**
* #ORM\ManyToOne(targetEntity="Client", inversedBy="contact_informations")
* #ORM\JoinColumn(name="client_id", referencedColumnName="id")
**/
private $client;
public function getId() {
return $this->id;
}
public function getType() {
return $this->type;
}
public function setType($type) {
$this->type = $type;
return $this;
}
public function getValue() {
return $this->value;
}
public function setValue($value) {
$this->value = $value;
return $this;
}
public function getClient() {
return $this->client;
}
public function setClient($client = null) {
$this->client = $client;
return $this;
}
}
Oracle doesn't support auto incrementing, so you cannot use the "IDENTITY" strategy in Doctrine. You'll have to use the "SEQUENCE" (or "AUTO") strategy.
When specifying "AUTO", Doctrine will use "IDENTITY" for MySql and "SEQUENCE" for Oracle.
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/basic-mapping.html#identifier-generation-strategies

oneToOne issue with Doctrine

I have 2 tables and I am trying to create a OneToOne assocation with doctrine using the zend framework, my error is as follows, table structure and entity code including controller code can be found below, any idea why I am getting this error?
Fatal error: Call to undefined method Closure::getDate() in C:\htdocs\ea2\module\Easchnitstelle\view\easchnitstelle\transactions\index.phtml on line 132
Table Structure
CREATE TABLE `transaction` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`file_id` int(10) unsigned NOT NULL,
`meta_data_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10386 DEFAULT CHARSET=utf8$$
CREATE TABLE `transaction_meta_data` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`meta_data_sender_id` int(10) unsigned NOT NULL,
`sender_account` float NOT NULL,
`sum_amounts` float NOT NULL,
`count` smallint(5) unsigned NOT NULL,
`date` date DEFAULT NULL,
`sum_bankcodes` float NOT NULL,
`sum_accounts` float NOT NULL,
`type` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10386 DEFAULT CHARSET=utf8$$
Here are my two entities:
namespace Easchnitstelle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* Entity Class representing a Post of our Zend Framework 2 Blogging Application
*
* #ORM\Entity
* #ORM\Table(name="transaction")
* #property int $id
* #property string $file_id
* #property string $meta_data_id
*/
class Transaction
{
/**
* #ORM\Id #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/** #ORM\Column(type="integer") */
protected $file_id;
/** #ORM\Column(type="integer") */
protected $meta_data_id;
/**
* #ORM\OneToMany(targetEntity="TransactionData", mappedBy="transaction")
* #ORM\JoinColumn(name="transaction_id", referencedColumnName="id")
**/
private $TransactionData;
/**
* #ORM\OneToOne(targetEntity="TransactionMetaData", mappedBy="transaction")
* #ORM\JoinColumn(name="meta_data_id", referencedColumnName="id")
**/
private $TransactionMetaData;
public function __construct() {
$this->TransactionData = new ArrayCollection();
$this->TransactionMetaData = new ArrayCollection();
}
public function getTransactionData() {
return $this->TransactionData;
}
public function setTransactionData($TransactionData){
$this->TransactionData = $TransactionData;
return $this;
}
public function getTransactionMetaData() {
return $this->TransactionMetaData;
}
public function setTransactionMetaData($TransactionMetaData){
$this->TransactionMetaData = $TransactionMetaData;
return $this;
}
public function setId($id){
$this->id = $id;
return $this;
}
public function getId(){
return $this->id;
}
public function setFileId($file_id){
$this->file_id = $file_id;
return $this;
}
public function getFileId(){
return $this->file_id;
}
public function setMetaDataId($meta_data_id){
$this->meta_data_id = $meta_data_id;
return $this;
}
public function getMetaDataId(){
return $this->meta_data_id;
}
}
And:
<?php
namespace Easchnitstelle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
/**
* This class is somewhere in your library
* #ORM\Entity
* #ORM\Table(name="transaction_meta_data")
*/
class TransactionMetaData {
/**
* #ORM\Id #ORM\Column(type="integer")
* #ORM\GeneratedValue
*/
protected $id;
/** #ORM\Column(type="integer") */
protected $meta_data_sender_id;
/** #ORM\Column(type="float") */
protected $sum_amounts;
/** #ORM\Column(type="float") */
protected $count;
/** #ORM\Column(type="date") */
protected $date;
/** #ORM\Column(type="float") */
protected $sum_bankcodes;
/** #ORM\Column(type="float") */
protected $sum_accounts;
/** #ORM\Column(type="integer") */
protected $type;
/**
* #ORM\OneToOne(targetEntity="Transaction", mappedBy="TransactionMetaData")
* #ORM\JoinColumn(name="meta_data_id", referencedColumnName="id")
**/
protected $transaction;
public function setId($id){
$this->id = $id;
return $this;
}
public function getId(){
return $this->id;
}
public function getSumAmounts() {
return $this->sum_amounts;
}
public function setSumAmounts($sum_amounts) {
$this->sum_amounts = $sum_amounts;
}
public function getCount() {
return $this->count;
}
public function setCount($count) {
$this->count = $count;
}
public function getDate() {
return $this->date;
}
public function setDate($date) {
$this->date = $date;
}
public function getSumBankcodes() {
return $this->sum_bankcodes;
}
public function setSumBankcodes($sum_bankcodes) {
$this->sum_bankcodes = $sum_bankcodes;
}
public function getSumAccounts() {
return $this->sum_accounts;
}
public function setSumAccounts($sum_accounts) {
$this->sum_accounts = $sum_accounts;
}
public function getType() {
return $this->type;
}
public function setType($type) {
$this->type = $type;
}
}
Below is the code in my view:
foreach($Transactions as $t){
$amount = '';
foreach($t->getTransactionData() as $t_data){
//echo $amount = $t_data->getPurposes();
}
//die;
//echo get_class($t->getTransactionData());
//$tm_data = $t->getTransactionMetaData();
foreach($t->getTransactionMetaData() as $tm_data){
//echo get_class($t->getTransactionMetaData());
$date = $tm_data->getDate();
echo $date;
die;
}
$data[] = array($amount);
}
The relation is a 1:1, not a 1:n. Why do you use the foreach keyword?
As I see your code, it should simply look like this:
foreach($Transactions as $transaction) {
$metadata = $transaction->getTransactionMetaData();
echo $metadata->getDate();
}
There is no foreach required with getTransactionMetaData()

Doctrine gives null while trying to access property of property

I am using Doctrine with CodeIgniter.
I can't access the category with this usage. $record is not null but $category is null.
$record_data = $this->getRepository('Entity\RecordData')->find($this->params['id']);
$record = $record_data->getRecord();
$category = $record->getCategory();
echo $category->getName();
Last line gives Fatal error: Call to a member function getName() on a non-object.
What am i doing wrong? Can you have a look please. Thanks.
Here is my entity classes.
Entity\RecordData:
<?php
namespace Entity;
/**
* #Entity(repositoryClass="RecordDataRepository")
* #Table(name="record_data")
*/
class RecordData {
/**
* #Id
* #Column(type="integer", nullable=false)
* #GeneratedValue(strategy="AUTO")
*/
protected $ID;
/**
* #ManyToOne(targetEntity="CategoryVariable")
* #JoinColumn(name="CategoryVariableID", referencedColumnName="ID")
*/
protected $CategoryVariable;
/**
* #ManyToOne(targetEntity="Record")
* #JoinColumn(name="RecordID", referencedColumnName="ID")
*/
protected $Record;
/**
* #ManyToOne(targetEntity="SkillLevel")
* #JoinColumn(name="SkillLevelID", referencedColumnName="ID")
*/
protected $SkillLevel = NULL;
/**
* #Column(type="string", length=255, nullable=true)
*/
protected $Value;
/**
* #Column(type="integer", nullable=false)
*/
protected $RecordDataOrder;
/**
* #Column(type="boolean", nullable=false)
*/
protected $Deleted = FALSE;
public function __construct(Record $record, CategoryVariable $category_variable)
{
$this->Record = $record;
$this->CategoryVariable = $category_variable;
}
public function getID()
{
return $this->ID;
}
public function getCategoryVariable()
{
return $this->CategoryVariable;
}
public function getRecord()
{
return $this->Record;
}
public function setSkillLevel($SkillLevel)
{
$this->SkillLevel = $SkillLevel;
}
public function getSkillLevel()
{
return $this->SkillLevel;
}
public function setValue($Value)
{
$this->Value = $Value;
}
public function getValue()
{
return $this->Value;
}
public function setRecordDataOrder($RecordDataOrder)
{
$this->RecordDataOrder = $RecordDataOrder;
}
public function getRecordDataOrder()
{
return $this->RecordDataOrder;
}
public function delete()
{
$this->Deleted = TRUE;
}
}
Entity\Record:
<?php
namespace Entity;
/**
* #Entity(repositoryClass="RecordRepository")
* #Table(name="record")
*/
class Record {
/**
* #Id
* #Column(type="integer", nullable=false)
* #GeneratedValue(strategy="AUTO")
*/
protected $ID;
/**
* #ManyToOne(targetEntity="Category")
* #JoinColumn(name="CategoryID", referencedColumnName="ID")
*/
protected $Category;
/**
* #Column(type="string", length=255, nullable=true)
*/
protected $Name;
/**
* #Column(type="integer", nullable=false)
*/
protected $RecordOrder;
/**
* #Column(type="string", length=255, nullable=true)
*/
protected $Description;
/**
* #Column(type="boolean", nullable=false)
*/
protected $Deleted = FALSE;
public function __construct(Category $category)
{
$this->Category = $category;
}
public function getID()
{
return $this->ID;
}
public function setCategory($Category)
{
$this->Category = $Category;
}
public function getCategory()
{
return $this->Category;
}
public function setName($Name)
{
$this->Name = $Name;
}
public function getName()
{
return $this->Name;
}
public function setRecordOrder($RecordOrder)
{
$this->RecordOrder = $RecordOrder;
}
public function getRecordOrder()
{
return $this->RecordOrder;
}
public function setDescription($Description)
{
$this->Description = $Description;
}
public function getDescription()
{
return $this->Description;
}
public function delete()
{
$this->Deleted = TRUE;
}
}
Entity\Category:
<?php
namespace Entity;
use Doctrine\Common\Collections\ArrayCollection;
/**
* #Entity(repositoryClass="CategoryRepository")
* #Table(name="category")
*/
class Category {
/**
* #Id
* #Column(type="integer", nullable=false)
* #GeneratedValue(strategy="AUTO")
*/
protected $ID;
/**
* #Column(type="string", length=255)
*/
protected $Name;
/**
* #Column(type="string", length=255)
*/
protected $Description;
/**
* #Column(type="integer", nullable=false)
*/
protected $CategoryOrder;
/**
* #Column(type="boolean", nullable=false)
*/
protected $IsMultiple;
/**
* #Column(type="boolean", nullable=false)
*/
protected $Deleted = FALSE;
public function getID()
{
return $this->ID;
}
public function setName($Name)
{
$this->Name = $Name;
}
public function getName()
{
return $this->Name;
}
public function setDescription($Description)
{
$this->Description = $Description;
}
public function getDescription()
{
return $this->Description;
}
public function setCategoryOrder($CategoryOrder)
{
$this->CategoryOrder = $CategoryOrder;
}
public function getCategoryOrder()
{
return $this->CategoryOrder;
}
public function setIsMultiple($IsMultiple)
{
$this->IsMultiple = $IsMultiple;
}
public function getIsMultiple()
{
return $this->IsMultiple;
}
public function delete()
{
$this->Deleted = TRUE;
}
/**
* #var CategoryVariable[]
* #OneToMany(targetEntity="CategoryVariable", mappedBy="Category")
*/
protected $CategoryVariables = NULL;
/**
* #var Record[]
* #OneToMany(targetEntity="Record", mappedBy="Category")
*/
protected $Records = NULL;
public function setCategoryVariable(CategoryVariable $CategoryVariable)
{
$this->CategoryVariables[] = $CategoryVariable;
}
public function getCategoryVariables()
{
return $this->CategoryVariables;
}
public function setRecord(Record $Record)
{
$this->Records[] = $Record;
}
public function getRecords()
{
return $this->Records;
}
public function __construct()
{
$this->CategoryVariables = new ArrayCollection();
$this->Records = new ArrayCollection();
}
}
If your record doesn't have category then the category object that you retrieve it is null. So before echo its category you must to control if category is a real object or null object.
Like this:
$record_data = $this->getRepository('Entity\RecordData')->find($this->params['id']);
$record = $record_data->getRecord();}
$category = $record->getCategory();
echo ($category) ? $category->getName() : "Record doesn't have category";

Resources