Query database and store results in array in drupal module - drupal

I have a table in my database called gsm_tariff. Basically I just want to run a simple select query
"SELECT * FROM {gsm_tariff} WHERE Country='Afghanistan'"
and store the results in an array. Can anyone help me with how to do this please? I know where to put the code and everything; I just need the code to do the query and store the results in an array.

$array = array();
$result = db_query('SELECT * FROM {gsm_tariff} WHERE Country = "%s"', 'Afghanistan');
while ($record = db_fetch_object($result)) {
$array[] = $record->(data to reference);
}
Note that I don't know the field you want to reference given the question, but it would be in the $record object.

Related

How to combine queryBuilder and raw queries on join table from many to many relation?

I have got following query
SELECT news.*, count(*) AS common_tags
FROM news
JOIN news_news_tag ON news.id = news_news_tag.news_id
WHERE news_tag_id IN
(SELECT news_tag_id FROM news_news_tag WHERE news_id = 2 )
AND news.id != 2 GROUP BY news.id ORDER BY common_tags DESC
What I want to achieve is to get hydrated news objects ordered by number of common tags with provided news id. News and Tag are many to many relation with news_news_tag join table.
News entity have got much more other relations. This is why I don't want to create a native query by myself to handle all other relations.
I would like to convert above query to use it with query builder. I wasn't able to use a DQL because my where statement uses a join (junction) table and I also need to use a join on that table.
All in all I have got 2 problems:
How can I create DQL subquery to select something from many to many join table)? If I know that I could do something like: ->where($queryBuilder->expr()->in('u.id', $mySubQueryAsDQL))
How to add that join statement that I could use news_tag_id in where statement?
If it is not possible I think that I would need to create two bidirectional one-to-many and many-to-one relations instead of many-to-many and work on special joining entity.
I finally came up with following solution. I decided to split that query into two separate ones. In first I can use just simple raw query as I need results only to where statement. Second query can be build using query builder in a normal way.
You have to only get rid of an extra count column at the end.
However if someone knows the solution how to use my first raw query directly inside query builder as a raw subquery for where statement please share with me.
public function getRelatedNews($newsId, $limit = 6)
$connection = $this->getEntityManager()->getConnection();
$sql = 'SELECT news_tag_id FROM news_news_tag WHERE news_id = :newsId';
try {
$stmt = $connection->prepare($sql);
} catch (DBALException $e) {
return [];
}
$stmt->execute(['newsId' => $newsId]);
$newsTagId = $stmt->fetchAll();
if (empty($newsTagId)) {
return [];
}
$newsTagId = array_column($newsTagId, 'news_tag_id');
$query = $this->createQueryBuilder('n')
->addSelect('COUNT(n.id) as common_tags_count')
->innerJoin("n.tags", "t")
->andWhere('t.id IN(:tagsId)')->setParameter('tagsId', array_values($newsTagId))
->andWhere('n.id != :newsId')->setParameter('newsId', $newsId)
->orderBy('common_tags_count', 'DESC')
->setMaxResults($limit)
->groupBy('n.id')
;
$results = $query->getQuery()->getResult();
$news = [];
foreach ($results as $result) {
$news[] = $result[0];
}
return $news;
}

Symfony / Doctrine findBy

Hove to create custom Repository function who query by json field. I have params column in my database who look like this:
"params": {
"product": "stopper",
"itemIdentifier": ""
}
I want to query record by product value. In this case stopper term.
You can achieve this with a classic example :
In your repository :
For one result
public function findOneProduct($value): ?Params
{
return $this->createQueryBuilder('p')
->andWhere('p.product = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
For multiple result
public function findParamsByProduct($value): ?Params
{
return $this->createQueryBuilder('p')
->andWhere('p.product = :val')
->setParameter('val', $value)
->orderBy(/*some field */)
->setMaxResults(/*if needed*/)
->getQuery()
->getResults()
;
}
In your controller:
$stoppers = $entityManager->getRepository(Params::class)->findParamsByProduct('stopper');
If I understood your question correctly, you have a table with a column named params. And inside this mysql column, you store JSON text.
And then you want to query that table and filter by looking into the JSON in your column.
This can be a bit tedious and was also highly discouraged in the past (prior to the JSON Type in Mysql 5.7.8).
Best practices would be to have a NoSQL DB such as MongoDB which is actual JSON stored in a collection(table).
Anyways, there is a solution for you.
Taking into account #AppyGG explained how to make a custom repository function.
First of all, we have to make a query using pure SQL.
It can be done two ways:
1.Return arrays containing your data.
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$stmt = $conn->prepare($sql);
$stmt->execute(['price' => $price]);
// returns an array of arrays (i.e. a raw data set)
return $stmt->fetchAll();
2.Return hydrated Entities
use Doctrine\ORM\Query\ResultSetMappingBuilder;
$rsm = new ResultSetMappingBuilder($entityManager);
$rsm->addRootEntityFromClassMetadata('MyProject\Product', 'p');
$sql = '
SELECT * FROM product p
WHERE p.price > :price
ORDER BY p.price ASC
';
$nql = $this->_em->createNativeQuery( $sql, $rsm );
$nql->setParameter('price', $price);
//Return loaded entities
return $nql->getResult();
Now, knowing how to make make a MySQL query with doctrine, we want to select results filtered in JSON data.
I'm am referencing this beautiful stackoverflow which explains it all:
How to search JSON data in MySQL?
The easiest solution proposed in there requires at least MySQL 5.7.8
Your MySQL query would be as follow:
//With $entity->getParams() == '{"params": {"product":"stopper", "itemIdentifier":""}}'
$conn = $this->getEntityManager()->getConnection();
$sql = '
SELECT * FROM Entity e
WHERE JSON_EXTRACT(e.params, "$.params.product") = :product
';
//Or Like this if the column is of Type JSON in MySQL(Not doctrine, yes check MySQL).
$sql = '
SELECT * FROM Entity e
WHERE e.params->"$.params.product" = :product
';
$stmt = $conn->prepare($sql);
$statement->bindValue("product","stopper");
$stmt->execute();
return $statement->fetchAll();
Hope this helps!
P.S: Note that my example uses a column named 'params' with a Json containing also a named attribute 'params', this can be confusing. The intended purpose is to show how to do multiple level filtering.

Symfony2 dynamic queryBuilder

I'm making a tool in which a user can view data from an entity, where they can choose what data and how they see the records.
I created a form with two date fields (start and end) and a list of fields that correspond to data counts and sums of the entity.
My question is:
How I can create a dynamically QueryBuilder that allows me to add fields based on what the user wants to see?
EDIT for Symfony2 dynamic queryBuilder
public function reportData($fields, $dateStart, $dateFinish)
{
$em = $this->getEntityManager()
->getRepository('AcmeBundle:Entity');
$query = $em->createQueryBuilder('e');
foreach($fields as $field)
{
switch($field)
{
case 'totalResults':
$query->setect('SUM(e.id) AS '.$field);
break;
}
}
$query->addWhere('e.dateStart >= :dateStart');
$query->addWhere('e.dateFinish <= :dateFinish');
...
Something like this ? You store all your select queries in an array, then pass the array to the query builder after testing each of your fields.
public function reportData($fields, $dateStart, $dateFinish)
{
$em = $this->getEntityManager()
->getRepository('AcmeBundle:Entity');
$query = $em->createQueryBuilder('e');
$select_array = array();
foreach($fields as $field)
{
switch($field)
{
case 'totalResults':
$select_array[] = 'SUM(e.id) AS '.$field;
break;
}
}
$query->select($select_array);
$query->addWhere('e.dateStart >= :dateStart');
$query->addWhere('e.dateFinish <= :dateFinish');
....
Basically, you want to keep on adding the
Select Fields
based upon the conditions.
So, the solution is simple.
You can use,
$queryBuilder->addSelect();
See Doctrine Query Builder Documentation
I would do a regular full query then filter it into a not doctrine object (dao/dto) then display it.
This way you can do the complex and optimized query first, then filter the result on whatever you want, even if it's not related to the query itself

symfony2 QueryBuilder with a json field

Sorry for my english.
I'm blocked to a point and I wish you help me.
I have a json field in my entity. I want, with querybuilder, get statut of profil1.
Example from my field in my table in the BDD : (saved like this)
{
"Profil1":{
"statut":"première visite",
"site":"site officiel"
},
"Profil2":{
"statut":"ancien",
"motif":"facebook"
}
}
Something like this:
$queryBuilder = $entityManager->createQueryBuilder()
->select('e')
->from('ACMEDemoBundle:YourEntity', 'e');
$result = $queryBuilder
->getQuery()->getResult();
foreach ($result as $entity)
{
$jsonObject = json_decode($entity->getJsonField()); //where jsonField is the name of the field containing the json
$profile1Statut = $jsonObject['Profil1']['statut'];
}
Probably you want to make some sanity checks also. And depending of the size of your table, it may be a little bit overkilling.

algorithm to get result like taxonomy_get_tree(). But retrieve only non empty terms

I need to get an associated array of terms in drupal that has node associated with it. However, I can't seem to figure it out the appropriate algorithm.
What I want is something like taxonomy_get_tree(). But, only term that has associated node with it.
This query will get the term ids for you.
db_query("SELECT DISTINCT tid FROM {term_node}");
The following code should do exactly what you're after.
$terms = array();
$result = db_query("SELECT * FROM {term_data} WHERE tid IN (SELECT DISTINCT(tid) FROM {term_node})");
while($term = db_fetch_object($result)) {
$terms[] = $term;
}

Resources