Magento2 add custom values in collection->setOrder - collections

I need to add some custom values in setOrder() of a collection, but it is not working.
$collection->setOrder("((lat - ".$lat.")*(lat - ".$lat.")) + ((lng - ".$lng.")*(lng - ".$lng."))", 'ASC');
The final part of my collection query like this:
ORDER BY ((lat - -34.9226513)*(lat - -34.9226513)) + ((lng - 138.6094486)*(lng - 138.6094486)) ASC

You should try to get rid of the minus signs in the $lat and $lng variables so you can concatenate them properly.
Something like this (untested).
$latString = '(lat'. (($lat >= 0) ? '-' : '+').abs($lat).')';
$lngString = '(lng'. (($lng >= 0) ? '-' : '+').abs($lng).')';
$collection->setOrder($latString.'*'.$latString.'+'.$lngString.'*'.$lngString, 'ASC');

Related

How to get total number of rows in a drupal view alter hook?

I've to avoid duplicate search result in a view, so what I am trying to alter the view using pre render hook. and removing the duplicates it's working fine but the problem is in the count of result. it shows the count from the query executed and this include the duplicated item too. also, I enabled the pagination with limit of 5 in a page. then the count seems to be strange it's taking the count of the elements showing in each page
function search_helper_views_pre_render(\Drupal\views\ViewExecutable $view) {
if ($view->id() == "all_news" || $view->id() == "all_publications" || $view->id() == "all_events" || $view->id() == "global_search") {
$unique_nids = $d_nids = $new_results = array();
// Loop through results and filter out duplicate results.
foreach($view->result as $key => $result) {
if(!in_array($result->nid, $unique_nids)) {
$unique_nids[] = $result->nid;
}
else {
unset($view->result[$key]);
}
}
$view->total_rows = count($view->result);
//$view->pager->total_items = count($view->result);
$view->pager->updatePageInfo();
}
}
the expected output of the $view->total_rows must be the total count of result instead of count of elements shown in the page.
You totaly done it in wrong way. as you see ( and it's clear from its name ), it's hook__views_pre_render it runs before the rendering. So its really hard to manipulate the views results and counter, pagination there.
As I see in your query you just remove duplicate Nids , so you can easily do it by Distinct drupal views feature.
Under Advanced, query settings, click on settings.
You will get this popup, now checkmark Distinct
Could do
$difference = count($view->result) - count($new_result);
$view->total_rows = $view->total_rows - $difference;
BTW Distinct setting doesn't always work, see https://www.drupal.org/project/drupal/issues/2993688

How to get count of certain record saved in Uppercase, lower or a combination using LINQ query

I need to get the count of IN / in / In from SoccerStatus regardless if the records are saved in upper case, lower case or a combination of both ie IN or in or In from SQLite database in Xamarin Forms. How can I achieve that ?
var count_in = (from x in conn.Table<SoccerAvailability>().Where(x => x.SoccerStatus == IN) select x).Count();
Use string.Equals and tell it to ignore case...
var count_in = (from x in conn.Table<SoccerAvailability>().Where(x => string.Equals(x.SoccerStatus, "IN", StringComparison.OrdinalIgnoreCase)) select x).Count();
EDIT: Per your comment I see that the Linq provider you're using doesn't support string.Equals. You can try the following which should be more portable but possibly a bit slower...
var count_in = (from x in conn.Table<SoccerAvailability>().Where(x => x.SoccerStatus.ToUpper() == "IN") select x).Count();

Firebase query endAt() except/exclude its key

a
b
c
d
e
FirebaseRef.orderByKey().endAt('c').limitToLast(2) will return
b, c
I want to retreive except c, so a, b are what I want.
How can I do this?
In this case you need to use limitToFirst() method like this:
FirebaseRef.orderByKey().limitToFirst(2);
You output will be: a, b
If you have data before a, you need to startAt() and endAt methods like this:
FirebaseRef.orderByKey().startAt('a').endAt('b');
Please see the official documentation regarding Retrieving Data in Firebase
If your endAt() query uses strings, it will compare lexicographically, so you'll need to subtract one charCode from the last character of the string. The following should work when searching for strings:
FirebaseRef.orderByKey().endAt(exclude('c')).limitToLast(2) will return
exclude(key){
return key.substring(0, key.length - 1) + String.fromCharCode(key.charCodeAt(key.length - 1) - 1)
}
#godlerner's answer worked best for me however an edge case needs to be added because if you have a key that ends with a 0 it will replace the 0 with "/" which will cause the query to fail and throw an exception because firebase does not allow keys to contains "/"
This works better
exclude(key) {
let unallowedChars = '.#$/[]'
let newKey = key.substring(0, key.length - 1) + String.fromCharCode(key.charCodeAt(key.length - 1) - 1)
if(unallowedChars.includes(newKey[newKey.length - 1])){
while(unallowedChars.includes(newKey[newKey.length - 1])) {
newKey = newKey.substring(0, newKey.length - 1) + String.fromCharCode(newKey.charCodeAt(newKey.length - 1) - 1)
}
}
return newKey
}

Symfony 3 Too many parameters

I'm new to Symfony, and I got an error while running a query :
public function getFilteredArticles($page, $nbPerPage, $data) {
$query = $this->createQueryBuilder('a')
->leftJoin('a.images', 'i')
->addSelect('i')
->leftJoin('a.type_stockage', 't')
->addSelect('t')
->leftJoin('a.famille', 'f')
->addSelect('f');
if ($data['famille'] != '') {
$query->where('f.id = :famille')
->setParameter('famille', $data['famille']);
}
if ($data['rds'] == false) {
$query->where('a.stock_actuel > 0');
}
if ($data['recherche'] != '' && $data['recherche'] != null) {
$query->where('a.ref_article LIKE :recherche')
->setParameter('recherche', '%' . $data['recherche'] . '%');
}
$query->leftJoin('a.sousfamille', 's')
->orderBy('a.ref_article', 'ASC')
->getQuery();
$query->setFirstResult(($page - 1) * $nbPerPage)
->setMaxResults($nbPerPage);
return new Paginator($query, true);
}
This query have conditionnals parameters as you can see, that returns the list of articles I need for a table. But when I run this query to fill my table, I got the error :
An exception has been thrown during the rendering of a template ("Too
many parameters: the query defines 0 parameters and you bound 1").
I don't know why he is expecting 0 parameters. I tried using setParameters instead, but the result is the same.
Does anyone has an idea?
You should use andWhere() methods instead of where().
where() method removes all previous where, but setParameter() does not. That's why he found more parameters than where clauses.
I personally never use where if the condition has no sense to be the first condition, to avoid this kinds of errors.
if ($data['famille'] != '') {
$query->andWhere('f.id = :famille')
->setParameter('famille', $data['famille']);
}
if ($data['rds'] == false) {
$query->andWhere('a.stock_actuel > 0');
}
if ($data['recherche'] != '' && $data['recherche'] != null) {
$query->andWhere('a.ref_article LIKE :recherche')
->setParameter('recherche', '%' . $data['recherche'] . '%');
}
where() php doc
Specifies one or more restrictions to the query result.
Replaces any previously specified restrictions, if any.
andWhere() php doc
Adds one or more restrictions to the query results, forming a logical
conjunction with any previously specified restrictions.
My error, in Symfony 4, using Doctrine 2.6 was
Too many parameters: the query defines 0 parameters and you bound 2
The problem was that I wasn't defining the parameters in andWhere method as
$this->createQueryBuilder('q')
...
->andWhere('q.propertyDate IS NOT NULL') //this also couldn't find anywhere
->andWhere('q.parameterName = :parameterName')
->setParameters(['q.parameterName' => $parameterName, ...2nd parameter])
As I couldn't find any answer to my problem, but was similar to this one, I thought to maybe help someone who is struggling like I was.
also in symfony 5 and 6 you should use andWhere() methods instead of where().
where() method removes all previous where, but setParameter() does not. That's why he found more parameters than where clauses.

add timestamp to click event in google tag manager

Currently, in the User Report view of Google Analytics, I get timestamps on each event, but it is only down to the minute, not the second. I can't find a setting in GA that changes that column.
My goal is to pass this timestamp through GTM, perhaps as "tag label", so that I can see it in GA.
How do I create a timestamp variable in GTM?
Create a custom javascript variable (i.e. a variable that contains a function, not a "javascript" variable that just reads a global variable), and give it a name, e.g. "timestamp".
Custom javascript variables are anonymous functions with a return value.
The current way to get a timestamp is Date.now(). This might not be supported by older browser (especially IE 8 and lower), so you might use new Date().getTime(); as an alternative.
The variable body would be as simple as:
function() {
return Date.now();
}
and you would use that in a tag by surrounding the variable name with double curly parenthesis, e.g. {{timestamp}}. Date.now() returns milliseconds ( elapsed since 1 January 1970 00:00:00 UTC), so you might want to divide by thousand.
Alternatively you could create a datetime variable that includes seconds and even milliseconds. I think this was originally by Simo Ahava:
function() {
// Get local time as ISO string with offset at the end
var now = new Date();
var tzo = -now.getTimezoneOffset();
var dif = tzo >= 0 ? '+' : '-';
var pad = function(num) {
var norm = Math.abs(Math.floor(num));
return (norm < 10 ? '0' : '') + norm;
};
return now.getFullYear()
+ '-' + pad(now.getMonth()+1)
+ '-' + pad(now.getDate())
+ 'T' + pad(now.getHours())
+ ':' + pad(now.getMinutes())
+ ':' + pad(now.getSeconds())
+ '.' + pad(now.getMilliseconds())
+ dif + pad(tzo / 60)
+ ':' + pad(tzo % 60);
}
which returns a formatted string like 2016-08-02T09:22:44.496+02:00.
The second it's not accesible via Google Analytics. The closest way to do this is via Google Big Query,but this last is only available for premium members.
Maybe you can add the timeStamp as CustomDimentions
function getdateGA(){
return Date();
}
ga('send', 'event', 'category', 'action', {
'dimention1': getdateGA()
});
The date format is not the best one, try to find the best for you modifing the getdateGA function
More resources about the date in
How to format a JavaScript date

Resources