Forum Webscript.Ru
Программирование => PHP => Тема начата: Moe от 20 Октября 2009, 19:51:59
-
Здравствуйте. Есть массив с тегами в виде ссылок. Часть тегов имеет несколько типов повторяющихся элементов (Например, тег: "Сюжет — ГМПИ"). Я хочу на основе этих повторений раскидать теги по группам под соответствующие заголовки.
Вот так:
Сюжеты
Тег2, Тег4, Тег5...
Источники
Тег1, Тег3, Тег6...
foreach ($tags as $tagkey => $onetag) {
preg_match_all ("/(]>Источник.+<\\/a>$)|(]>Сюжет.+<\\/a>$)|(]>Текст.+<\\/a>$)/", $onetag, $matches, PREG_PATTERN_ORDER);
$done = preg_replace(\'"(Сюжет\\s—\\s)|(Текст\\s—\\s)|(Источник\\s—\\s)"\', \'\', $matches[1][0] .$matches[2][0] .$matches[3][0] ."\\n");
echo ($done);
}
Вызывая попеременно $matches, у меня получается эти группы выводить, но как приделать к ним заголовок так, чтобы не обходить массив по несколько раз для каждой группы — я не знаю. К тому же, скорее всего этих групп будет около 10. Подскажите, пожалуйста, разумное решение.
-
Живой пример массива $tags — в студию!
-
brainkiller
Речь идет о движке Wordpress и функции wp_tag_cloud. Перед этим кодом есть строка:
$tags = wp_tag_cloud(\'format=array&number=0&order=DESC&orderby=count\');
И данные там такого типа:
...
Сюжет — Тег1
Источник — Тег2
Сюжет — Тег3
Источник — Тег4
...
-
А не проще ли взять функцию wp_tag_cloud(), посмотреть, что там внутри и написать свою wp_custom_tag_cloud(), которая выдаст нужные данные в нужном формате — вместо того, чтобы парсить вывод существующей функции?
-
brainkiller
Я совсем не спец, но мне кажется, что даже создавая свою функцию мне все равно придется тем или иным способом сортировать точно такой же массив тегов. Ну или просто сортировать теги по наличию в них определенных элементов тем же preg_match_all. Или я ошибаюсь?
Ну а с текущим вариантом совсем тухло? Он умеет почти все, кроме как приставлять заголовки к группам тегов, а не к каждому тегу :)
Сейчас, если я напишу:
echo ("Сюжет ".$matches[1][0);
echo ("Текст ".$matches[2][0);
То ожидаемо получу: Сюжет Тег1 Сюжет Тег2 Сюжет Тег3 Текст Тег4 Текст Тег 5 Текст Тег6.
И вопрос в том, как эту проблему разрешить, не инициализируя для каждого шаблона обход всего массива? Вроде такого:
echo ("Сюжет");
foreach ($tags as $tagkey => $onetag) {
preg_match_all ("/(]>Сюжет.+$)", $onetag, $matches, PREG_PATTERN_ORDER);
$done = preg_replace(\'"(Сюжетs—s)"\', \'\', $matches[0][0]."\\n");
echo ($done);
}
echo ("Текст");
foreach ($tags as $tagkey => $onetag) {
...
-
Для иллюстрации: вот так выглядит функция wp_tag_cloud
function wp_tag_cloud( $args = \'\' ) {
$defaults = array(
\'smallest\' => 8, \'largest\' => 22, \'unit\' => \'pt\', \'number\' => 45,
\'format\' => \'flat\', \'orderby\' => \'name\', \'order\' => \'ASC\',
\'exclude\' => \'\', \'include\' => \'\', \'link\' => \'view\', \'taxonomy\' => \'post_tag\', \'echo\' => true
);
$args = wp_parse_args( $args, $defaults );
$tags = get_terms( $args[\'taxonomy\'], array_merge( $args, array( \'orderby\' => \'count\', \'order\' => \'DESC\' ) ) ); // Always query top tags
if ( empty( $tags ) )
return;
foreach ( $tags as $key => $tag ) {
if ( \'edit\' == $args[\'link\'] )
$link = get_edit_tag_link( $tag->term_id, $args[\'taxonomy\'] );
else
$link = get_term_link( intval($tag->term_id), $args[\'taxonomy\'] );
if ( is_wp_error( $link ) )
return false;
$tags[ $key ]->link = $link;
$tags[ $key ]->id = $tag->term_id;
}
$return = wp_generate_tag_cloud( $tags, $args ); // Here\'s where those top tags get sorted according to $args
$return = apply_filters( \'wp_tag_cloud\', $return, $args );
if ( \'array\' == $args[\'format\'] || empty($args[\'echo\']) )
return $return;
echo $return;
}
-
$done = preg_replace("(Сюжетs—s)|(Текстs—s)|(Источникs—s)", \'\', \'
Сюжет
\'. $matches[1][0] .\'Текст
\'. $matches[2][0] .\'Источник
\'.$matches[3][0] ."\\n");
Проверять лень. :)
-
brainkiller
К сожалению, та же беда :(
Сюжет Текст Источник Тег1 Сюжет Текст Источник Тег2 Сюжет Текст Источник Тег3...
-
Да, точно! Туплю.
$tags = array(
"Сюжет — Тег1
Источник — Тег2
Сюжет — Тег3
Текст — Тег4
Источник — Тег5"
);
foreach ($tags as $tagkey => $onetag) {
preg_match_all ("/(]+>Текст.+<\\/a>$)|(]+>Источник.+<\\/a>$)|(]+>Сюжет.+<\\/a>$)/m", $onetag, $matches, PREG_SET_ORDER);
$str1 = "Текст
"; $str2 = "Источник
"; $str3 = "Сюжет
";
$j = count($matches);
for($i = 0; $i < $j; $i++) {
$str1 .= @str_replace(\'Текст — \', \'\', $matches[$i][1])." ";
$str2 .= @str_replace(\'Источник — \', \'\', $matches[$i][2])." ";
$str3 .= @str_replace(\'Сюжет — \', \'\', $matches[$i][3])." ";
}
echo $str1, $str2, $str3;
}
Соответственно, первое, что в голову пришло, да на скорую руку набросал. Проверки переменных и прочий лоск давайте уж сами.
-
brainkiller
Хех, просто божественно, большое спасибо! :)
Я только убрал знак конца строки $.
preg_match_all ("/(]+>Текст.+<\\/a>)|(]+>Источник.+<\\/a>)|(]+>Сюжет.+<\\/a>)/m", $onetag, $matches, PREG_SET_ORDER);
Правда, тот массив, с которым я работаю какой-то неправильный и все равно ничего не получается. Видимо, я что-то недопонял с этим wp_tag_cloud, потому что при echo $i; в вашем случае выводит количество элементов в массиве, например, цифру 5, а в моем такую фигню 00001100011110001100011111111. Также в первом случае при echo $tags; выведет array, а у меня array array array... Что это может быть?
В любом случае, спасибо, буду разбираться.
-
Да вовсе не божественно: кабы не подавление ошибок перед оператором замены подстроки, Вас бы нотисами засыпало. :) Говорю же, причёсывать и причёсывать.
Смотрю, у Вас пробел вместо конца строки — надо полагать, пробелами разделены ссылки на тэги? А после последней ссылки пробел есть, или она не попадёт в $matches?
Сделайте print_r($tags) и посмотрите, что там: возможно регулярку снова переделать придётся.
-
brainkiller
Нет, пробела в шаблоне нет, почему-то автоматом при посте здесь на форуме там оказывается пробел. При echo $onetag; теги выводятся впритык друг к другу, следовательно, насколько я понимаю, пробела между
Если делать print_r($tags), то в вашем примере выводит:
Array([0] => Сюжет — Тег1
Источник — Тег2
Сюжет — Тег3
Текст — Тег4
Источник — Тег5
)
А в моем случае:
Array([0] => Сюжет — Тег1
[1] =>Источник — Тег2
[2] =>Сюжет — Тег3
[3] =>Текст — Тег4
[4] =>Источник — Тег5)
Array([0] => Сюжет — Тег1
[1] =>Источник — Тег2
[2] =>Сюжет — Тег3
[3] =>Текст — Тег4
[4] =>Источник — Тег5)
...
И так, видимо, до бесконечности.
-
А при print_r ($matches); совсем запутано:
Array
(
)
Array
(
)
Array
(
[0] => Array
(
[0] =>Сюжет — Тег1
[1] =>
[2] =>Сюжет — Тег1
)
)
Array (
[0] => Array
(
[0] =>Сюжет — Тег3
[1] =>
[2] =>Сюжет — Тег3
...
-
А в моем случае:
Ну так это в корне меняет дело! Я из Вашей реплики не понял, признаться, что там каждый тэг в отдельном элементе.
Исправить это просто при помощи implode(), но лучше всё же
$tags = array(
"Сюжет — Тег1",
"Источник — Тег2",
"Сюжет — Тег3",
"Текст — Тег4",
"Источник — Тег5"
);
$str1 = "Текст
"; $str2 = "Источник
"; $str3 = "Сюжет
";
$pat1 = \'Текст — \'; $pat2 = \'Источник — \'; $pat3 = \'Сюжет — \';
foreach($tags as $tag) {
if (strpos($tag, $pat1)) {
$str1 .= str_replace($pat1, \'\', $tag)." ";
}
if (strpos($tag, $pat2)) {
$str2 .= str_replace($pat2, \'\', $tag)." ";
}
if (strpos($tag, $pat3)) {
$str3 .= str_replace($pat3, \'\', $tag)." ";
}
}
echo $str1, $str2, $str3;
…и никаких регулярных выражений!
[OFF]А вопросы надо задавать максимально конкретно![/OFF]
-
brainkiller
Теперь все работает должным образом, еще раз большое спасибо!
[OFF]Я настоящий профан в этом деле, но на будущее постараюсь учесть все нюансы и буду формулировать вопрос корректнее :) [/OFF]
-
Первая настоящая тема за последний год :) а то и три
-
hanslinger
:) А в каком смысле?
-
В смысле что длинный разговор по делу и без тупака :)
-
hanslinger
Тогда понятно, приятно, что это так ))
-
Да. Прямо как в старые добрые времена. :)