Getting multiple rows using ParamConverter - symfony

Hi Im trying to use ParamConverter to get multiple rows from DB but profiler show query with limi 1. Is it possible to get it like that
/**
* #Route("/localization/{code}", name="pkt-index")
* #ParamConverter("localizations", class="PriceBundle:Localization")
*/
after entering localization/0003 I should get more than 100 rows.
EDIT:
I have used repository_method option
and
/*
* #Route("/localization/{id}", name="pkt-index")
* #ParamConverter("localizations", class="PriceBundle:Localization", options={
* "repository_method": "getByLocalizationCode"
* })
*/
but funny thing is that when I change {id} in route it does not work it throws and exception
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
even if variable exists in entity class, if variable dont exist it throws
Unable to guess how to get a Doctrine instance from the request information.
EXPLANATION
when I change {id} in route it does not work it throws and exception
SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
Here I think symfony treads id like primary key and as parameter to repository method it pass string when I changed this id to something else it pass array
Example
/**
* #Route("/localization/{id}", name="pkt-index")
*/
pass string to method
/**
* #Route("/localization/{code}/{name}", name="pkt-index")
*/
pass array to method
array(
'code' => 003
'name' => localization_name
)
and last
/**
* #Route("/localization/{id}/{name}", name="pkt-index")
*/
will pass string id omit the name
Hope this sounds reasonable.

forgottenbas's answer isn't completely right. #ParamConverter will first try to find one entity by id ...
... then try to match the route variables against db columns to find an entity ...
but essentially it will only convert one entity at a time.
If you would still like to use a paramconverter you would need to write a custom one.
or just use a one-liner inside your controller action:
/**
* #Route("/localization/{code}", name="pkt-index")
*/
public function yourAction($code)
{
$localizations = $this->getDoctrine()->getRepository("YourBundle:Localization")->findBy(array("code" => $code));
// ...

ParamConverter currently can only extract id from request and find one entity from db. Look at
DoctrineParamConverter code. But you can specify your own param converter with some extra logic.

Related

Route with a lot of optional parameters in Symfony

I got a lot of products, and it can be filter with a lot of different parameters.
So user input search parameter in a form, and then the list is filter by those parameters.
I have try to create a route like this :
/**
* Display a list of product
* #Route("/product/list/{name}/{price_min}/{price_max}/{publish_date}/{supplier_code}", name="product_list")
*/
public function listProduct(){
// ... Check parameters format and then escape special caracters
// ... Display product logic
return $this->render('Product/product_list.html.twig', $array_params_view);
}
I know you can provide optional parameter, but this solution looks really bad to me...
I think there might be another solution.
I have think to use the Request instead of a lot of parameter, but if I do so, I loose the fonctionality of nice and easily readable URL, and maybe it'll be more difficult to manage routing.
I don't know what is the best solution for search functionnality.
If you use route for search into your list, I think you need to read this : link
Query String is a better way for search.
// the query string is '?foo=bar'
$request->query->get('foo');
// returns 'bar'
/**
* Display a list of product
*
* #Route("/list/", name="product_list")
*
* #param Request $request
*
*/
public function listProduct(Request $request)
{
$name = $request->query->get('name');
$price_min = $request->query->get('price_min');
$price_max = $request->query->get('price_max');
$publish_date = $request->query->get('publish_date');
$supplier_code = $request->query->get('supplier_code');
$list_products = $this->getListProducts($name,$price_min,$price_max,$publish_date,$supplier_code);
//Next code
......
}
You would only have to control within the getListProducts function
or whatever you call it, that the arguments can arrive as null

Symfony 2 - could not able to insert json_array type variable

json_array type variable is not able to include to the database. The populated exception is as follow
(Symfony\Component\Debug\Exception\ContextErrorException(code: 0): Warning: implode(): Invalid arguments passed at /var/www/vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/SimpleArrayType.php:51)"}
My entity class has this part for json_array type paramter.
/**
*
* #ORM\Column(name="street", type="json_array")
*/
private $street;
also I include to the db using entity manager.
$entityName->setStreet(
array(
'street_1' => $queueItem->street_1,
'street_2' => $queueItem->street_2));
if($this->em->getUnitOfWork()->getEntityState($entityName)) {
$this->em->flush();
}
I think you should use type="text" or a own entity for multiple streets
http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#text
Because:
type="json_array" is deprecated use type="json" http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html#json-array
this type want a string that could be encoded, not an array

Symfony2 data fixtures

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);

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/Doctrine 2 - Use config parameter in Entity

I have a tree of Employee objects (they are in a tree-like hierarchy, with everyone having one leader, and all leaders having more employees). All the Employees have a integer parameter called units.
/**
* #ORM\Entity
* #ORM\Table(name="employees")
*/
class Employee
{
/**
* #ORM\Id
* #ORM\Column(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="Employee", mappedBy="leader")
*/
protected $employees;
/**
* #ORM\ManyToOne(targetEntity("Employee", inversedBy="employees")
*/
protected $leader;
}
I need to get all the employees, who have at most N units, where N is defined in config.yml. At first, I was trying to push $configContainer into $GLOBALS, and use it in ArrayCollection::filter()'s Closure. Now I found a method, so I can use variables in the Closure:
public function getBestEmployees(&$configContainer)
{
return $this->getAllEmployees()->filter(
function bestEmployees($employee) use ($configContainer)
{
return ($employee->getUnits() >= $configContainer->getParameter('best_unit_count'));
}
);
}
Now I wonder if there is any other way to access the configuration parameters from an Entity, or do I really have to pass the whole configContainer as a reference? Or am I doing it totally wrong?
You shouldn't be accessing the service container at all inside entities. The value itself should be passed instead
public function getBestEmployees($bestUnitCount)
{
return $this->getAllEmployees()->filter(function ($employee) use ($bestUnitCount) {
return $employee->getUnits()->count() >= $bestUnitCount;
});
}
Of course, we haven't actually solved the problem yet: the parameter still needs to be fetched from the container somewhere. If this method gets invoked mostly in controller actions, I wouldn't bother doing any extra work to make things cleaner and would pass the container parameter straight in the controller action.
However, should there be a need to get the best employees in a Twig template, for example, it would be nice if it wouldn't be necessary to pass the parameter. One possibility would be using a setter method and passing the parameter down beforehand to each and every entity that gets retrieved from the database. You could do this either in repositories or entitiy managers. The most advanced solution would be to listen to the postLoad event and pass the parameter in an event listener.

Resources