Глоссарий во views: сортировка по фамилии и вывод полного алфавита

Главные вкладки

Аватар пользователя esmer esmer 30 марта 2016 в 13:36

Глоссарий во views по полю title. В нем имя и фамилия. Выборка идет по первой букве. Допустим Celine Dion по букве С. Как сделать выборку по фамилии, т.е. по букве d в данном случае, не создавая дополнительные поля. Т.к. по полю title у меня идет формирование url. Создание дополнительного поля для фамилии как то не комильфо. Наверняка можно как то программно решить?

Ну и вопрос номер два. Как я понимаю в глоссарии нельзя вывести целиком алфавит, если нет по соответствующей букве материалов.

Я нашел код для template.php и он работает:

<?php  if ($variables['view']->name == 'artists' && $variables['view']->current_display == 'attachment') {
                    
// Get the current rows of letters for glossary.
                    
preg_match_all('/<a href="([^\s]+)(?:,.*)?">/'$variables['rows'], $matches);
                    foreach (
$matches as $match) {
                      foreach (
$match as $url) {
                        
// Basically breaking down the a href link into a letter.
                        
$check explode('/artists/'$url);
                        if (isset(
$check[1])) {
                          
$letters[] = substr($check[1], 0, -2);
                        }
                      }
                    }
                    
// Take the urls and check them against alphabet
                    
$alphas = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
                
$output =  '<a href="/artists/"></a>';
                foreach (
$alphas as $alpha) {
                  if (!
in_array($alpha$letters)) {
                    
$output .= '<span class="alphaPagerBig">' strtoupper($alpha) . '</span>';
                  }
                  else {
                    
$output .= '<span class="alphaPagerBig"><a href="/artists/' $alpha '">' strtoupper($alpha) . '</a></span>';
                  }
                }
                
$output .= '<span class="alphaPagerBig"><a href="/artists/">Все</a></span>';
                
$variables['rows'] = $output;
              }
                  }
?>

Но проблема по пункту 1 все портит.

Еще нашел регулярное выражение по выборке из фамилии

<?phppreg_match('~([^\s]+)(?:,.*)?$~',$node->title, $match);
    $node_field[0]['value'] = $match[0];?>

Но как соединить одно с другим не пойму....

3. Ну и третий вопрос. Рядом разместить русский алфавит и выборку по другому полю с русскими именем и фамилией.

Комментарии

Аватар пользователя sveta-konfeta sveta-konfeta 31 марта 2016 в 11:09

Если правильно поняла, по поводу программного решения - можно попробовать использовать критерий сортировки - Глобальный PHP (вытащить из title фамилию и сортировать).

Аватар пользователя esmer esmer 31 марта 2016 в 14:03

ООО!!! Спасибо ! Добавил explode(" ", $row1->title); но сортировка по прежнему по первому слову. Тут что-то надо добавить, чтобы после сепаратора "пробел" сортировка была по второму.

Аватар пользователя sveta-konfeta sveta-konfeta 31 марта 2016 в 14:53

esmer wrote:

Добавил explode(" ", $row1->title); но сортировка по прежнему по первому слову.

это поможет вам извлечь второе слово, а далее нужно вручную реализовать сортировку.
На примере:
$pizza = "кусок1 кусок2 кусок3 кусок4 кусок5 кусок6";
$pieces = explode(" ", $pizza);
echo $pieces[0]; // кусок1
echo $pieces[1]; // кусок2
т.е. вам надо сравнивать $pieces[1] двух соседних строк и в зависимости от этого менять или не менять строки местами.
(обратите внимание, около кода сортировки есть примечание: "The comparison code must return an integer less than, equal to, or greater than zero if the first row should respectively appear before, stay where it was compared to, or appear after the second row.")
esmer wrote:

А вообще это разве в сортировке надо указывать, а не в контекстном фильтре?


нет, контекстные фильтры - это ФИЛЬТРЫ.

Аватар пользователя esmer esmer 31 марта 2016 в 15:17

Explode как я понимаю разбивает строку через разделитель. А через что менять местами? И в данном случае ведь не echo нужно? Простите, я слаб на php)

Аватар пользователя sveta-konfeta sveta-konfeta 31 марта 2016 в 17:34

esmer wrote:

Explode как я понимаю разбивает строку через разделитель.


да, верно. echo не нужно, это для примера написала.
вам после сравнения надо возвращать разные значения:
число <=0 - если 1ая из двух сравниваемых строк должна появляться раньше 2ой или остаться на своем месте
число >0 - 1ая должна следовать за второй
Почитайте как коды сортировок пишутся:)

Аватар пользователя esmer esmer 31 марта 2016 в 18:48

Я нашел что-то типа такого

<?phplist($fname1, $lname1) = explode(' ', $row1->title , 2);
list($fname2, $lname2) = explode(' ', $row2->title , 2);
return(strcasecmp($lname1,$lname2));?>

но не срабатывает....

кстати я так и не понял что за row2 оно у меня тоже есть...

Аватар пользователя esmer esmer 1 апреля 2016 в 18:45

При коде выше дает ошибку Notice: Undefined offset: 1 в функции __lambda_func() (строка 1 в файле C:\OpenServer\domains\drupal77\sites\all\modules\views_php\plugins\views\views_php_handler_sort.inc(73) : runtime-created function)

Хотя dsm($row1-> title); выводит список title

Не пойму в чем тут дело. Help !!

Аватар пользователя esmer esmer 1 апреля 2016 в 19:27

Поправочка !!!!

Код работает!!!

<?php
list($fname1$lname1) = explode(' '$row1->title 2);
list(
$fname2$lname2) = explode(' '$row2->title 2);
return(
strcasecmp($lname1,$lname2));
?>

Сортирует по фамилии!!! Только у меня есть исполнители с одним именем, поэтому и ошибка. Подскажите, как написать условие что если title из одного слова то не надо делить строку и участвовать в сортировке наравне с фамилией.

Еще одна поправочка. а вот в attachement global php в сортировке не работает. Та же ошибка. Т.е. первые буквы по фамилии не подставляет в алфавит

Аватар пользователя esmer esmer 1 апреля 2016 в 20:44

Пытаюсь сделать проверку так на наличие второй строки:

<?php
list($fname1$lname1) = explode(' '$row1->title 2);
list(
$fname2$lname2) = explode(' '$row2->title 2);
if (empty(
$lname1) || ($lname2)) {
return(
strcasecmp($fname1,$fname2)); }
else {return(
strcasecmp($lname1,$lname2));}
?>

Ошибка.Notice: Undefined offset: 1 в функции __lambda_func() (строка 1 в файле C:\OpenServer\domains\drupal77\sites\all\modules\views_php\plugins\views\views_php_handler_sort.inc(73) : runtime-created function).

Аватар пользователя sveta-konfeta sveta-konfeta 2 апреля 2016 в 0:27

попробуйте проверять наличие второго слова в строке, и только в случае наличия использовать explode.
может быть как-то так.. Smile

if (empty($lname1) || ($lname2)) {
return(strcasecmp($fname1,$fname2)); }
if (!(empty($lname1) || ($lname2))) {
list($fname1, $lname1) = explode(' ', $row1->title , 2);
list($fname2, $lname2) = explode(' ', $row2->title , 2);
return(strcasecmp($lname1,$lname2));
}
Аватар пользователя esmer esmer 2 апреля 2016 в 2:45

Спасибо за ваш ответ. К сожалению выдает те же ошибки. В данном случае мне кажется если проверять сразу наличие второго слова в строке то не получается потому как переменные $lname1 и т.п. не присвоены (не назначены) подстрокам в строке. Т.е. сначала надо как то присвоить как мы делали list ($fname1, $lname1), а потом проверять на пустоту.

Аватар пользователя esmer esmer 2 апреля 2016 в 3:04

Поставил вот так:

<?php
list($fname1$lname1) = $row1->title;
list(
$fname2$lname2) = $row2->title;
if (empty(
$lname1) || ($lname2)) {
return(
strcasecmp($fname1,$fname2)); }
if (!(empty(
$lname1) || ($lname2))) {
list(
$fname1$lname1) = explode(' '$row1->title 2);
list(
$fname2$lname2) = explode(' '$row2->title 2);
return(
strcasecmp($lname1,$lname2));
}
?>

Ошибка пропала. Но сортирует неправильно, опять по первому слову сортировка

Аватар пользователя esmer esmer 2 апреля 2016 в 11:52

оо! Спасибо за ваш отклик ! Теперь сортирует правильно сортировка

Но выдает ошибку по первым двум строкам :

Notice: Undefined offset: 1 в функции __lambda_func() (строка 2 в файле C:\OpenServer\domains\drupal77\sites\all\modules\views_php\plugins\views\views_php_handler_sort.inc(73) : runtime-created function).
Notice: Undefined offset: 1 в функции __lambda_func() (строка 1 в файле C:\OpenServer\domains\drupal77\sites\all\modules\views_php\plugins\views\views_php_handler_sort.inc(73) : runtime-created function).

Т.е. как я понимаю мы сразу присваиваем через list две переменные и пытаемся разделить через explode, и даже в тех случаях где только одно слово и нет сепаратора " ".Поэтому возможно появляется ошибка что элемент пустой? Как этого избежать?

Аватар пользователя esmer esmer 2 апреля 2016 в 18:59

goodboy Это гениально !!! Оно работает и без ошибок !!! Спасибо !!!!! Вы Бог !!! sveta-konfeta, спасибо что на толкнули на эту идею с explode !

Для вывода полного алфавита в attachement я использую код в template.php, который отображен в старт посте. Подскажите, как к этому коду прикрутить эту проверку на второе слово (фамилию)? Сейчас он работает на первое слово и соотвественно активные буквы на первое слово имени в алфавите:

сортировка

Аватар пользователя esmer esmer 4 апреля 2016 в 11:11

Есть у кого идеи как проделать тоже самое с алфавитом, т.е. сортировку по фамилии ? Мне кажется это многим было бы полезно.

Аватар пользователя esmer esmer 5 апреля 2016 в 19:05

Как можно алфавит с сортировкой по первому слову сделать сортировку по второму? В этом коде для template.php по первой букве первого слова:

<?php  if ($variables['view']->name == 'artists' && $variables['view']->current_display == 'attachment') {
                    
// Get the current rows of letters for glossary.
                    
preg_match_all('/<a href="([^\s]+)(?:,.*)?">/'$variables['rows'], $matches);
                    foreach (
$matches as $match) {
                      foreach (
$match as $url) {
                        
// Basically breaking down the a href link into a letter.
                        
$check explode('/artists/'$url);
                        if (isset(
$check[1])) {
                          
$letters[] = substr($check[1], 0, -2);
                        }
                      }
                    }
                    
// Take the urls and check them against alphabet
                    
$alphas = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
                
$output =  '<a href="/artists/"></a>';
                foreach (
$alphas as $alpha) {
                  if (!
in_array($alpha$letters)) {
                    
$output .= '<span class="alphaPagerBig">' strtoupper($alpha) . '</span>';
                  }
                  else {
                    
$output .= '<span class="alphaPagerBig"><a href="/artists/' $alpha '">' strtoupper($alpha) . '</a></span>';
                  }
                }
                
$output .= '<span class="alphaPagerBig"><a href="/artists/">Все</a></span>';
                
$variables['rows'] = $output;
              }
                  }
?>

Этот код прекрасно сортирует по второму во views:

<?phplist($fname1, $lname1) = array_pad(explode(' ', $row1->title , 2),2,null);
list($fname2, $lname2) = array_pad(explode(' ', $row2->title , 2),2,null);
if (empty($lname1)) $lname1 = $row1->title;
if (empty($lname2)) $lname2 = $row2->title;
return(strcasecmp($lname1,$lname2));?>

Как их объединить? в первом коде поле title не подгружается, поэтому там разделять нечего получается. Как его модифицировать? Help ! I need somebody !

Аватар пользователя esmer esmer 16 апреля 2016 в 21:33

Друзья. Неужели никто не сталкивался с подобным? Ведь куча ресурсов массивами данных. Алфавит - один из лучших способов катологизации....