Symfony 2 "findBy" a mapped entity parameter into controller - php

I'm new with Symfony2 and i would like to know whether there is a way to use the "findBy" with a param which is present only in a mapped entity.
This is my snippet controller:
$prods = $em->getRepository('EcommerceProductBundle:ProductData')
->findBy(array(
'product_id'=>46
));
It works good but if i try to add another element to the array, which is present in a mapped entity, it get (rightly) this error
Unrecognized field: ProductImage.is_visible
What i would like to do, is just to know wehether i can use the "filterBy" with a mapped element of the entity ProductData.
I'm in wrong but this is my idea:
->findBy(array(
'product_id'=>46,
'ProductImage.is_visible'=>1
));

Not possible as far as i know. Just add this custom method to your repository:
public function findByIdAndVisibleImage($id)
{
return $this->createQueryBuilder('product')
->lefJoin("product.image","i")
->where("product.product_id = :id")
->andWhere("i.is_visible = 1")
->setParameter("id", $id)
->getQuery()
->getSingleResult();
}

You can't do that, you need to write a custom method in the repository with a join clause.
The findBy method just add a where clause on the criteria.

Related

Route binding with composite key

I am trying to bind a model that has composite key. Take a look, at first place I define my route:
Route::get('laptop/{company}/{model}', 'TestController#test');
Now, I define as I want to be resolved:
$router->bind('laptop', function ($company, $model) {
$laptop = ... select laptop where company=$company and ...;
return $laptop;
});
Now, I see how I am injecting the class in order to get the laptop in the controller: function into to test the resolution:
function test(Laptop $laptop){
return 'ok';
}
However, I am receiving the following error:
BindingResolutionException in Container.php line 839:
I assume that the error is caused by $router->bind('laptop' because it should matches a unique placeholder in the url ("company" or "model"). In my case I get lost because I need to matches both at the same time.
Note: I am not using db/eloquent layer. This problem is focused in the way on how to resolve route binding with multiples keys representing an unique object.
I am not sure if is it possible or if am I missing something. Thank you in advance for any suggestion.
Laravel does not support composite key in eloquent query.
You need to use query builder method of laravel to match against both values. ie: DB::select()->where()->where()->get();
Just put select and where conditions in above.
If you bind $router->bind('laptop', ...); then your route parameter should be Route::get('{laptop}', ...);. There is two possibility to query a laptop by model and company as you expected.
The safest way is query laptop on your controller:
Route::get('laptop/{company}/{model}', 'TestController#test');
In you TestController.php
function test(Laptop $laptop, $company, $model){
return $laptop->whereCompany($company)->whereModel($model)->first();
}
Another solution is allow slashes on your route parameter:
Route::get('laptop/{laptop}', 'TestController#test')->where('laptop', , '(.*)?');
and your binding function could be:
$router->bind('laptop', function ($laptop) {
$laptop = explode('/', $laptop);
$company = current($laptop);
$model = end($laptop);
if ((count($laptop) === 2) && ($result = App\Laptop::whereCompany($company)->whereModel($model)->first()) {
return $result;
}
return abort(404);
}

Mapping myself form in Symfony2

I'd like to map an entity of a form by myself. The thing is I'm working with 36 000 cities in a database and Doctrine doesn't return any result when I'm performing a request using findBy. But I set this up by writting my owns methods.
The problem is in a form I need to ask for a city through an entity field (because there are a lot of data, I'm using select2 with remote's data). So far, no problem but when I'm submiting the form, Symfony can't bind the city's id to a database entry because of the none result of the classic method of Doctrine.
So, my question is : How can I tell Symfony to use my repository's method instead of the Doctrine's one to bind my data?
Thank you very much ! And have a good day ;)
The method findBy() request an array parameter sometimes people miss that:
$result = $this->getDoctrine()->getManager()
->getRepository("AcmeDemoBundle")->findBy(array(
"city" => $city)
);
If you want to use repository you just need to map it to your class:
/**
* #ORM\Entity(repositoryClass="Acme/DemoBundle/Repository/CountryRepository")
*/
class Country
{ ... }
Then in
class CountryRepository extends EntityRepository
{
public function getMySpecificCity($city)
{
$qb = $this->createQueryBuilder('c');
$cities = $qb->select(*)
->where("c.city =:city ")->setParameter('city', $city)
->getQuery()
->getResult();
return $cities;
}
...
}
So you can use it as follow:
$result = $this->getDoctrine()->getManager()
->getRepository("AcmeDemoBundle")->getMySpecificCity($city);

symfony2 doctrine findBy id in arrayCollection

Using Symfony2.3.4 and Doctrine.
I have a class Student with a ManyToMany relation with a class Edition.
Now in my StudentController I have this IndexAction($edition_id) to list not all students in the DB but only those related to the given Edition id.
$entities = $em->getRepository('PersonBundle:Student')->findBy(array(
????????
));
I'm thinking of some kind of criteria to use with $edition_id but can't come up with any.
Tips appreciated, thanks.
#dmnptr:
I'm trying that, I'm quite new to this so tell me if I did something wrong.
I put that function you wrote in the controller and in the method IndexAction($edition) I added
$students = this->findAllByEdition($edition);
now the problem is that the parameter $edition is coming from a twig template like this:
<a href="{{ path('student', { 'edition': entity}) }}"</a>
being entity who holds the Edition object.
But when I do it like this entity returns the __toString() method, meaning a string with the name of the edition, not the edition itself which is what the function you gave me uses.
Now, do you happen to know a way to get the object itself from the template, not the __toString() method, thanks...
You should use custom repository method. Pass $edition as a parameter, not just an id. Something like this:
public function findAllByEdition($edition)
{
$em = $this->getEntityManager();
$queryText = "SELECT s FROM PersonBundle:Student s ";
$queryText .= "WHERE :edition MEMBER OF s.editions";
$query = $em->createQuery($queryText);
$query->setParameter('edition', $edition)
return $query->getResult();
}

Delete records in Doctrine

I'm trying to delete a record in Doctrine, but I don't know why it's not deleting.
Here is my Code:
function del_user($id)
{
$single_user = $entityManager->find('Users', $id);
$entityManager->remove($single_user);
$entityManager->flush();
}
Plus: How can I echo query to see what going on here?
This is an old question and doesn't seem to have an answer yet. For reference I am leaving that here for more reference. Also you can check the doctrine documentation
To delete a record, you need to ( assuming you are in your controller ):
// get EntityManager
$em = $this->getDoctrine()->getManager();
// Get a reference to the entity ( will not generate a query )
$user = $em->getReference('ProjectBundle:User', $id);
// OR you can get the entity itself ( will generate a query )
// $user = $em->getRepository('ProjectBundle:User')->find($id);
// Remove it and flush
$em->remove($user);
$em->flush();
Using the first method of getting a reference is usually better if you just want to delete the entity without checking first whether it exists or not, because it will not query the DB and will only create a proxy object that you can use to delete your entity.
If you want to make sure that this ID corresponds to a valid entity first, then the second method is better because it will query the DB for your entity before trying to delete it.
For my understanding if you need to delete a record in doctrine that have a doctrine relationship eg. OneToMany, ManyToMany and association cannot be easy deleted until you set the field that reference to another relation equal to null.
......
you can use this for non relation doctrine
$entityManager=$this->getDoctrine()->getManager();
$single_user=$this->getDoctrine()->getRepository(User::class)->findOneBy(['id'=>$id]);
$entityManager->remove($single_user);
$entityManager->flush();
but for relation doctrine set the field that reference to another relation to null
$entityManager=$this->getDoctrine()->getManager();
$single_user=$this->getDoctrine()->getRepository(User::class)->findOneBy(['id'=>$id]);
{# assume you have field that reference #}
$single_user->setFieldData(null);
$entityManager->remove($single_user);
$entityManager->flush();
do you check your entity as the good comment annotation ?
cascade={"persist", "remove"}, orphanRemoval=true
In a Silex route I do like this, in case it helps someone:
$app->get('/db/order/delete', function (Request $request) use ($app) {
...
$id = $request->query->get('id');
$em = $app['orm.em']; //or wherever your EntityManager is
$order = $em->find("\App\Entity\Orders",$id); //your Entity
if($order){
try{
$em->remove($order);
$em->flush();
}
catch( Exception $e )
{
return new Response( $e->getMessage(), 500 );
}
return new Response( "Success deleting order " . $order->getId(), 200 );
}else{
return new Response("Order Not Found", 500);
}
}
You first need repository.
$entityManager->getRepository('Users')->find($id);
instead of
$single_user = $entityManager->find('Users', $id);
'Users' String is the name of the Users repository in doctrine ( depends if you are using Symfony , Zend . . etc ).
First, You may need to check if 'Users' is your fully qualified class name. If not check, and update it to your class name with the namespace info.
Make sure the object returned by find() is not null or not false and is an instance of your entity class before calling EM's remove().
Regarding your other question, instead of making doctrine return SQL's I just use my database (MySQL) to log all queries (since its just development environment).
try a var_dump() of your $single_user. If it is "null", it doens't exist ?
Also check if "Users" is a valid Entity name (no namespace?), and does the $id reference the PK of the user?
If you want to see the queries that are executed check your mysql/sql/... log or look into Doctrine\DBAL\Logging\EchoSQLLogger

Doctrine2: dynamic entity associations, many targetEntity mapped by one field

I have a Entity called Event which has
a field "associatedEntity" containing the class name of another Entity in the Bundle
a field "targetId" of that specific "associatedEntity" Entity
I would now like to access this target entity inside my Event-Entity somehow but im now sure how to do it. I'd like to access the different target Entities in a twig template using something like
{% if event.getClassName() == "User" %}
{{ if event.getUser().getName() }}
{% endif %}
Edit: Just to be clear, the only thing im interested so far is how to create the relation properly. Outside a ORM World you would probably use a join statement for this. It is like i have many target Entities mapped by one field.
So far im using the entity repository and DI to load the associated Entities, but i find that ugly knowing there is a JOIN Statement which i could use:
public function getUpcomingEvents(){
$query = $this->createQueryBuilder('E')
->where('E.resolved = false')
->orderBy('E.notify_date', 'ASC')
->setMaxResults( $limit );
$res = $query->getQuery()->getResult();
$res = $this->attachAssociatedObjects($res);
return $res;
}
public function attachAssociatedObjects($res){
foreach ($res as $key => $entity) {
$assocObject = $this->getEntityManager()->getReference('My\Bundle\Entity\\'.$entity->getClassName(), $entity->getTargetId());
$res[$key]->setAssociatedObject($assocObject);
}
return $res;
}
Twig attribute function is what you need.

Categories