SQL request with an array of arguments - php

I have a problem with a SQL(dql) request,
I have a table with Books(Media), a table with categories, and a table who associate the two: CategoryAffiliation (a book can have multiple categories)
In the Client side, i can choose to search for books by checking multiple categories. Then the client send a array of categories to the server and he must return the books who have at least one of those categories.
$books = [];
if (isset($data['categories'])) {
foreach ($data['categories'] as $key => $value){
$query = $em->createQuery("SELECT m
FROM AppBundle:Media m, AppBundle:Category c, AppBundle:CategoryAffiliation mc
WHERE m.idMedia = mc.idMedia
AND mc.idCategory = :key
GROUP by m.idMedia"
)->setParameter('key',$key);
$result = $query->getResult();
foreach ($result as $book) {
array_push($books, $book);
}
}
}
This is my solution for now but this is not great, i can't ORDER BY the result..
I receive an array of duplicates books, and then in the client side I merge them to delete the duplicates.
I am searching a way to have a single request to fetch all the data at once
Thanks

I don't have access to my stuff to test it but this could do it. I'm just not sure how setParameter will handle the fact that I put ' inside the string. I think that you will need to get the raw information. I can't remember how symfony and doctrine manage that, it's been too long ;)
If you can't find an other way, you could build it in the string directly... which I don't really recommend.
$query = $em->createQuery("SELECT m
FROM AppBundle:Media m, AppBundle:Category c, AppBundle:CategoryAffiliation mc
WHERE m.idMedia = mc.idMedia
AND mc.idCategory IN (:key)
GROUP by m.idMedia"
)->setParameter('key',implode("','",array_keys($data['categories'])));

Related

how to get users per category and sub categories in moodle

I want to get the users per category. I'm using moodle 3.8 version. is there any method for get the users by category.
If you're looking for Moodle functions to do this, then you could probably call:
$cat = core_course_category::get($categoryid);
$courseids = $cat->get_courses(['recursive', 'idonly']);
$userids = [];
foreach ($courseids as $courseid) {
$context = context_course::instance($courseid);
$courseusers = get_enrolled_users($context, '', 0, 'u.id');
$userids = array_merge($userids, array_keys($courseusers));
}
This is, however, horribly inefficient - you'd be best off writing a custom SQL query that, given the list of course ids, will generate a list of enrolled users for all of those courses (take a look inside the code of get_enrolled_users() to see how to build such an SQL query).

Is it okay to perform many queries with mysql or should I look to optimize?

I'm relatively new to programming and have been working in a project group to create our first proper website. We have products and a page where we want to display multiple of those products depending on which category is selected.
$productlist = new ProductList($DB_con, htmlspecialchars($_POST['categoryID']));
$productids = $productlist->getids();
$product = new Product($DB_con);
foreach ($productids as $id) {
$product->read($id);
echo $product->productname
}
Now this is just a basic example of what I'm talking about but essentially the foreach loop would iterate over read($id) numerous times meaning it will essentially perform a query for each product. Now my question is if this is really the acceptable way to go about it or whether I should look to perform one query and somehow grab the data out of that query instead(or any other alternative).
This could be a job for a SQL WHERE IN. If you have an array of Ids you can simply run:
SELECT * FROM products WHERE id IN (1, 2, 3, 4, 5, n...)
You can generate the numbers with:
$ids = implode(", ", $productids);
$sql = "SELECT * FROM products WHERE id IN ({$ids})";

Array to string conversion SYmfony Sql

I have an sql request:
$listUsers=$connection->prepare("SELECT u.id as userid From user u , account a where (a.id_parent=$id_account OR a.id=$id_account) and u.id_account=a.id ");
$listUsers->execute();
$users=$listUsers->fetchColumn();
but fetchColumn return just one result, and I want a set of list user id to use it in the next request.
$listPush=$connection->prepare("select id from Table_name where id_user in (?));
$listPush->bindValue(1, $users);
$listPush->execute();
$idpushs=$listPush->fetchColumn();
but this return just one result. Any Idea to replace fetchColumn by other request or using doctrince.
With your logic, you can simply fetch all your users and implode it.
$listUsers=$connection->prepare("SELECT u.id as userid From user u , account a where (a.id_parent=$id_account OR a.id=$id_account) and u.id_account=a.id ");
$listUsers->execute();
$users=$listUsers->fetchAll();
$userIds = array();
foreach ($users as $user) {
$userIds[] = $user['userid'];
}
$users = implode(',', $userIds); //that hurts me so hard to code like this with symfony :'(
Fetch colum will only return the column of the next row. So for your second piece of code, you can loop over results.
But, if you're are using a framework like symfony, you have many other ways to make it cleaner. Just check out the symfony doc to use repository relations and more generally doctrine

Doctrine2 w/ child entities in the same table

I have a database table that generally (because of a NDA) has the structure of:
Category:
id(int) parent_id(int) title(string) description(text)
Note that I cannot change the table's schema, so that's not a possible solution to my problem.
I need to be able to get all of these categories' info, including a list of all their children, but I'm not quite sure how to do it. I'm fairly certain that I'll need to use recursion, but I'm not sure if there's anything built into Doctrine that can aid in it, or if I need to write raw DQL or even SQL. I currently have the following in my Symfony controller:
$em = $this->get('doctrine')->getManager();
$categoryQuery = $em->getRepository('Acme\MyBundle\Entity\Category')->findBy(array(), array('sortPosition' => 'asc'));
$categories = array();
foreach ($categoryQuery as $category) {
$categories[] = array(
'id' => $category->getId(),
'parent' => $category->getParent(),
'title' => $category->getTitle(),
'description' => $category->getDescription(),
);
}
There's another wrinkle: I need to output this info in JSON.
Ultimately, I'm not sure
A. How to create a query that will get me both a category and all of its child info (which can have more children)
B. How to then output that info as JSON
Any ideas would be greatly appreciated
If you have the category <> category relation defined in doctrine:
$categoryQuery = $em->getRepository('Acme\MyBundle\Entity\Category')
->createQueryBuilder('c')
->leftJoin('c.subCategories sc') // assuming your category <> category relation is called "subCategories
->getQuery()
->getResult()
;
Then in each record of $categoryQuery you will have a Category and its children in ->subCategories (you dont really need the join there)
If you dont have a relation defined in doctrine, then:
$query = $em->createQuery(
'SELECT c
FROM AcmeMyBundle:Category c
LEFT JOIN AcmeMyBundle:Category sc on sc.parent_id = c.id
ORDER BY sortPosition ASC'
);
$categories = $query->getResult();
And return them as JSON
return new JSONResponse($categories);
A. Recursive selection is ... hard/impossible without a path.
See : MySQL parent children one query selection
B. You can use this in Symfony2 :
Symfony\Component\HttpFoundation\JsonResponse

Is it possible to use the Drupal api to get a list of users?

I would like to get a list of all the users who have been assigned a certain role. I could write my own SQL but I would like to use the api as much as possible.
You can use entity_load to get array of users. Here is the sample that will create list of all emails for admin users (used to send notification)
<?php
$users = entity_load('user');
$emails = '';
foreach($users as $user) {
if (array_key_exists(3, $user->roles)) {
if (strlen($emails) > 0) {
$emails .= ' ' . $user->mail;
} else {
$emails = $user->mail;
}
}
}
?>
There are generally no Drupal API functions for this sort of task (pulling up entities that match certain criteria). It tends to focus on single-entity CRUD functions in the API; everything else is up to a developer's own SQL skills.
The Views module allows you to build lists of users filtered by role, permission, etc -- but it could easily be overkill.
The SQL that worked for me:
$users = "";
$result = db_query('SELECT users.name AS users_name FROM users users
INNER JOIN users_roles users_roles ON users.uid = users_roles.uid
WHERE users_roles.rid = 4');
while ($existing_user = db_fetch_object($result)) {
if ($users != "") $users .= ", ";
$users .= $existing_user->users_name; // or do whatever
}
echo $users;
Keep in mind this is for Drupal 6 and I'm not sure about the performance of this for large user bases. Not sure about Drupal 7.
One easy option is to use Views to generate the SQL (appears below the view its self when you press the preview button) for you and then use the Drupal SQL abstraction layer to get the results you need if you need to get access to the raw data rather than display a View.
It'd look a bit like this:
$result = db_query('SELECT users.uid AS uid,
users.mail AS users_mail,
users.name AS users_name
FROM users users');
while ($existing_user = db_fetch_object($result)) {
print_r($existing_user); // or do whatever
}
Just add more fields to the view to get the complete query.
In Drupal 8:
$users = \Drupal\user\Entity\User::loadMultiple();
And if you want to get e.g. only admins:
$admins = [];
foreach ($users as $user) {
if ($user->hasRole('administrator')) {
$admins[] = $user;
}
}
I don't know about any API can help to collect users by role. Here you are some link you can get something: http://drupal.org/node/82002.
Although SO is an awesome service I suggest using drupal.org or #drupal channel on irc.freenode.org for Drupal related questions.
Ps.: sometimes SQL is not that evil:)
In Drupal 7, use EntityFieldQuery is the proper way.
In Drupal 8 the following works (in this example, load all users with the administrator role)
\Drupal::service('entity_type.manager')
->getStorage('user')
->loadByProperties(['roles' => 'administrator']);
will return a list of user entities.
To get a list of uids instead, an entity field query:
$query = \Drupal::service('entity_type.manager')->getStorage('user')->getQuery();
$query->condition('roles', 'administrator');
$query->execute();

Categories