Подводный камень в foreach($items as &$item). Описание структуры шаблона com_content Расположение стандартного шаблона материалов


Многие любят писать такие конструкции в том или ином виде, каждый сталкивался:
foreach ($items as &$item) { $item += 2; }
Но не многие подозревают о том, какая опасность тут скрывается.
Рассмотрим пример.

Вася Пупкин взял массив, прошелся по нему, увеличив на два все элементы:
$items = array("a" => 10, "b" => 20, "c" => 30,); foreach ($items as &$item) { $item += 2; } print_r($items);
Посмотрел дамп, увидел что задача решена, и ушел довольный:
Array ([a] => 12 [b] => 22 [c] => 32)
Спустя некоторое время, Петрович решил дополнить этот участок кода другим перебором, дописав ниже:
$newitems = array("a" => 10, "b" => 20, "c" => 30,); foreach ($newitems as $key=>$item) { $newitems[$key] += 5; } print_r($newitems);
Посмотрел, что его задача тоже решена, и с чувством выполненного долга закрыл файл:
Array ([a] => 15 [b] => 25 [c] => 35)
Спустя какое-то время, стали вылезать необъяснимые баги. Почему?
Сделаем в конце кода var_dump($items):
array(3) { ["a"]=> int(12) ["b"]=> int(22) ["c"]=> &int(30) }
30! Вася Пупкин клянётся, что проверял. Почему было 32, а после кода Петровича 30?

Причина кроется в амперсанде. Он сообщает, что на отмеченные данные ссылается кто-то ещё. Уходя, Вася не подтёр за собой временную переменную, которую использовал для перебора ($item). Переменная использовалась с разрешением на изменение источника ("&"), которое также называют «присваиванием по ссылке». Он был уверен, что переменная будет использоваться только внутри цикла. Петрович, используя переменную с таким же именем, в ходе своего перебора, менял её значение, и каждый раз менялось то место, где эта переменная хранилась. А хранилась она там же, где последний элемент массива Пупкина.

Конечно, в случай в статье утрирован. На практике такие связи могут быть очень сложными, особенно если проект недорогой, и в нём участвуют недостаточно опытные и разрозненные веб-разработчики.

Как можно с этим оброться?

  • Уничтожать временные переменные после использования, особенно если они имеют какие-то связи с используемыми данными:
    foreach ($items as &$item) $item += 2; unset($item);
  • Быть осторожнее с переменными, которые уже кем-то использовались.
  • Инкапсулировать свои действия в отдельные функции, методы или пространства имён.
  • Использовать var_dump, вместо print_r, и обращать внимание на амперсанд. Чтобы дампить в файл, а не в браузер, альтернативой print_r($var,true) будет такая конструкция:
    function dump() { ob_start(); foreach(func_get_args() as $var) var_dump($var); return ob_get_clean(); }
В заключение скажу, что баги, связанные со ссылками, могут быть не только в foreach. И все они когда-то обсуждались. Однако, этот случай, судя по моему опыту, так распространён на практике, что заслуживает отдельного внимания.

Сколько бы мы не использовали PHP, всё равно всплывают некоторые функции, о которых мы даже не слышали. Некоторые из них были бы нам очень полезны. Я создал небольшой список полезных функций, которые должны быть в арсенале каждого PHP программиста.

1. Создание функций с переменным числом аргументов

Скорее всего, вы уже знаете, что PHP позволяет нам создавать функции с необязательными аргументами. Сейчас я покажу функцию, в которой число аргументов может меняться от случая к случаю.

Но для начала, вспомним как мы создаём функции обычным образом:

// функция с двумя необязательными параметрами function foo($arg1 = "", $arg2 = "") { echo "arg1: $arg1\n"; echo "arg2: $arg2\n"; } foo("hello","world"); /* выведет: arg1: hello arg2: world */ foo(); /* выведет: arg1: arg2: */

Теперь посмотрим на то, как можно написать функцию с неограниченным количеством аргументов. Для этого будет использовать метод func_get_args() :

// не указываем аргументы function foo() { // возвращает массив, переданных аргументов $args = func_get_args(); foreach ($args as $k => $v) { echo "arg".($k+1).": $v\n"; } } foo(); /* ничего не выведет */ foo("hello"); /* выведет arg1: hello */ foo("hello", "world", "again"); /* выведет arg1: hello arg2: world arg3: again */

2. Используем Glob() для поиска файлов

Часто названия функций говорят сами за себя. Такого нельзя сказать о функции glob() .

Если не вдаваться в подробности, её функциональность схожа с методом scandir() . Она позволяет найти необходимый файл по шаблону:

// найти все php файлы $files = glob("*.php"); print_r($files); /* выведет: Array ( => phptest.php => pi.php => post_output.php => test.php) */

Для нахождения файлов нескольких типов надо писать так:

// найти все php и txt файлы $files = glob("*.{php,txt}", GLOB_BRACE); print_r($files); /* на выходе: Array ( => phptest.php => pi.php => post_output.php => test.php => log.txt => test.txt) */

Так же можно в шаблоне указать путь:

$files = glob("../images/a*.jpg"); print_r($files); /* на выходе: Array ( => ../images/apple.jpg => ../images/art.jpg) */

Для того чтобы получить полный путь к документу используйте метод realpath() :

$files = glob("../images/a*.jpg"); // Применить функцию "realpath" к каждому элементу массива $files = array_map("realpath",$files); print_r($files); /* выведет: Array ( => C:\wamp\www\images\apple.jpg => C:\wamp\www\images\art.jpg) */

3. Информация об используемой памяти

Если вы будете отслеживать количество памяти, которое съедается на работу ваших скриптов то, наверное, чаще будете их оптимизировать.

В PHP существует мощный инструмент отслеживания используемой памяти. В разных частях скрипта нагрузки могут быть разные. Для того чтобы получить значение используемой памяти в данный момент, нам следует использовать метод memory_get_usage() . Для фиксации максимального количества используемой памяти используем memory_get_peak_usage()

Echo "Initial: ".memory_get_usage()." bytes \n"; /* Initial: 361400 bytes */ // дадим небольшую нагрузку for ($i = 0; $i < 100000; $i++) { $array = md5($i); } // и ещё for ($i = 0; $i < 100000; $i++) { unset($array[$i]); } echo "Final: ".memory_get_usage()." bytes \n"; /* Final: 885912 bytes */ echo "Peak: ".memory_get_peak_usage()." bytes \n"; /* Peak: 13687072 bytes */

4. Информация о процессоре

Для этого необходимо использовать метод getrusage() . Но учтите, что на Windows эта функция работать не будет.

Print_r(getrusage()); /* prints Array ( => 0 => 0 => 2 => 3 => 12692 => 764 => 3864 => 94 => 0 => 1 => 67 => 4 => 0 => 0 => 0 => 6269 => 0) */

Картина, изложенная выше, будет понятно тем, у кого есть опыт в системном администрировании. Для всех остальных предлагаем расшифровку:

  • ru_oublock: количество операций блочной записи
  • ru_inblock: количество операций блочного чтения
  • ru_msgsnd: количество отправленных сообщений
  • ru_msgrcv: количество принятых сообщений
  • ru_maxrss: максимальный размер невыгружаемого набора
  • ru_ixrss: общий объем разделяемой памяти
  • ru_idrss: общий объем неразделяемых данных
  • ru_minflt: количество используемых страниц памяти
  • ru_majflt: количество ошибок отсутствия страниц
  • ru_nsignals: количество принятых сигналов
  • ru_nvcsw: количество переключений контекста процессом
  • ru_nivcsw: количество принудительных переключений контекста
  • ru_nswap: количество обращений к диску при подкачке страниц
  • ru_utime.tv_usec: время работы в пользовательском режиме (микросекунды)
  • ru_utime.tv_sec: время работы в пользовательском режиме (секунды)
  • ru_stime.tv_usec: время работы в привилегированном режиме (микросекунды)
  • ru_stime.tv_sec: время работы в привилегированном режиме (секунды)

Для того чтобы узнать какие ресурсы вашего процессора используются скриптом, вам необходимо значение ‘user time’ (время работы в пользовательском режиме) и ’system time’ (время работы в привилегированном режиме). Вы можете получить результат как в секундах, так и в микросекундах. Для того чтобы превратить общее количество секунд в десятичное число, вам необходимо разделить значение микросекунд на 1 миллион и добавить к значению секунд.

Запутанно как-то. Вот пример:

// отдыхаем 3 секунды sleep(3); $data = getrusage(); echo "User time: ". ($data["ru_utime.tv_sec"] + $data["ru_utime.tv_usec"] / 1000000); echo "System time: ". ($data["ru_stime.tv_sec"] + $data["ru_stime.tv_usec"] / 1000000); /* выводит User time: 0.011552 System time: 0 */

Хотя выполнение скрипта заняло около 3-х секунд, процессор не был сильно нагружен. Дело в том, что при вызове (sleep) скрипт практически не потребляет ресурсов процессора. Вообще существует множество задач, которые занимают значительное время, но при этом не используют процессор. К примеру, ожидание операций связанных с диском. Так что вы не всегда используете процессорное время в своих скриптах.

Вот ещё пример:

// пройтись 10 миллионов раз for($i=0;$i hello => 42 => Array ( => 1 => two) => apple) */

Вот так вот работают эти функции. Однако из-за бурного роста популярности JSON, в PHP 5.2 были добавлены 2 метода json_encode() и json_decode(). Их работа схожа с serialize():

// сложные массив $myvar = array("hello", 42, array(1,"two"), "apple"); // конвертируем в строку $string = json_encode($myvar); echo $string; /* выведет ["hello",42,,"apple"] */ // восстанавливаем исходное значение $newvar = json_decode($string); print_r($newvar); /* prints Array ( => hello => 42 => Array ( => 1 => two) => apple) */

Этот вариант более компактный и совместимый с другими языками, такими как JavaScript. Однако при работе с очень навороченными объектами может возникнуть потеря данных.

8. Сжатие строк

Кода мы говорим о сжатии, то на ум сразу же приходят архивные файлы в формате ZIP. PHP предоставляет возможность сжатия длинных строк без всяких файлов.

В следующем примере продемонстрируем работу функций gzcompress() и gzuncompress() :

$string = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut elit id mi ultricies adipiscing. Nulla facilisi. Praesent pulvinar, sapien vel feugiat vestibulum, nulla dui pretium orci, non ultricies elit lacus quis ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam pretium ullamcorper urna quis iaculis. Etiam ac massa sed turpis tempor luctus. Curabitur sed nibh eu elit mollis congue. Praesent ipsum diam, consectetur vitae ornare a, aliquam a nunc. In id magna pellentesque tellus posuere adipiscing. Sed non mi metus, at lacinia augue. Sed magna nisi, ornare in mollis in, mollis sed nunc. Etiam at justo in leo congue mollis. Nullam in neque eget metus hendrerit scelerisque eu non enim. Ut malesuada lacus eu nulla bibendum id euismod urna sodales. "; $compressed = gzcompress($string); echo "Original size: ". strlen($string)."\n"; /* выведет Original size: 800 */ echo "Compressed size: ". strlen($compressed)."\n"; /* выведет Compressed size: 418 */ // возвращаем $original = gzuncompress($compressed);

В наших силах уменьшить объём текста на 50%. В этих же целях можно использовать методы gzencode() и gzdecode(), которые используют другой алгоритм сжатия.

9. Выполнить перед завершением

В PHP существует функция register_shutdown_function() , которая позволит вам выполнить какой-то код перед завершением работы скрипта.

Допустим, вы хотите узнать какую-то информацию… Время работы скрипта:

// получаем время начала $start_time = microtime(true); // какие-то операции // ... // выводим время работы echo "execution took: ". (microtime(true) - $start_time). " seconds.";

На первый взгляд это может показаться тривиальной задачей. Для этих целей, вы можете поместить код в конце файла. Однако если перед этим где-то сработает функция exit(), этот код никогда не сработает. Так же, он не сработает если на странице будет ошибка или пользователь прервёт загрузку страницы (нажав на соответствующую кнопку в своём браузере);

При использовании метода register_shutdown_function() код выполнится в любом случае:

$start_time = microtime(true); register_shutdown_function("my_shutdown"); function my_shutdown() { global $start_time; echo "execution took: ". (microtime(true) - $start_time). " seconds."; }

Вывод

PHP это целая планета, которая не перестаёт нас удивлять своим содержимым. А что думаете вы о данных функциях?

См. невольно... Словарь русских синонимов и сходных по смыслу выражений. под. ред. Н. Абрамова, М.: Русские словари, 1999. безотчетно чутьем, сам не сознавая, стихийно, панически, инстинктивно, сам того не сознавая, не отдавая себе отчета,… … Словарь синонимов

Безотчетно, инстинктивно, машинально, стихийно, слепо. См … Словарь синонимов

Непроизвольно, безотчетно, бессознательно, инстинктивно, машинально, механически, слепо, стихийно; нечаянно, неумышленно; волей неволей, хочешь не хочешь (volens nolens), по необходимости Это ему пришлось сделать по не зависящим от него… … Словарь синонимов

Слепо, подсознательно, нутром, сам того не сознавая, сам не сознавая, стихийно, безотчетно, не отдавая себе отчета, бессознательно, механически, несознанно, несознательно, интуитивно, неосознаваемо, шестым чувством, инстинктивно Словарь русских… … Словарь синонимов

См. невольно... Словарь русских синонимов и сходных по смыслу выражений. под. ред. Н. Абрамова, М.: Русские словари, 1999. слепо бессознательно, невольно; неотчетливо, безрассудно, безотчетно, стихийно, инстинктивно, рабски, неосознанно, неясно,… … Словарь синонимов

Нареч. к безотчетный. [Мать] хотела повернуть назад, но безотчетно снова пошла вперед. М. Горький, Мать. [Иудушка] умолил доброго друга маменьку управлять его имением безотчетно. Салтыков Щедрин, Господа Головлевы … Малый академический словарь

БЕЗОТЧЁТНЫЙ, безотчетная, безотчетное; (кратк. мужск. не употр.) безотчетна, безотчетно. 1. Не подчиняющийся никакому контролю, не обязанный отчитываться. Он безотчетно (нареч.) распоряжался в лавке. 2. Не зависящий от разумных соображений,… … Толковый словарь Ушакова

- (греч.). Лицо, которому доверено торговать безотчетно, за счет другого лица. Словарь иностранных слов, вошедших в состав русского языка. Чудинов А.Н., 1910. АНАГАЛИСТ Лицо, которому доверено торговать за счет другого лица безотчетно. Объяснение… … Словарь иностранных слов русского языка

Безотчетно, бессознательно, механично, непроизвольно, автоматично, машинально, автоматом, механически, автопилотом Словарь русских синонимов. автоматически см. машинально Словарь синонимов русского языка. Практический справочник. М.: Русск … Словарь синонимов

См. невольно... Словарь русских синонимов и сходных по смыслу выражений. под. ред. Н. Абрамова, М.: Русские словари, 1999. инстинктивно бессознательно, невольно; непроизвольно, неосознанно, нутром, спонтанно, стихийно, несознательно, слепо,… … Словарь синонимов

Книги
  • Путешествие по Чехословакии , Й. Марко , М. Петерка , Прага, 1959 год. Артия. С множеством фотоиллюстраций. Издательский переплет. Сохранность хорошая. Очарованный странник любой страны света, углубившись в эту прекрасную книгу, сможет… Категория: Записки путешественников, мемуары, исследования Издатель: Артия ,
  • Доска, или Встречи на Сенной , Геннадий Григорьев , Сергей Носов , Есть в Петербурге места просто фантасмогенные. К ним относится Сенная площадь. "Сенная - колыбель фантасмагорий" . Авторы, похоже, сами удивлены тем, что произошло с ними на Сенной. Да и… Категория: Классическая и современная проза Серия: Петербургские лики нашего времени Издатель:

Many fatal and recoverable fatal errors have been converted to exceptions in PHP 7. These error exceptions inherit from the Error class, which itself implements the Throwable interface (the new base interface all exceptions inherit).

This means that custom error handlers may no longer be triggered because exceptions may be thrown instead (causing new fatal errors for uncaught Error exceptions).

A fuller description of how errors operate in PHP 7 can be found on the PHP 7 errors page . This migration guide will merely enumerate the changes that affect backward compatibility.

Internal constructors always throw exceptions on failure

Previously, some internal classes would return NULL or an unusable object when the constructor failed. All internal classes will now throw an Exception in this case in the same way that user classes already had to.

E_STRICT notices severity changes

All of the E_STRICT notices have been reclassified to other levels. E_STRICT constant is retained, so calls like error_reporting(E_ALL|E_STRICT) will not cause an error.

E_STRICT notices severity changes Situation New level/behaviour
Indexing by a resource E_NOTICE
Abstract static methods
"Redefining" a constructor Notice removed, triggers no error
Signature mismatch during inheritance E_WARNING
Same (compatible) property in two used traits Notice removed, triggers no error
Accessing static property non-statically E_NOTICE
Only variables should be assigned by reference E_NOTICE
Only variables should be passed by reference E_NOTICE
Calling non-static methods statically E_DEPRECATED
Changes to variable handling

PHP 7 now uses an abstract syntax tree when parsing source files. This has permitted many improvements to the language which were previously impossible due to limitations in the parser used in earlier versions of PHP, but has resulted in the removal of a few special cases for consistency reasons, which has resulted in backward compatibility breaks. These cases are detailed in this section.

Changes to the handling of indirect variables, properties, and methods

Indirect access to variables, properties, and methods will now be evaluated strictly in left-to-right order, as opposed to the previous mix of special cases. The table below shows how the order of evaluation has changed.

Old and new evaluation of indirect expressions Expression PHP 5 interpretation PHP 7 interpretation
$$foo["bar"]["baz"] ${$foo["bar"]["baz"]} ($$foo)["bar"]["baz"]
$foo->$bar["baz"] $foo->{$bar["baz"]} ($foo->$bar)["baz"]
$foo->$bar["baz"]() $foo->{$bar["baz"]}() ($foo->$bar)["baz"]()
Foo::$bar["baz"]() Foo::{$bar["baz"]}() (Foo::$bar)["baz"]()

Code that used the old right-to-left evaluation order must be rewritten to explicitly use that evaluation order with curly braces (see the above middle column). This will make the code both forwards compatible with PHP 7.x and backwards compatible with PHP 5.x.

Fatal error: Uncaught ArithmeticError: Bit shift by negative number in /tmp/test.php:2 Stack trace: #0 {main} thrown in /tmp/test.php on line 2

Out of range bitshifts

Bitwise shifts (in either direction) beyond the bit width of an integer will always result in 0. Previously, the behaviour of such shifts was architecture dependent.

Changes to Division By Zero

Previously, when 0 was used as the divisor for either the divide (/) or modulus (%) operators, an E_WARNING would be emitted and false would be returned. Now, the divide operator returns a float as either +INF, -INF, or NAN, as specified by IEEE 754. The modulus operator E_WARNING has been removed and will throw a DivisionByZeroError exception.

Output of the above example in PHP 5:

Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false) Warning: Division by zero in %s on line %d bool(false)

Output of the above example in PHP 7:

Warning: Division by zero in %s on line %d float(INF) Warning: Division by zero in %s on line %d float(NAN) PHP Fatal error: Uncaught DivisionByZeroError: Modulo by zero in %s line %d

\u{ may cause errors

Due to the addition of the new Unicode codepoint escape syntax , strings containing a literal \u{ followed by an invalid sequence will cause a fatal error. To avoid this, the leading backslash should be escaped.

Removed functions Removed INI directives xsl.security_prefs

The xsl.security_prefs directive has been removed. Instead, the XsltProcessor::setSecurityPrefs() method should be called to control the security preferences on a per-processor basis.

Other backward incompatible changes New objects cannot be assigned by reference

The result of the new statement can no longer be assigned to a variable by reference:

Output of the above example in PHP 5:

Deprecated: Assigning the return value of new by reference is deprecated in /tmp/test.php on line 3

Output of the above example in PHP 7:

Parse error: syntax error, unexpected "new" (T_NEW) in /tmp/test.php on line 3

Invalid class, interface and trait names

The following names cannot be used to name classes, interfaces or traits:

  • bool
  • int
  • float
  • string
  • NULL
  • TRUE
  • FALSE

Furthermore, the following names should not be used. Although they will not generate an error in PHP 7.0, they are reserved for future use and should be considered deprecated.

  • object
  • mixed
  • numeric
ASP and script PHP tags removed

Support for using ASP and script tags to delimit PHP code has been removed. The affected tags are:

Removed ASP and script tags Opening tag Closing tag
Calls from incompatible context removed

Previously deprecated in PHP 5.6 , static calls made to a non-static method with an incompatible context will now result in the called method having an undefined $this variable and a deprecation warning being issued.

Output of the above example in PHP 5.6:

Deprecated: Non-static method A::test() should not be called statically, assuming $this from incompatible context in /tmp/test.php on line 8 object(B)#1 (0) { }

Output of the above example in PHP 7:

Deprecated: Non-static method A::test() should not be called statically in /tmp/test.php on line 8 Notice: Undefined variable: this in /tmp/test.php on line 3 NULL

yield is now a right associative operator

The yield construct no longer requires parentheses, and has been changed to a right associative operator with precedence between print and => . This can result in changed behaviour:

Parentheses can be used to disambiguate those cases.

Functions cannot have multiple parameters with the same name

It is no longer possible to define two or more function parameters with the same name. For example, the following function will trigger an E_COMPILE_ERROR :

Functions inspecting arguments report the current parameter value

func_get_arg() , func_get_args() , debug_backtrace() and exception backtraces will no longer report the original value that was passed to a parameter, but will instead provide the current value (which might have been modified).

Output of the above example in PHP 5:

Output of the above example in PHP 7:

Switch statements cannot have multiple default blocks

It is no longer possible to define two or more default blocks in a switch statement. For example, the following switch statement will trigger an E_COMPILE_ERROR :

JSON extension replaced with JSOND

The JSON extension has been replaced with JSOND, causing three minor BC breaks. Firstly, a number must not end in a decimal point (i.e. 34. must be changed to either 34.0 or 34 ). Secondly, when using scientific notation, the e exponent must not immediately follow a decimal point (i.e. 3.e3 must be changed to either 3.0e3 or 3e3 ). Finally, an empty string is no longer considered valid JSON.

Internal function failure on overflow

Previously, internal functions would silently truncate numbers produced from float-to-integer coercions when the float was too large to represent as an integer. Now, an E_WARNING will be emitted and NULL will be returned.

Fixes to custom session handler return values

Any predicate functions implemented by custom session handlers that return either FALSE or -1 will be fatal errors. If any value from these functions other than a boolean, -1 , or 0 is returned, then it will fail and an E_WARNING will be emitted.

Sort order of equal elements

The internal sorting algorithm has been improved, what may result in different sort order of elements, which compare as equal, than before.

Don"t rely on the order of elements which compare as equal; it might change anytime.

Misplaced break and switch statements

break and continue statements outside of a loop or switch control structure are now detected at compile-time instead of run-time as before, and trigger an E_COMPILE_ERROR .

Занимаетесь созданием и продвижением сайта под управлением CMS Joomla и у Вас вдруг возникла необходимость переделать на свой вкус и лад оформление материала путем редактирования стандартных шаблонов компонента com_content ? Компонент отвечает за формирование контента. Давайте разберемся в структуре самого компонента.

Расположение стандартного шаблона материалов

Оригинальные файлы компонента com_content находятся в папке components\com_content\views\Представление\tmpl. Если файлы компонента скопировать в каталог \templates\Вами используемый шаблон\html\com_content\, то шаблон материалов будет браться из файлов этой папки.

Каталоги и файлы шаблона

В директории расположения шаблона находятся пять папок для формирования представлений.

папка archive

  • Папка шаблон вывода архива. В данной статье не рассматривается, редко кто им пользуется. Структура аналогична нижеописанным папкам;

папка article - Материал

папка frontpage - Главная страница

  • default.php Такой же принцип, как и у category\blog.php;
  • default_item.php Такой же принцип, как и у category\blog_item.php;
  • default_links.php Такой же принцип, как и у category\blog_links.php;

папка section - Раздел

  • blog.php Шаблон блога раздела. Такой же принцип, как и у category\blog.php;
  • blog_item.php Шаблон отдельного материала из блога раздела. Такой же принцип, как и у category\blog_item.php;
  • blog_links.php Шаблон представления ссылок под блогом раздела. Такой же принцип, как и у category\blog_links.php;
  • default.php Стандартный шаблон раздела. Отображает заголовок категории, ее описание, количество элементов. После клика на заголовок категории страница обрабатывается category\default.php;
Пример редактирования шаблона. Отображение количества просмотров материала.

Допустим, мы хотим вывести количество хитов отдельного материала из блога категории. Для этого редактируем шаблон category\blog_item.php. Код для вставки информации о хитах будет таким:

Теперь нужно найти в файле шаблона category\blog_item.php место, где этот код вставить. Например перед отображением даты последнего редактирования материала. Ищем строку:

И перед ней вставляем строку с кодом.

Пример вывода списка категорий в несколько колонок .