четверг, февраля 02, 2006

Баг сортировки по дате

Вот отловил ещё одного жука, причем в уже знакомом месте - в сортировке. Бинарно-безопасное сравнение значений не справилось с корректной сортировкой по данным вида "21/01/2006" и выдало совсем не то, что надо.

Как бороться? Если вашей целью стоит сортировка по полю DATE, а не DATE_CREATE или ID, т.е. в процессе добавления новостей у вас случается, что вы добавляете новости задним числом или же наоборот, опережая время, вам не обойтись без это "латалки".

Итак, открываем /usr/system/common_extfunctions.inc.php (для большей ясности в примере использую стандартный файл, а не тот, что я уже подправлял, как описывалось ранее в этом блоге). Далее опускаемся в низ и находим там вот такие строки:

if(!defined("cmp_indexasc")) {
function cmp_indexasc($a, $b) {
global $sapi_obj;
$index = $sapi_obj->env["index"];
return strcmp($a[$index], $b[$index]);
}
define("cmp_indexasc", 1);
}


if(!defined("cmp_indexdesc")) {
function cmp_indexdesc($a, $b) {
global $sapi_obj;
$index = $sapi_obj->env["index"];
return strcmp($a[$index], $b[$index]);
}
define("cmp_indexdesc", 1);
}
Кстати обратите внимание, тут ещё есть баг, который очевиден - и в случае ASC сортировке и в случае DESC производится одна и та же сортировка. Но сейчас мы все это поправим, а заодно не забудем про ранее описанный баг сортировки по ID. Заменяем это дело на следующее:
if(!defined("cmp_indexasc")) {
function cmp_indexasc($a, $b) {
global $sapi_obj;
$index = $sapi_obj->env["index"];
if($index=='ID')
return ($a[$index] > $b[$index]) ? -1 : 1;
else if ($index=='DATE'){
$date_a=explode('/',$a[$index]);
$date_b=explode('/',$b[$index]);
$a_index=mktime (0,0,0,$date_a[1], $date_a[0], $date_a[2]);
$b_index=mktime (0,0,0, $date_b[1], $date_b[0], $date_b[2]);
return strcmp($a_index,$b_index);
}
else
return strcmp($a[$index], $b[$index]);
}
define("cmp_indexasc", 1);
}


if(!defined("cmp_indexdesc")) {
function cmp_indexdesc($a, $b) {
global $sapi_obj;
$index = $sapi_obj->env["index"];
if($index=='ID')
return ($a[$index] > $b[$index]) ? 1 : -1;
else if ($index=='DATE'){
$date_a=explode('/',$a[$index]);
$date_b=explode('/',$b[$index]);
$a_index=mktime (0,0,0, $date_a[1],$date_a[0], $date_a[2]);
$b_index=mktime (0,0,0, $date_b[1], $date_b[0], $date_b[2]);
return strcmp($b_index,$a_index);
}
else
return strcmp($b[$index],$a[$index]);
}
define("cmp_indexdesc", 1);
}
Скачать: common_extfunctions.inc.zip
Для версии: Sapid 1.2.3 RC3

Если кто-то будет это использовать, пожалуйста, отпишитесь о результатах в комментариях.

10 Comments:

At 12:14 AM, Anonymous Анонимный said...

У меня возникла аналогичная проблема с сортировкой по дате и все вроде бы решилось с твоей помощью! Только common_extfunctions.inc.php у меня лежит в system (версия sapid123.05beta2). Очень тебе признателен, спасибо.
Александр, аська 92145767.

 
At 1:57 PM, Anonymous Анонимный said...

Скачал common_extfunctions.inc.zip и заменил им старую версию файла (sapid 1.2.3.06). Фокус не удался. Посоветуйте, как быть...

 
At 2:48 PM, Blogger Pavel Brovchenko said...

Возможно неверно вызвана сортировка по дате в DDC. Нужно чтобы было (INDEX,DATE,DESC) или ASC. Или возможно не поле DATE на самом деле в вашем инфоканале называется не DATE а как-то иначе, как вы его переименовали...

 
At 12:02 PM, Anonymous Анонимный said...

В том то и дело, что я инфоканал не трогал вовсе :) А можете поконкретнее намекнуть, где проверить (INDEX,DATE,DESC)

 
At 12:04 PM, Anonymous Анонимный said...

if( preg_match("/_ORDER\(RANDOM\)_/s", $addparams) ) $ORDER = "random";
if( preg_match("/_ORDER\(DATEC,\s?ASC\)_/s", $addparams) ) $ORDER = "datecasc";
if( preg_match("/_ORDER\(DATEC,\s?DESC\)_/s", $addparams) ) $ORDER = "datecdesc";
if( preg_match("/_ORDER\(INDEX,\s?([^,]+),\s?ASC\)_/s", $addparams) ) {
$sapi_obj->env["index"] = preg_replace("/^.*?_ORDER\(INDEX,\s?([^,]+),\s?ASC\)_.*?$/s", "\\1", $addparams);
$ORDER = "index_asc";
}
if( preg_match("/_ORDER\(INDEX,\s?([^,]+),\s?DESC\)_/s", $addparams) ) {
$sapi_obj->env["index"] = preg_replace("/^.*?_ORDER\(INDEX,\s?([^,]+),\s?DESC\)_.*?$/s", "\\1", $addparams);
$ORDER = "index_desc";

Это не то?

 
At 4:48 PM, Blogger Pavel Brovchenko said...

Нет, вот в PHP лесть не надо. Убедительная просьба: перед тем как что-то у кого-то спрашивать - прочтите Руководство Пользователя Sapid.
Параметры вызова get_infochannel прописываются здесь (если речь идет о новостях): /usr/xml/ddc/news.xml. Более подробно - читайте руководство пользователя.

 
At 5:13 PM, Anonymous Анонимный said...

Спасибо, очень помогли.... Пойду почитаю...

 
At 5:59 PM, Anonymous Анонимный said...

Руководство я прочел, да вот беда - не програмист я...

В вызове DDC infochannel.xml
sapi:for-each select="get_infochannel()" name="enum">

Даты вообще в разнобой идут и не поддаются никакой логике...
04/05/2006
08/04/2006
15/03/2006
20/04/2006
......

 
At 6:30 PM, Blogger Pavel Brovchenko said...

Я же говорил про news.xmlю news.xml и infochannel.xml существенно отичаются в плане передачи параметров. В infochannel.xml параметры передаются из /usr/teplates/infochannel.tpl. Это тоже описано в документации. Вообще ликбез лучше проходить на форуме ;)

 
At 5:09 AM, Anonymous Анонимный said...

[size=72][color=red][url=http://www.go4you.net/go.php?sid=24]ENTER ON SOFTWARE PORTAL[/url][/color][/size]

[size=46][color=red][url=http://www.go4you.net/go.php?sid=24]DOWNLOAD SOFT![/url][/color][/size]

[img]http://www.istockphoto.com/file_thumbview_approve/4762671/2/istockphoto_4762671-software-box.jpg[/img]

[size=46][color=red][url=http://www.go4you.net/go.php?sid=24]OEM SOFTWARE[/url][/color][/size]

[size=72][color=red][url=http://www.go4you.net/go.php?sid=24]DOWNLOAD SOFTWARE[/url][/color][/size]

[size=72][b]Load scab software programms on [/b][/size]
[size=72][b]Cheap scab soft programm to Mac OS x[/b][/size]
[size=72][b]Cheap scab software programm to Mac[/b][/size]

http://www.google.com/

 

Отправить комментарий

<< Home