Doctrine create subquery with bound params - doctrine

I am trying to construct a query that will basically pull all entries whose id's have 2 particular entries in another table so I am trying the below:
$query = $this->createQuery('e');
$subquery1 = $query->createSubquery('sea')
->select('sea.entry_id')
->from('Table sea')
->addWhere('sea.form_element_id = ?', $element)
->addWhere('sea.answer = ?', $answer)
->getDQL();
$subquery2 = $query->createSubquery('sea2')
->select('sea2.entry_id')
->from('Table sea2')
->addwhere('sea2.form_element_id = ?', $element2)
->addWhere('sea2.answer = ?', $answer2)
->getDQL();
$query->addWhere('e.id IN ?', $subquery1)
->addWhere('e.id IN ?', $subquery2);
return $query->execute();
However this is gives me an error on bound params.
What is the correct ways of constructing such subqueries?
NOTE that if I dont bind the params in the subqueries it works fine.

$nestedQuery = " id IN (SELECT sea.entry_id from table sea where sea.form_element_id = ? and sea.answer = ?) "
. " and id IN (SELECT sea2.entry_id from table sea2 where sea2.form_element_id = ? and sea2.answer = ?)";
return $this->findBySql($nestedQuery, array($param1, $param2, $param3, $param4));
That obviously returns a doctrine collection but you can do getFirst or loop through the returned objects or even use the Hydrator to get an array!

Related

Doctrine Many-To-Many bulk insert

I need to do a bulk insert of thousands of records (5k up to 20k).
The scenario is User<->n:m<->Group. The list of users is obtained by a complex query with many joins.
I have access to the QueryBuilder that generates the list.
The simpliest approach to add the users to the group is
$users = $this->repository->findRecipientsByCriteria($group->getCriteria());
foreach ($users as $user){
$group->addUser($user);
}
But for the number of users involved i don't think it's a good idea (in term of performances).
I can't even iterate results because of the fetch join relations.
I would like to inject the QueryBuilder Dql (or Sql) to the INSERT statement?
I mean something like:
$qb = $this->repository->getRecipientsByCriteriaQueryBuilder($group->getCriteria());
$qb->select("'".$group->getId()."' AS gruppo_id, U.id AS utente_id");
$d = $qb->getQuery()->getSQL();
$q = $this->entityManager->createNativeQuery('INSERT INTO `msg_gruppo_utente` (`gruppo_id`, `utente_id`) '.$d, new ResultSetMapping());
$q->execute();
But this results in
INSERT INTO `msg_gruppo_utente` (`gruppo_id`, `utente_id`) SELECT '64f105a3-a6ab-460a-8378-84b0c3258601' AS sclr_0, s0_.id AS id_1 FROM security_utente s0_ INNER JOIN security_utente_cliente s1_ ON s0_.id = s1_.utente_id INNER JOIN api_cliente a2_ ON s1_.cliente_id = a2_.id INNER JOIN api_indirizzo_cliente a3_ ON a2_.id = a3_.cliente_id INNER JOIN api_contratto a4_ ON a2_.id = a4_.cliente_id WHERE s1_.verificato = ? AND a3_.city = ?
Where parameters are not set, while i thought thatthe parameters should have been be set in getRecipientsByCriteriaQueryBuilder
Due to doctrine native SQL resctrictions
If you want to execute DELETE, UPDATE or INSERT statements the Native
SQL API cannot be used and will probably throw errors. Use
EntityManager#getConnection() to access the native database connection
and call the executeUpdate() method for these queries.
I've used this solution (executeUpdate is deprecated in favor of executeStatement)
$usersQueryBuilder = $this->repository->getRecipientsByCriteriaQueryBuilder($group->getCriteria());
$usersQueryBuilder->select("'".$group->getId()."' AS gruppo_id, U.id AS utente_id");
$parameters = $usersQueryBuilder->getParameters();
$p = [];
/** #var Parameter $parameter */
foreach ($parameters as $parameter){
$p[] = $parameter->getValue();
}
$conn = $this->entityManager->getConnection();
$conn->executeStatement('INSERT INTO `msg_gruppo_utente` (`gruppo_id`, `utente_id`) '.
$usersQueryBuilder->getQuery()->getSQL(), $p);

Active record of not in

$this->db->query('DELETE FROM default_model WHERE cat_id NOT IN (SELECT id FROM default_category)');
the active record format for this query
$query = $this->db->select('id')
->get('category')->result();
$this->db->where_not_in('cat_id',$query )
->delete('model');
I tried a lot but could not do it. How to pass $query
The query results are returned as standard objects. Therefore you need to fetch the ids from the returned objects in a non associative array before passing that array to the delete query.
Like this:
$result = $this->db->select('id')->get('category')->result();
$ids = [];
foreach($result as $result)
$ids[] = $result->id;
$this->db->where_not_in('cat_id', $ids)->delete('model');

Active records class in CodeIgniter

Basicly i have two tables photos and users. I wanna join tables and Update colums image_max and image_min. I get error unknown colum username. In which way i can join two tabels and get data from both. My sintax is:
$this->db->select('*');
$this->db->from('photos');
$this->db->join('users', 'photos.id = users.id');
$this->db->where('username',$username);
$this->db->update('photos',$data);
And I get error
Unknown column username in where clause
UPDATE `photos` SET `image_max` = '', `image_min` = '' WHERE `username` = 'wwww'
apparently you need a letter on the table should say "users.username", check that.
Greetings.
$this->db->select('*');
$this->db->from('photos');
$this->db->join('users', 'photos.id = users.id');
$this->db->where('users.username',$username);
$this->db->update('photos',$data);
You don't need to use "select and from" before upload fields, just update in this way
$data = array('image_max'=> 4, 'image_min' => 1);
$this->db->join('users', 'photos.id = users.id');
$this->db->where('username',$username);
$this->db->update('photos',$data);

Get values from a doctrine collection with composite key

4 for on on my applications with Doctrine.
In there I'm using the following doctrine command to retrieve person object collection
//query
$people = $q->execute();
This return 20 objects. The primary key of the person object is a composite key with three attributes. Those are
id
department_id
name
I need to get person objects by searching in it as follows.
$id = 10;
$department_id = 1;
$name = "abc";
$people->get($id, $department_id, $name);
But this doesn't work and not give correct results. I tried with this and it gives null results which seems my collections primary key is not set.
$people->getKeyColumn();
I don't want to go through a foreach loop in collection and process it because when I deal with about 500 people, it slow down my application.
Can some one help me with this issue to get values from a doctrine collection.
Can you use something like this?
$people = Doctrine::getTable('Persons')
->createQuery()
->where('id = ? AND department_id = ? AND name = ?', array($id, $department_id, $name))
->execute();
It will get you a DoctrineCollection already filtered by the parameters provided.
'Persons' here is a Doctrine model name, not a table name from mySQL.
You can also use Doctrine's magic finders findBy*():
$people = Doctrine_Core::getTable('Persons')
->findByIdAndDepartmentIdAndName($id, $department_id, $name);

Filtering Results with CodeIgniter

I have two tables books and authors. Using CodeIgniter I would like users to be able to Filter results - for example, show results where author_id = 'x' and book_lang = 'y' and publication_year = '2000'. Filter criteria values come from user via drop-downs.
What's the best way to generate the query using codeigniter helper and binding etc?
For example, the query below will give me everything with author_id= 1. what if filters are a mix, for example; author_id = 1; language = 'all' (don’t put where clause on language) and publication year = 'all' also don’t put where clause.. Do I manually need to check for values and code or is there a codigniter helper method that allows filter to be removed from where clause if dropdown value is 'show all'?
$sql = "select * from AUTHORs a , BOOKS b where
a.AUTH_ID = b.BOOK_AUTH_ID
and b.BOOK_AUTH_ID = ?
and b.BOOK_LANGUAGE = ?
and b.PUB_YEAR = ? ";
$query = $this->db->query($sql, array ($author_id, $book_lang, $pub_year));
You should use Codeigniter's Active Record class to construct your query:
$this->db->select('*');
$this->db->from('AUTHORs a , BOOKS b');
$this->db->where('a.AUTH_ID', 'b.BOOK_AUTH_ID');
if ($author_id != 'all') $this->db->where('b.BOOK_AUTH_ID', $author_id);
if ($book_lang != 'all') $this->db->where('b.BOOK_LANGUAGE', $book_lang);
if ($pub_year != 'all') $this->db->where('b.PUB_YEAR', $pub_year);
$query = $this->db->get();
To read more about Codeigniter's Active Record class, visit the Docs:
http://codeigniter.com/user_guide/database/active_record.html

Resources