Symfony2 data fixtures - symfony

very new to Symfony2 so trying to working things out. Got a couple of tables. First one is called availability_alert. This table has the usual stuff like an id, but the important thing to note is that it does not have a link to anything.
The second table is call booking_class. This one has a couple of fields, one of which is availability_alert_id. This value is linked to the id field in my first table.
I had a working application, but decided to move it to Symfony. I used my existing database to produce some entity classes. In my BookingClass Entity, I have a link to the AvailabilityAlert id.
/**
* #var \AlertBundle\Entity\AvailabilityAlert
*
* #ORM\ManyToOne(targetEntity="\AlertBundle\Entity\AvailabilityAlert")
* #ORM\JoinColumns({
* #ORM\JoinColumn(name="availability_alert_id", referencedColumnName="id")
* })
*/
private $availabilityAlert;
Now for some reason, it set the setter to this field like so
public function setAvailabilityAlert(\AlertBundle\Entity\AvailabilityAlert $availabilityAlert = null)
{
$this->availabilityAlert = $availabilityAlert;
return $this;
}
So I first want to make sure this is correct?
Next, I am doing some Data Fixtures, so I do
$alert = new AvailabilityAlert();
And then set a few other bits and pieces. I then do one for the other table
$bookingClass = new BookingClass();
However, when I try to set the id
$bookingClass->setAvailabilityAlert($this.$alert->getId());
It tells me it is expecting an AvailabilityAlert but instead it is getting a String.
So I was just wondering what I am doing wrong here?
Thanks

The problem is that you're trying to add a string instead of an AvailabilityAlert object to your BookingClass object.
Instead of this:
$bookingClass->setAvailabilityAlert($this.$alert->getId());
Simply try this:
$bookingClass->setAvailabilityAlert($alert);

Related

symfony annotations access to another field

I wanna have a start date and end date field in the database, but start date cant be greater than end date (logically) but is there any way to use Entity to make a comparison (with Assert/Constraints) or I have to do it elsewhere(and where)
in this example I use
/**
* #ORM\Column(type="date")
* #Assert\GreaterThanOrEqual("today")
*/
private $start_date;
/**
* #ORM\Column(type="date")
*/
private $end_date;
is it possible at $end date to have #Assert\GreaterThan($start_date) somehow
can I access that or I need to have some custom function for that kind of check, and what is best practice to create that kind of check in Symfony
You would need to implement a class constraint validator for your entity. In that validator your can get the whole entity as an argument and then you can compare the dates like this:
if ($value->getStartDate() > $value->getEndDate()) {
$this->context->buildViolation($constraint->message)
->atPath('startDate')
->addViolation();
}
Look at https://symfony.com/doc/current/validation/custom_constraint.html#class-constraint-validator

Symfony 3 - Update Many-To-Many

I have been looking around for a clean solution on how to update (keep in sync) a many to many relationship?
I have the following scenario:
A Sprint Entity owns the Many To Many relationship towards the Ticket entity.
When editing a Ticket (or Sprint, but I am not there yet), I want to be able to select (checkboxes) the Sprints that this ticket belongs to.
Upon persistance (save), I want to update my join table tickets_sprint (which is just a join table on ticket_id, sprint_id).
Adding Sprints to the Ticket seems easy enough, but removing Sprints from the Ticket is not reflected at all.
Code
Ticket Entity contains this method for adding a Ticket to a Sprint:
public function setSprints($sprints) {
/**
* #var $sprint \AppBundle\Entity\Sprint
*/
foreach ($sprints as $sprint) {
$this->sprints[] = $sprint;
$sprint->addTicket($this);
}
}
I have read here that the only way to go would be to remove all relations and re-save them upon persistance.
Coming from the Laravel world, this hardly feels like a good idea :)
This is how it is done in Laravel:
/**
* #param \App\User $user
* #param \App\Http\Requests\StoreUserRequest $request
* #return \Illuminate\Http\RedirectResponse
* Update the specified resource in storage.
*/
public function update(User $user, StoreUserRequest $request)
{
$user->fill($request->input());
$user->employee_code = strtolower($user->employee_code);
$user->roles()->sync($request->role ? : []);
$user->save();
\Session::flash('flash_message_success', 'The user was successfully updated.');
return redirect()->route('frontend::users.show', [$user]);
}
All suggestions are welcome!
The EntityType that you may use to create a multiple selectbox doesn't have a by_reference option like CollectionType.
If your Ticket Entity use the "inversedBy" side, you don't need to add the reference in the other object. So you can symply do this :
public function setSprints($sprints) {
$this->sprints = $sprints;
}
Maybe this will be enough to add and remove your elements automatically (Sorry didn't try).
Otherwise you have to do it manually and you can create a new method to remove elements returns by the difference between your new ArrayCollection and the old one.

Symfony - access object of non related tables

How can i access the object of second table when joined (non-related tables)?
I have two table which are not related and I want to get the object of the second class (from below dump output)
My repository with dump
For example:
my controller:
$ProductSet_Repo = $em->getRepository('MyTestBundle:Product\ProductSet')->FindProductSet($productid);
Normally when the tables are related I can simple do
$productSet = $ProductSet_Repo->getproductid()->getProduct(); to get the object of Product class From ProductSet Class.
See My Dump
However since the tables are not in relationship and when i dump the data i get the objects of two classes is there a way I can access the Object My\TestBundle:Products\Entity\Product\ProductSet and \My\TestBundle\Entity\Product\Product?
Note: i don't want to do establish relationship between the two tables as I am working on already existing table for which i don't want to make any changes
Also I know I can select the fields which i want to retrieve. (I dont want to do that)
You write:
i don't want to do establish relationship between the two tables as I am working on already existing table for which i don't want to make any changes.
But with doctrine you are very well able to make a association between two entities without changing the tables. As far as I can see from your query you have a product_id column in your product_set table. That is all you need to make an association between Product and ProductSet.
In your ProductSet class you can do:
<?php
namespace My\TestBundle\Entity\Product;
class ProductSet
{
//... other properties
/**
* #var Product
* #ORM\Id
* #ORM\ManyToOne(targetEntity="My\TestBundle\Entity\Product\Product")
* #ORM\JoinColumn(name="product_id", referencedColumnName="id")
*/
protected $product;
/**
* Set the product.
*
* #param Product $product
* #return ProductSet
*/
public function setProduct(Product $product)
{
$this->product = $product;
return $this;
}
/**
* Get the product.
*
* #return Product
*/
public function getProduct()
{
return $this->product;
}
//... other setters and getters
}
Now you can do:
$repository = $em->getRepository('MyTestBundle:Product\ProductSet')
$productSets = $repository->findBy(array('product' => $productid));
foreach($productSets as $productSet){
$productSet->getProduct()->getId() === $productId; // true
}
You can still join them (despite of strange naming convention you have id of corresponding object in the other entity) using query builder or native sql, but it's a really bad way.
it was developed by previous webdeveloper and i dont want to spend more time as i work as free lancer
That's not an excuse. You should create a relation and migration for these data. Getting money for a poorly designed and developed app is not cool.
Probably additional work when working with that poor design will take your more time than doing it in a proper way.

Symfony 2 JMS Serializer Bundle - Serialize only IDs for User friends

I have a question about the JMS Serializer Bundle in Symfony 2.
I want to serialize a User entity, which has a many-to-many relation with itself called "friends".
While I want to expose a bunch of property from the original User, I only want the ids from the friend objects, which are also User entities.
How can I solve this problem?
Thanks in advance.
Okay, while I wrote the question, I also solved it.
The solution is to use the #VirtualProperty annotation.
Example:
use JMS\Serializer\Annotation\VirtualProperty;
use JMS\Serializer\Annotation\SerializedName;
// ...
/**
* #VirtualProperty
* #SerializedName("friends")
*/
public function getFriendIdsOnly()
{
$friendIds = array();
foreach ($this->friends as $friendEntity) {
$friendIds[] = $friendEntity->getId();
}
return $friendIds;
}
With this, the "friends" key will contain an array of User ids.
Or maybe you could use the #Groups annotation.
class User
{
/*
* #JMS\Groups({"user_id", "friend_id"})
*/
$id;
/*
* #JMS\Groups({"user_friends"})
*/
$friends;
}
And when you want to serialize you set up the ["user_friends", "friend_id"] groups. The difference with your solution is the format of the return (if we talk about json)
// You
{"id":, "friends":["id", "id"]}
// Me
{"id":, "friends":[{"id":}, {"id":}]}
The solution with the groups allow a more manageable return. If one day you want to send back the username for instance, you just need to change the groups annotations.

Symfony Entity check for ArrayCollection if already exists, then do update

For a Collection, I want to check if a new added Part already exists in the database. And if so, that it'll be overwritten with the new value.
/**
* Add Part
*/
public function addPart(\MyBundle\Entity\FooTypePart $Part)
{
$part->setProduct($this);
$this->part[] = $part;
return $this;
}
/**
*/
public function removePart(\MyBundle\Entity\FooTypePart $part)
{
$this->part->removeElement($part);
}
/**
* Get Part
* #return \Doctrine\Common\Collections\Collection
*/
public function getPart()
{
return $this->part;
}
/**
* Set Part
*/
public function setPart($part)
{
$this->part = $part;
return $this;
}
The Part Entity has: ID, Category_id (FK), Product_id (FK), Part (Collection)
It is possible at the moment to add a new Part with the same name, also when there is already a Part with the same Product_id AND Category_id.
Making Part unique isn't the fix, because Part can be used for many Products/Categories.
The following example already exists in the database, with a different 'Part'. So it should do a update command.
<?php
$part = new FooTypePart();
$part->setCategory($specification);
$part->setProduct($product);
$part->setPart('DifferentNamingThenCurrentOne');
$xx->addSpecificationValue($part);
How? :-)
Just use the UniqueEntity validator to find an already existant Item in the collection.
You can specify uniqueness using multiple properties or a repository method. This way you can search for items only having a unique combination of name, product-id and category-id.
Create a validation group i.e. "unique" and find the non-unique/existant entity in your collection by looking for invalid entities.
... then update the existing entity with your new value. You will probably need some extra logic because there might be multiple fields with the same name added to your form collection.

Resources