FOSRestbundle: Serialize public method as field - rest

I have an entity with a standard datetimetz field, with standard getter and setter:
/**
* #var \DateTime
*
* #ORM\Column(name="date", type="datetimetz")
*/
private $date;
/**
* Get date
*
* #return \DateTime
*/
public function getDate() {
return $this->date;
}
/**
* Set date
*
* #param \DateTime $date
* #return ConsultationForm
*/
public function setDate($date) {
$this->date = $date;
return $this;
}
Serializing this works just fine, and the resulting JSON has a field with a string representing the date:
date: "2014-07-05T09:53:45+0200"
However, I would like to add a second method to my entity, which returns a Unix timestamp corresponding to my date object:
/**
* Get date as millis
*
* #return int
*/
public function getDateAsMillis() {
return $this->date->getTimestamp();
}
I would like the output of this method to also be encoded as a JSON field in the resulting object:
dateAsMillis: 3423435252345232
How can I instruct the FOSRestbundle or the serialiser to do this automatically?

You can use the VirtualPropery annotation (http://jmsyst.com/libs/serializer/master/reference/annotations#virtualproperty)
/**
* #JMS\VirtualProperty
* #JMS\SerializedName("dateAsMillis")
*/
public function getDateAsMillis() {
return $this->date->getTimestamp();
}

Related

Problem creating an instance of ObjectStorage

In my domain model there is a property month which is an ObjectStorage for bill elements. Here is how the domain model looks:
/**
* establishment
*
* #var ObjectStorage<Bill>
* #TYPO3\CMS\Extbase\Annotation\ORM\Cascade("remove")
*/
protected ObjectStorage $month;
public function __construct()
{
$this->setMonth(new ObjectStorage());
}
Here is the setter:
/**
* month setter
*
* #param ObjectStorage<Bill> $month
* #return void
*/
public function setMonth(ObjectStorage $month) : void
{
$this->month = $month;
}
Sadly phpstan shows the following error:
Parameter #1 $establishment of method VIC\Ext\Domain\Model\StorageRoom::setMonth() expects iterable&TYPO3\CMS\Extbase\Persistence\ObjectStorage,
TYPO3\CMS\Extbase\Persistence\ObjectStorage given.
Any Idea what is wrong?
How to build the construct for phpstan:
/**
* establishment
*
* #var ObjectStorage<Bill>
* #TYPO3\CMS\Extbase\Annotation\ORM\Cascade("remove")
*/
protected $month;
public function __construct()
{
/** #var ObjectStorage<Bill> $objectStorageBill */
$objectStorageBill = new ObjectStorage();
$this->setMonth($objectStorageBill);
}

Get the id, not the object in a ManyToOne relationship to send it from an API Rest

I've got an entity I send in a datatable (webix) thanks to an API rest. In this entity I have several ManyToOne relationeships which I don't know how to display or edit.
In my datatable, when I try to display the field which is in a relathinship I've got this instead of the id
[object Object]
When I try to edit this field by adding the id I've got this error message
Type error: Argument 1 passed to ErpBundle\Entity\Trial::setGSponsor() must be an instance of ErpBundle\Entity\Sponsor, string given
I understand what I get in my datatable is an object but I don't know how to get the Id of the name instead (and being able to chose it from the datatable).
Do I have to edit the getter? The repository?
I've tried to edit my getter like that but of course it's not working:
/**
* Get gSponsor
*
* #return \ErpBundle\Entity\Sponsor
*/
public function getGSponsor()
{
return $this->gSponsor->getId();
}
Below a part of my code:
In the controller, I'm just rendering the template for the view. Webix just take the url as an argument to get the data (url: "rest->{{ path('erp_trialapi_cgetload') }}") The datatable is displayed automatically from what I send in my ApiController
Part of my entity
class Trial
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\ManyToOne(targetEntity="ErpBundle\Entity\Sponsor")
*/
private $gSponsor;
/**
* Get id
*
* #return int
*/
public function getId()
{
return $this->id;
}
/**
* Set gSponsor
*
* #param \ErpBundle\Entity\Sponsor $gSponsor
*
* #return Trial
*/
public function setGSponsor(\ErpBundle\Entity\Sponsor $gSponsor = null)
{
$this->gSponsor->get = $gSponsor;
return $this;
}
/**
* Get gSponsor
*
* #return \ErpBundle\Entity\Sponsor
*/
public function getGSponsor()
{
return $this->gSponsor;
}
My API
class TrialApiController extends FOSRestController
{
/**
* #Rest\Get("/api_t/get")
*/
public function cgetLoadAction()
{
$em = $this->getDoctrine()->getManager();
$repo = $em->getRepository('ErpBundle:Trial');
$trials = $repo->findAll();
return $trials;
}
I'd appreciate any kind of help.
Thank you very much!

Symfony 2 Doctrine ODM returning errors on existing fields

I have a simple symfony 2 setup with Doctrine ORM and a db with some underscore seperated field names (for instance "error_page"). Querying this never gives a result (getTitle does give a result, getErrorPage is always empty) and symfony gives me an error:
Method "error_page" for object "My\CmsBundle\Document\Website" does not exist in MyCmsBundle:Default:dashboard.html.twig at line 5
I can't figure out why... My Document looks like this:
<?php
// src/My/CmsBundle/Document/Website.php
namespace My\CmsBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
/**
* #MongoDB\Document(
* collection="websites"
* )
*/
class Website
{
/**
* #MongoDB\Id
*/
protected $id;
/**
* #MongoDB\String
*/
protected $slug;
/**
* #MongoDB\Field(type="string", name="error_page")
*/
protected $error_page = "";
/**
* #MongoDB\String
*/
protected $title;
/**
* #MongoDB\String(name="seo_title")
*/
protected $seo_title;
/**
* #MongoDB\String
*/
protected $seo_description;
/**
* #MongoDB\Collection
*/
protected $url = array();
/**
* Get id
*
* #return id $id
*/
public function getId()
{
return $this->id;
}
/**
* Set slug
*
* #param string $slug
* #return self
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get slug
*
* #return string $slug
*/
public function getSlug()
{
return $this->slug;
}
/**
* Set title
*
* #param string $title
* #return self
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* #return string $title
*/
public function getTitle()
{
return $this->title;
}
/**
* Set errorPage
*
* #param string $errorPage
* #return self
*/
public function setErrorPage($errorPage)
{
$this->error_page = $errorPage;
return $this;
}
/**
* Get errorPage
*
* #return string $errorPage
*/
public function getErrorPage()
{
return $this->error_page;
}
/**
* Set url
*
* #param collection $url
* #return self
*/
public function setUrl($url)
{
$this->url = $url;
return $this;
}
/**
* Get url
*
* #return collection $url
*/
public function getUrl()
{
return $this->url;
}
/**
* Set seoTitle
*
* #param string $seoTitle
* #return self
*/
public function setSeoTitle($seoTitle)
{
$this->seo_title = $seoTitle;
return $this;
}
/**
* Get seoTitle
*
* #return string $seoTitle
*/
public function getSeoTitle()
{
return $this->seo_title;
}
/**
* Set seoDescription
*
* #param string $seoDescription
* #return self
*/
public function setSeoDescription($seoDescription)
{
$this->seo_description = $seoDescription;
return $this;
}
/**
* Get seoDescription
*
* #return string $seoDescription
*/
public function getSeoDescription()
{
return $this->seo_description;
}
}
Document creation via this document works fine by the way. The field name is also set to error_page as expected... I'm at a loss here :S
Actually, Doctrine+Symfony2 assume camel case variable naming. Twig using the getter method names should be obvious, how should it access protected/private variables? It needs a name for something public : the getter. You're probably wondering why "get" is ignored; it is a simplification for designers as they normally shouldnt know about what "getters" are and the difference between methods and variables.
so in your twig file ,change :
{{document.error_page}}
to
{{document.errorPage}}
this would helpful.

Create and save a value object in CommandController

im trying to create and save a value object in my ImportCommandController.php, but only the entity will be saved.
Let me show some code:
// Create Entity "Fewo"
$fewo = new Fewo();
$fewo->setTitle('MyFewo');
...
// Create Value Object "Period"
$period = new Period();
$period->setTitle('MyTestTitle');
...
$fewo->addPeriod($period);
$this->fewoRepository->add($fewo);
$this->persistenceManager->persistAll();
Now the Fewo is in the database, but the period-table is still empty. I can't find my mistake...
UPDATE:
This is the Period Model:
<?php
namespace TYPO3\Fewo\Domain\Model;
class Period extends \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject {
/**
* Name der Saison
*
* #var \string
*/
protected $name;
/**
* Von
*
* #var \DateTime
*/
protected $begin;
/**
* Bis
*
* #var \DateTime
*/
protected $end;
/**
* rentalcharges
*
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\Fewo\Domain\Model\Rentalcharge>
*/
protected $rentalcharges;
/**
* __construct
*
* #return Period
*/
public function __construct() {
//Do not remove the next line: It would break the functionality
$this->initStorageObjects();
}
/**
* Initializes all ObjectStorage properties.
*
* #return void
*/
protected function initStorageObjects() {
/**
* Do not modify this method!
* It will be rewritten on each save in the extension builder
* You may modify the constructor of this class instead
*/
$this->rentalcharges = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
/**
* Returns the name
*
* #return \string $name
*/
public function getName() {
return $this->name;
}
/**
* Sets the name
*
* #param \string $name
* #return void
*/
public function setName($name) {
$this->name = $name;
}
/**
* Returns the begin
*
* #return \DateTime $begin
*/
public function getBegin() {
return $this->begin;
}
/**
* Sets the begin
*
* #param \DateTime $begin
* #return void
*/
public function setBegin($begin) {
$this->begin = $begin;
}
/**
* Returns the end
*
* #return \DateTime $end
*/
public function getEnd() {
return $this->end;
}
/**
* Sets the end
*
* #param \DateTime $end
* #return void
*/
public function setEnd($end) {
$this->end = $end;
}
/**
* Adds a Rentalcharge
*
* #param \TYPO3\Fewo\Domain\Model\Rentalcharge $rentalcharge
* #return void
*/
public function addRentalcharge(\TYPO3\Fewo\Domain\Model\Rentalcharge $rentalcharge) {
$this->rentalcharges->attach($rentalcharge);
}
/**
* Removes a Rentalcharge
*
* #param \TYPO3\Fewo\Domain\Model\Rentalcharge $rentalchargeToRemove The Rentalcharge to be removed
* #return void
*/
public function removeRentalcharge(\TYPO3\Fewo\Domain\Model\Rentalcharge $rentalchargeToRemove) {
$this->rentalcharges->detach($rentalchargeToRemove);
}
/**
* Returns the rentalcharges
*
* #return \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\Fewo\Domain\Model\Rentalcharge> $rentalcharges
*/
public function getRentalcharges() {
return $this->rentalcharges;
}
/**
* Sets the rentalcharges
*
* #param \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\Fewo\Domain\Model\Rentalcharge> $rentalcharges
* #return void
*/
public function setRentalcharges(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $rentalcharges) {
$this->rentalcharges = $rentalcharges;
}
}
UPDATE2:
Tried:
class Period extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity {...}
and:
$period = $this->objectManager->get('TYPO3\Fewo\Domain\Model\Period');
with no effect :(
Is Period in FeWo of the right type?
It have to be something like this:
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\Fewo\Domain\Model\Fewo>

Editing Slug using Gedmo TreeSlugHandler

I have an entity that is hierarchical using the Gedmo Tree Doctrine extension in Symfony 2. The code for the Category entity is:
<?php
namespace MD\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use MD\Entity\Extension\Treeable;
/**
* Category
*
* #ORM\Entity(repositoryClass="MD\Entity\Repository\CategoryRepository")
*
* #Gedmo\Tree(type="nested")
*/
class Category
{
/**
* Entity Extensions
*/
use Treeable;
/**
* The ID of the category
*
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* The title of the category
*
* #var string
*
* #ORM\Column(type="string", length=255)
*
* #Assert\NotBlank(message="category.title.not_blank")
* #Assert\Length(
* max=255,
* maxMessage="category.title.length.max"
* )
*/
protected $title;
/**
* The description of the category
*
* #var string
*
* #ORM\Column(type="text")
*
* #Assert\NotBlank(message="category.description.not_blank")
*/
protected $description;
/**
* The parent of the category
*
* #var Category
*
* #ORM\ManyToOne(targetEntity="Category", inversedBy="children")
* #ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
*
* #Gedmo\TreeParent
*/
protected $parent;
/**
* The children of the category
*
* #var ArrayCollection
*
* #ORM\OneToMany(targetEntity="Category", mappedBy="parent", cascade={"persist"})
* #ORM\OrderBy({"left" = "ASC"})
*/
protected $children;
/**
* The slug of the category
*
* #var string
*
* #ORM\Column(type="string", length=255, unique=true)
*
* #Gedmo\Slug(handlers={
* #Gedmo\SlugHandler(class="Gedmo\Sluggable\Handler\TreeSlugHandler", options={
* #Gedmo\SlugHandlerOption(name="parentRelationField", value="parent"),
* #Gedmo\SlugHandlerOption(name="separator", value="/")
* })
* }, fields={"title"})
*/
protected $slug;
/**
* Constructor
*/
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get the ID of the category
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set the title of the category
*
* #param string $title
*
* #return $this
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get the title of the category
*
* #return string
*/
public function getTitle()
{
return $this->title;
}
/**
* Set the description of the category
*
* #param string $description
*
* #return $this
*/
public function setDescription($description)
{
$this->description = $description;
return $this;
}
/**
* Get the description of the category
*
* #return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set the parent of the category
*
* #param Category $parent
*
* #return $this
*/
public function setParent(Category $parent = null)
{
$this->parent = $parent;
if (null !== $parent) {
$parent->addChild($this);
}
return $this;
}
/**
* Get the parent of the category
*
* #return Category
*/
public function getParent()
{
return $this->parent;
}
/**
* Add a child to the category
*
* #param Category $child
*
* #return $this
*/
public function addChild(Category $child = null)
{
if (!$this->children->contains($child)) {
$this->children->add($child);
$child->setParent($this);
}
return $this;
}
/**
* Get the children of the category
*
* #return ArrayCollection
*/
public function getChildren()
{
return $this->children;
}
/**
* Set the slug of the category
*
* #param string $slug
*
* #return $this
*/
public function setSlug($slug)
{
$this->slug = $slug;
return $this;
}
/**
* Get the slug of the category
*
* #return string
*/
public function getSlug()
{
return $this->slug;
}
/** Magic Methods */
/**
* Return a string representation of the category
*
* #return string
*/
public function __toString()
{
return $this->getTitle();
}
}
Given a category with a title of Bands and a sub-category with a title of Rock, the latter category, on creation, has a slug of bands/rock. This works as expected.
When I add the slug field to a form, however, when I edit the entity, I initially get bands/rock added to the form field. If I change this to bands/rock-and-roll and submit the form, the slug gets updated to bands/bands-rock-and-roll and not bands/rock-and-roll as I'd expect.
If I edit the category and set the slug field to rock-and-roll, then submit the form, the slug gets updated to bands/rock-and-roll. I'd expect the slug to be rock-and-roll after update.
What do I need to do to fix this behaviour? I essentially want the slug to be auto-generated with the handler if it's not provided, but to be set to exactly what I provide if I do provide it.
Thanks
looking at the docs of the Gedmo Tree Doctrine extension and it's relative code, it's not a wrong behaviour because the slug is composed accordingly with the "TreeSlugHandler" method = parentFieldName/field-You-Have-Inserted (that happens every time you edit the slug).
If you need at the same moment of a slug for a specific category and of another that follows the category tree you can add another property (ex: cat_slug) with the simple annotation: #Gedmo\Slug(fields={"fieldYouWantToSlug"}).
Remember that every time (using the "TreeSlugHandler" method) you edit the slug (changing the precedent), every subcategory will be updated with the new slug.
I hope I was helpful