get Result only from one Collection mongodb/Symfony 2 - symfony

I wanted to select cities depending from countries so i made this code, but the funny things here is that code show me only the id of the countries that's it and he ignores totally the cities query, it doesn't return nothing:
public function ctsAction() {
$ctry = $this->get('doctrine_mongodb')
->getRepository('indexBundle:Ctes')
->findOneByCountryName($q_country);
if( !empty($ctry) )
{
$search_country = $ctry->getCtryId();
$cties_list = $this->get('doctrine_mongodb')
->getRepository('indexBundle:Cties')
->findOneByCountryId($ctry);
}
}
If u need some other things tell me, from where comes the problem?

I solved like that:
$result = array();
$return = array();
$result = $cties_list->toArray();
foreach ($result as $val) {
array_push($return, $val->getCityName());
};
If there is any other suggestion, don't hesitate

Related

Query Builder "OR" in dynamic query

I would like to build a query with clause "OR" and the query receive an array parameter and doesn't know how elements it contains.
The query has to return a list of contents that have the category "1" or "2"(if $categ array contain [1,2]) etc.
Category is a foreign key in the content entity.
My repository:
public function getContentOfSomeCategories($categs)
{
$query = $this->createQueryBuilder('c');
$conditions = [];
foreach($categs as $value){
$conditions[] = 'c.contentCategory = '.$value;
}
$orX = $query->expr()->orX();
foreach ($conditions as $condition) {
$orX->add($condition);
}
$query->add('where', $orX);
I obtain the error message "Too many parameters: the query defines 1 parameters and you bound 2".
From PHP 5.6 onward, you can probably use PHP splat ... to expand an array to arguments.
$query = $this->createQueryBuilder('c');
$expr = $query->expr();
$conditions = [];
$valueNo = 0;
foreach ($categs as $value) {
$conditions[] = $expr->eq('c.contentCategory', 'value'.$valueNo);
$query->setParameter('value'.$valueNo, $value);
$valueNo++;
}
$query->andWhere($expr->orX(...$conditions));
Disclaimer: I've not tested this.
See: https://www.php.net/manual/en/functions.arguments.php
You can also use ... when calling functions to unpack an array or Traversable variable or literal into the argument list:
Edit:
If your query is simple, you could just use orWhere instead.
$query = $this->createQueryBuilder('c');
$expr = $query->expr();
$valueNo = 0;
foreach ($categs as $value) {
$query->orWhere($expr->eq('c.contentCategory', 'value'.$valueNo));
$query->setParameter('value'.$valueNo, $value);
$valueNo++;
}
Edit 2:
You might even want to just use an in clause instead.
$query->where($expr->in('c.contentCategory', ':values'));
$query->setParameter('values', $categs);`
You can achieve this quite easily, below utilises the query builder expression builder:
$queryBuilder = $this->createQueryBuilder('c');
$conditions = [];
$i = 0;
foreach ($categs as $value) {
$i++;
$conditions[] = $queryBuilder->expr()->eq('c.contentCategory', $i);
$queryBuilder->setParameter($i, $value);
}
$queryBuilder->andWhere(
$queryBuilder->expr()->orX()->addMultiple($conditions)
);
If you parameter applies to all then you can just add
$queryBuilder->setParameter();

Add class to drupal body

How can I add term id of all terms related to a node, to that node body class in drupal site?
For example, A node named stackoverflow is tagged with four terms
term1
term2
term3
term4
term5
I want to add these classed to node body class...
article-term-(term1tid)
article-term-(term2tid)
article-term-(term3tid)
article-term-(term4tid)
article-term-(term5tid)
These are pages I want to change their class names:
عکس نوزاد
عکس نوزاد
کاردستی
سوپ ساده
داستان برای کودک
کاردستی
leymannx code is really complete and fine.
But it does not contains all terms of a node.
I wrote this code and i wish it will be useful for you.
function YOURTHEME_preprocess_html(&$variables) {
if (arg(0) == 'node' && is_numeric(arg(1))) {
$node = node_load(arg(1));
$results = stackoverflow_taxonomy_node_get_terms($node);
if (is_array($results)) {
foreach ($results as $item) {
$variables['classes_array'][] = "article-term-" . $item->tid;
}
}
}
}
There is a function named ""stackoverflow_taxonomy_node_get_terms"" that returns all terms attached to a node.
function stackoverflow_taxonomy_node_get_terms($node, $key = 'tid'){
static $terms;
if (!isset($terms[$node->vid][$key])) {
$query = db_select('taxonomy_index', 'r');
$t_alias = $query->join('taxonomy_term_data', 't', 'r.tid = t.tid');
$v_alias = $query->join('taxonomy_vocabulary', 'v', 't.vid = v.vid');
$query->fields($t_alias);
$query->condition("r.nid", $node->nid);
$result = $query->execute();
$terms[$node->vid][$key] = array();
foreach ($result as $term) {
$terms[$node->vid][$key][$term->$key] = $term;
}
}
return $terms[$node->vid][$key];
}
i wish this code could be the best.
write all of this codes in template.php file in your theme.
if you want just some nodes have class name, add replace this part of code.
> if (arg(0) == 'node' && is_numeric(arg(1)) && ( arg(1)==X || arg(1)==Y
> ) ) {
As #P1ratRuleZZZ already pointed out template_preprocess_html (implemented from your sub-theme's template.php file) is the function to add body classes.
Thing is, that within this function, you need to load the actual node object first, then get the values of that term reference field, to finally add them as classes to the body tag.
Replace MYTHEME and field_MYFIELD with your names.
/**
* Implements template_preprocess_html().
*/
function MYTHEME_preprocess_html(&$variables) {
// Get the node.
if ($node = menu_get_object()) {
// Check node type.
if ($node->type === 'article') {
// Get taxonomy terms.
$terms = field_get_items('node', $node, 'field_MYFIELD');
foreach ($terms as $term) {
// Add body class.
$variables['classes_array'][] = 'article-term-' . $term['tid'];
}
}
}
}
Try to use template_preprocess_html()
this is in your theme's template.php file:
YOURTHEMENAME_preprocess_html(&$variables) {
$term_id = arg(1); // For example, or use some &drupal_static() to store a value while preprocessing from module
$variables['classes_array'][] = 'article-term-' . $term_id;
}
So as you can see it you shoud change template_ to your themename_ first

Silverstripe - filter DataObject list by many many relationship

I have an Object that extends Page ("Thing") which has a many_many relationship with a DataObject ("Tag").
class Thing extends Page
{
static $many_many = array(
'Tags' => 'Tag'
);
}
class Tag extends DataObject
{
static $belongs_many_many = array(
'Things' => 'Thing'
);
}
I have an array of Tag IDs and I want to get a list of Things that have all of these tags attached.
The following should be possible...
$tag_ids = array(1,2,3,4);
$things = Thing::get();
$things->filter('Tags.ID', array($tag_ids));
...but this just returns an unfiltered list. Apparently this hasn't been implemented for relationships yet. So how can I do it?
I think if you are using older versions for SilverStripe 3, you need to use the ExactMatchMulti SearchFilter.
$tag_ids = array(1,2,3,4);
$things = Thing::get();
$things->filter('Tags.ID:ExactMatchMulti', $tag_ids);
I don't see an easy solution do do this directly with the ORM. But you should be able to solve this with some loops and filtering.
$tag_ids = array(1,2,3,4);
$things = Thing::get();
$results = new ArrayList();
$tags_count = count($tag_ids);
$matches = 0;
foreach ($things as $thing)
{
foreach ($thing->Tags() as $tags)
{
$matches = 0;
foreach ($tags as $tag)
{
if ( in_array($tag->ID, $tag_ids) )
{
$matches++;
}
}
if ( $matches === $tags_count )
{
$results->push($thing);
}
}
}
Although not tested, this should leave you with $things that contain those with all tags and more. (Assuming a thing can only be tagged once with the same tag).
For performance reasons you would probably be better off relying as much as possible on a sql query.
$tag_ids = array(1,2,3);
$objects = new ArrayList();
if (count($tag_ids)) {
$sql = "SELECT \"SiteTree\".*, \"Page\".*, \"Thing\".*,count(\"ThingID\") AS ThingIDCount FROM \"SiteTree\" ";
$sql.= "LEFT JOIN \"Page\" ON \"Page\".\"ID\" = \"SiteTree\".\"ID\" ";
$sql.= "LEFT JOIN \"Thing\" ON \"Thing\".\"ID\" = \"SiteTree\".\"ID\" ";
$sql.= "LEFT JOIN \"Thing_Tags\" ON \"Thing_Tags\".\"ThingID\" = \"SiteTree\".\"ID\" ";
$sql.= "LEFT JOIN \"Tag\" ON \"Thing_Tags\".\"TagID\" = \"Tag\".\"ID\" ";
$sql.= "WHERE \"TagID\" IN (" . implode(',', $tag_ids) . ") GROUP BY \"ThingID\" HAVING ThingIDCount >= " . count($tag_ids);
// Get records
$records = DB::query($sql);
foreach($records as $record) {
$objects->push(new Thing($record));
}
}
// Display the Things for demo purposes
foreach($objects as $thing){
Debug::Dump($thing);
}
NB I have added a left join to a Thing table, as I imagine you have some db fields on it, but drop the line (and the \"Thing\".* on the SELECT statement) if that's not the case
You can try to do the following:
Tag::get()->byIds($tag_ids)->relation('Things')
which will return a ManyManyList that you can iterate over, ie
foreach(Tag::get()->byIds($tag_ids)->relation('Things') as $thing){
Debug::Dump($thing); // A 'Thing' object
}
Hope this helps

Drupal 7 - Insert taxonomy into node object

I have a script which successfully creates new nodes. But I'm having trouble setting the taxonomy before saving.
I believe in Drupal 6 I would use this method.
$cat1_tid = taxonomy_get_term_by_name($data[$i]['cat1']);
$cat2_tid = taxonomy_get_term_by_name($data[$i]['cat2']);
$cat3_tid = taxonomy_get_term_by_name($data[$i]['cat3']);
$node->taxonomy = array($cat1_tid, $cat2_tid, $cat3_tid);
I think in Drupal 7 I would do this (my field name is Catalog)
$node->taxonomy_catalog['und'][0] = array($term1Obj, $term2Obj);
taxonomy_get_term_by_name doesn't seem to return the correct object to insert into the node object.
If anyone can shed some light, appreciated.
Thanks
EDIT
Solution:
// Taxonomy
$categories = array($data[$i]['cat1'], $data[$i]['cat2'], $data[$i]['cat3']);
foreach ($categories as $key => $category) {
if ($term = taxonomy_get_term_by_name($category)) {
$terms_array = array_keys($term);
$node->taxonomy_catalog[LANGUAGE_NONE][$key]['tid'] = $terms_array['0'];
}
}
Below is some quick-and-dirty code I used recently to import "command" nodes into a site. Mid-way down, the foreach loop takes care of creating and assigning terms, as needed.
$command = new stdClass;
$command->language = LANGUAGE_NONE;
$command->uid = 1;
$command->type = 'drubnub';
$command->title = $line['0'];
$command->body[LANGUAGE_NONE]['0']['value'] = $line['1'];
$command->url[LANGUAGE_NONE]['0']['value'] = trim($line['2']);
$command->uses[LANGUAGE_NONE]['0']['value'] = $line['3'];
$tags = explode(',', $line['4']);
foreach ($tags as $key => $tag) {
if ($term = taxonomy_get_term_by_name($tag)) {
$terms_array = array_keys($term);
$command->field_tags[LANGUAGE_NONE][$key]['tid'] = $terms_array['0'];
} else {
$term = new STDClass();
$term->name = $tag;
$term->vid = 1;
if (!empty($term->name)) {
$test = taxonomy_term_save($term);
$term = taxonomy_get_term_by_name($tag);
foreach($term as $term_id){
$command->product_tags[LANGUAGE_NONE][$key]['tid'] = $term_id->tid;
}
$command->field_tags[LANGUAGE_NONE][$key]['tid'] = $tid;
}
}
}
node_save($command);
Here you are, this code successfully add a new term to the node before the node is created.
$my_term_name = 'micky';
$term_array = taxonomy_get_term_by_name($my_term_name);
if($term_array == array()){
//empty term ..
$term->name = $my_term_name;
$term->vid = 1;
taxonomy_term_save($term);
$term_array = taxonomy_get_term_by_name($my_term_name);
}
//get the first index of the array .
foreach ($term_array as $tid => $term_object)break;
$node->field_tag['und'][$tid] = (array)$term_object;
Perhaps my experience is unique, but I found that using
$term = taxonomy_get_term_by_name($tag)
$tid = $term->tid;
caused an error.
I found that after $term is saved, there is no need to fetch the newly created term.
The $term object is updated to include the new tid.
Any answer that use LANGUAGE_NONE or 'und' to alter a field is not the proper way of doing it as it assumes that the drupal site is one language. The proper way to edit a field is to use entity_metadata_wrapper.
$node_wrapper = entity_metadata_wrapper('node', $node);
// If you have Entity API [entity] module installed you can simply.
$node_wrapper = $node->wrapper();
// It is good practice to check the terms in the field before adding
// a new one to make sure that the term is not already set.
$term_ids_current = $node_wrapper->taxonomy_catalog->raw();
if (!in_array($term_new_id, $term_ids_current)) {
$node_wrapper->taxonomy_catalog[] = $term_new_id;
}
// To add multiple terms iterate an array or terms ids.
$term_ids_current = $node_wrapper->taxonomy_catalog->raw();
$tern_new_ids = array(1, 2, 3);
foreach ($term_new_ids as $term_new_id) {
if (!in_array($term_new_id, $term_ids_current)) {
$node_wrapper->taxonomy_catalog[] = $term_new_id;
}
}
// To remove a term.
$term_ids_current = $node_wrapper->taxonomy_catalog->raw();
$delta = array_search($term_remove_id, $term_ids_current);
if (is_int($delta)) {
$node_wrapper->taxonomy_catalog->offsetUnset($delta);
}
// To replace all terms.
$term_new_ids = array(1, 2, 3);
$node_wrapper->taxonomy_catalog->set($term_new_ids);
// To get all the fully loaded terms in a field.
$terms = $node_wrapper->taxonomy_catalog->value();
// At the end make sure to save it.
$node_wrapper->save();

how to do boolean search in apache solr

I was trying to do do a boolean search 'sname:'.$user->name.' OR sname:xxxxxx; , i am not getting any results where as sname:xxxxxx; works fine. i even added mm=1 with the query modify hook. can somebody guide me how i can accomplish this.
Here is my code.....
$keys = "";
$filters = 'sname:'.$user->name.' OR sname:xxxxxx;
//print($filters);
$solrsort = variable_get('apachesolr_search_taxonomy_sort', 'created desc');
$page = isset($_GET['page']) ? $_GET['page'] : 0;
$_GET['retain-filters'] = 1;
try {
//stolen from search.module (search_data)
$data = apachesolr_search_execute($keys, $filters, $solrsort, 'search/apachesolr_search', $page);
$results = theme('search_results', $data, $type);
} catch (Exception $e){
watchdog('apachesolr', t('Error running search'));
}
function reports_apachesolr_modify_query(&$query, &$params, $caller) {
// I only want to see articles by the admin!
$params['mm'] = 1;
}
Adv thanks.
The $user object is not available in some places, so it depends where you are calling it from. You need to invoke it globally. Add the following to the top of your code.
$keys = "";
global $user; //Add this line
$filters = 'sname:'.$user->name.' OR sname:xxxxxx';
Also note that you are missing a closing quotation mark after the xxxxxx. I added it in the above code.
Did you try removing the second sname:?? My SOLR filters look like:
(fname:carrie OR carol)
AND
(lname:miller OR jones)

Resources