среда, 22 декабря 2010 г.

Взаимосвязанные меню в TYPO3

 
Довольно часто на сайтах система меню устроена таким образом, что сверху расположены основные разделы сайта, а сбоку его подразделы, как это показано на скриншоте ниже.




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

Это кусочек кода который отвечает за верхнюю строку меню. За это отвечает параметр - entryLevel = 0

tempmenu.TOP_MENU = HMENU
tempmenu.TOP_MENU.entryLevel = 0
# исключаем из меню некоторые страницы, например Карта сайта и все-такое...
tempmenu.TOP_MENU.excludeUidList = 44,163
tempmenu.TOP_MENU.1 = TMENU
tempmenu.TOP_MENU.1 {
noBlur = 1
ACT = 1
CUR = 1
}
tempmenu.TOP_MENU.1.NO {
allWrap = <span class="menu_left"> </span><span class="menu">|</span><span class="menu_right"> </span>
}
tempmenu.TOP_MENU.1.ACT {
allWrap = <span class="curmenu_left"> </span><span class="curmenu">|</span><span class="curmenu_right"> </span>
}
tempmenu.TOP_MENU.1.CUR {
allWrap = <span class="curmenu_left"> </span><span class="curmenu">|</span><span class="curmenu_right"> </span>
doNotLinkIt = 1
}

А это кусочек typoscript, который отвечает за генерацию бокового меню или меню подразделов (entryLevel = 1):

# Настройка левого меню
tempmenu.LEFT_MENU = HMENU
tempmenu.LEFT_MENU.entryLevel = 1
tempmenu.LEFT_MENU.wrap = <ul>|</ul>
# Настройка 1-го уровня левого меню
tempmenu.LEFT_MENU.1 = TMENU
tempmenu.LEFT_MENU.1 {
noBlur = 1
ACT = 1
CUR = 1
}
tempmenu.LEFT_MENU.1.NO {
allWrap = <li class="menu_v1_lev2">|</li>
}
tempmenu.LEFT_MENU.1.ACT {
allWrap = <li class="menu_v1_lev2 active">|</li>
}
tempmenu.LEFT_MENU.1.CUR {
allWrap = <li class="menu_v1_lev2 current"><span>|</span></li>
doNotLinkIt = 1
}
# Настройка 2-го уровня левого меню
tempmenu.LEFT_MENU.2 = TMENU
tempmenu.LEFT_MENU.2 {
noBlur = 1
ACT = 1
CUR = 1
}
tempmenu.LEFT_MENU.2.NO {
allWrap = <li class="menu_v1_lev3">|</li>
}
tempmenu.LEFT_MENU.2.ACT {
allWrap = <li class="menu_v1_lev3 active">|</li>
}
tempmenu.LEFT_MENU.2.CUR {
allWrap = <li class="menu_v1_lev3 current"><span>|</span></li>
doNotLinkIt = 1
}


Совет

Несмотря на то, что, по своей неопытности, я использовал в скриптах имя объекта - tempmenu, рекомендую делать красиво и не повторять моих прежних "ошибок".

Используйте в своих TypoScript либо lib объект, либо temp. Возможно Вы спросите - но какая разница между ними? В каких случаях нужно использовать один объект, а когда другой?

Дело в том, что объекты, которые хранятся внутри temp носят временный характер, и как следствие - не кэшируются, в отличии от объекта - lib. Это также означает, что Вы не сможете делать ссылку на объект temp или изменять его по ссылке.

Хочу привести наглядный пример. Допустим у нас есть объекты temp и lib:

temp.myTemp = TEXT
temp.myTemp.value = Это текст внутри temp!
lib.myLib = TEXT
lib.myLib.value = Это текст внутри lib!

Попытаемся вывести данный текст на страницу 3-мя различными способами...
# Вывод значений объектов
page.10 = COA
page.10 {
10 < temp.myTemp
10.wrap = <strong>Temp: </strong>|<br />
20 < lib.myLib
20.wrap = <strong>Lib: </strong>|<br />
wrap = <p>|</p>
}
# Вывод значений объектов по ссылке
page.20 = COA
page.20 {
10 =< temp.myTemp
10.wrap = <strong>Temp: </strong>|<br />
20 =< lib.myLib
20.wrap = <strong>Lib: </strong>|<br />
wrap = <p>|</p>
}
# Передача объекта lib по ссылке объекту temp
temp.myTemp =< lib.myLib
page.30 = COA
page.30 {
10 < temp.myTemp
10.wrap = <strong>Temp: </strong>|<br />
20 < lib.myLib
20.wrap = <strong>Lib: </strong>|<br />
}

Результатом работы данного скрипта будет следующий вывод:

Это текст внутри temp!
Это текст внутри lib!

Это текст внутри lib!

Это текст внутри temp!
Это текст внутри lib!

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

 
воскресенье, 19 декабря 2010 г.

4 способа создания страницы 404 (Page not found) в TYPO3

Как я уже писал в одной своей заметке (SEO и общие рекомендации), для сайта очень важно, чтобы при обращении к заведомо несуществующей странице, например http://www.domain.com/bla-bla-bla, сервер не выдавал страницу с кодом: HTTP/1.1 302 Found. Сайт необходимо настраивать так, чтобы при обращении к несуществующей странице веб-сервер возвращал страницу с кодом - Error 404 (Page not found).
В противном случае, некорректная обработка данного запроса может привести к неправильной индексации сайта поисковыми системами, вплоть до полного исключения сайта из индекса поисковой системы.

Как же настроить сайт на TYPO3 надлежащим образом?

Для решения данной задачи у TYPO3 имеется несколько различных способов:

1. Самый простой способ. В конфигурационном файле localconf.php установить параметр:
$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = true;
После этого, реакция системы на URL типа http://www.domain.com/kgfhted будет приводить к появлению страшного и непонятного для пользователя сообщению:


2. Более сложный подход. В конфигурационном файле localconf.php установить 2 параметра:
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling_statheader"] = 'HTTP/1.1 404 Not Found';
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling"] = "http://www.domain.com.ua/error404.html";
Где error404.html это такая же страница сайта, которая была создана с помощью админки Typo3. Например:


Второй параметр можно прописать и так, заменив алиас страницы, на её id:
$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/index.php?id=page_id';

Этот подход намного цивильнее, т.к. данная страница уже будет содержать более внятные и полезные комментарии, помогающие пользователю быстрее понять, что произошло и как из данной ситуации можно выйти. Вот, 11 советов о том, какой должна быть данная страница (а это перевод). Как вариант, она может выглядеть вот так:


3. Более продвинутый способ. Страницу 404 можно не создавать в BE, а генерировать с помощью php. Для этого в localconf.php нужно установить следующих 2 параметра:
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling_statheader"] = 'HTTP/1.1 404 Not Found';
$TYPO3_CONF_VARS["FE"]["pageNotFound_handling"] = 'USER_FUNCTION:fileadmin/pageNotFoundHandling.php:user_pageNotFound->pageNotFound';

Как видно из значения 2-го параметра, в директории fileadmin должен находиться файл -
pageNotFoundHandling.php (имя файла может быть произвольным), в нем должен быть определен класс - user_pageNotFound, который имеет метод - pageNotFound.
Примерное содержимое pageNotFoundHandling.php, может быть таковым:
<?php
class user_pageNotFound {

function pageNotFound($param,$ref) {

print "<html>\n<head>\n<title>404 Not found : Sitename</title>\n";


//print '<meta http-equiv="refresh" CONTENT="0;URL=/fileadmin/404-not-found.html">\n';

print "</head>\n<body>\n";

print "Запрашиваемая Вами страница не найдена!";
print "<!--

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

-->";

print "</body>\n</html>\n";

}

}
?>

Т.к. страница 404 должна быть размером более 512 байт, я добавил лишние комментарии - Lorem Ipsum...

4. Опять простой способ. TYPO3 можно настроить так, чтобы при возникновении ошибки 404 на сайте, веб-сервер возвращал пользователю статическую html-страничку. Для этого в localconf.php нужно установить 2 параметра:

$TYPO3_CONF_VARS["FE"]["pageNotFound_handling_statheader"] = 'HTTP/1.1 404 Not Found';
$TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = 'READFILE:fileadmin/404.html';

Как видно из примера, в директории fileadmin должен находиться файл 404.html, который и будет видеть пользователь. Напомню еще раз, его размер должен быть более 512 байт!

Обязательно проверьте настройки RealUrl, а то, иногда, можно сломать себе мозг от того, что ничего не работает, хотя все сделано правильно! Обычно, у меня настройки RealUrl находятся в  файлах typo3conf/realurl_conf.php или typo3conf/realurlconf.php. Убедитесь что параметр postVarSet_failureMode не имеет значение - redirect_goodUpperDir. Он должен быть пустым, т.е. postVarSet_failureMode=''.

Что же касается многоязычных сайтов, то для того, чтобы страница с 404-ошибкой была на соответствующем языке, необходимо параметр $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] в typo3conf/localconf.php менять примерно следующим образом:

if (substr($_SERVER['REQUEST_URI'], 0, 4) == '/en/' || $_GET['L'] == 1) {
   $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/en/error404.html';
} elseif (substr($_SERVER['REQUEST_URI'], 0, 4) == '/fr/' || $_GET['L'] == 2) {
   $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/fr/error404.html';
} else {
   $TYPO3_CONF_VARS['FE']['pageNotFound_handling'] = '/error404.html';
}

Начиная с 6-й версии TYPO3 конфигурационный файл системы стал называться LocalConfiguration.php, а также претерпел значительные изменения в формате данных. Для того, чтобы сделать страницу 404-й ошибки мультиязычной для данной версии, я использовал следующие настройки:

'FE' => array(
  ......
 'pageNotFound_handling_statheader' => 'HTTP/1.1 404 Not Found',
 'pageNotFound_handling' => (substr($_SERVER['REQUEST_URI'], 0, 5) == '/rus/' || $_GET['L'] == 1) ? '/rus/error404/' : '/error404/',
),

Ну вот и всё! Упомяну также, что данную задачу можно решить и настройками Apache. Просто почитайте о параметре ErrorDocument.
суббота, 11 декабря 2010 г.

Indexed Search или эпопея с InnoDB


Казалось бы, какая связь между Indexed Search и InnoDB? Но...

Переносил я тут недавно один свой TYPO3-сайт на новый хостинг... Как говорится, перенес один в один. Но все пошло не так гладко как казалось на первый взгляд - перестал работать поиск на сайте, организованный экстом - indexed_search.

Слёту я решил переустановить (uninstall+install), а затем и обновить версию indexed_search, но это не помогло.

Правильное направление поиска причин возникновения проблемы, задала такая вещь. Каждый раз, при проверке настроек экста - indexed_search в менеджере расширений, он предлагал мне сделать update некоторых своих таблиц. Причем, суть данного апдейта сводилась не к созданию отсутствующих таблиц или полей, а смене движка для некоторых таблиц на InnoDB. Ну тут и начался несколько пролонгированный и довольно "сексуальный" курс повышения квалификации в области MySQL.

У меня сразу возник вопрос, а поднят ли этот движок на моем хостинге. Зайдя на консоль мускула я набрал следующую команду:
mysql> show engines;
и увидел ответ:
InnoDB |DISABLED
набрал еще другую команду, которая подтвердила наличие трабл с InnoDB:
mysql> show engine innodb status;
ERROR 1235 (42000): Cannot call SHOW INNODB STATUS because skip-innodb is defined

Немного погуглив, я сделал следующее:
1. Остановил MySQL, с помощью команды: /etc/init.d/mysql stop
2. Переименовал 2 лог-файла - ib_logfile0 и ib_logfile1:
mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bak
mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bak
3. Запустил MySQL: /etc/init.d/mysql start. При запуске на консоли стали появляться довольно страшные сообщения:
101027 20:59:45 InnoDB: Error: page 513 log sequence number 0 972453278
InnoDB: is in the future! Current system log sequence number 0 544625838.
InnoDB: Your database may be corrupt or you may have copied the InnoDB
InnoDB: tablespace but not the InnoDB log files. See
InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html
InnoDB: for more information.

Хотя, когда я опять из консоли MySQL выполнил знакомую нам команду:
mysql> show engines;
то увидел более приятное сообщение:
MyISAM | DEFAULT
InnoDB | YES

Таким образом я оживил InnoDB на своем сервере, но моя база оставалась "паламатая".

Вылечил базу мускула я следующими действиями:
1. В конфигурационный файл MySQL - /etc/mysql/my.cnf добавил параметр, который блокирует все Insert и Update на сервере:
innodb_force_recovery = 4
(это позволяет нам, как бы, заморозить базу в исходном состоянии на какое-то время). Заодно можно запомнить или записать значение параметра datadir из my.cnf, указывающий на местонахождение файлов БД и которое будет нужно в дальнейшем.

Если вы не знаете где находится файл my.cnf, то воспользуйтесь командой: find / -name my.cnf.

2. Рестартовал MySQL:
/etc/init.d/mysql stop
/etc/init.d/mysql start

3. Дополнительной утилитой мускула сделал дамп своей базы данных:
mysqldump --force --compress --triggers --routines --create-options -uroot -pROOTPASSWORD --databases DATABASENAME > /usr/mydb.sql

4. В очередной раз остановил сервер MySQL:
/etc/init.d/mysql stop
есть также и другой способ остановки сервиса:
mysqladmin -uroot -pROOTPASSWORD shutdown

5. Нашел физическое местонахождение директории с файлами БД (можно с помощью find / -name DATABASENAME) и записал на листике её имя, имя ее собственника (owner) и сумму прав на неё (rwx------, или 700). Все это может показать команда ls -l

6. Удалил полностью эту директорию (а точнее переместил в другое место - береженого бог бережет, как говорится :):
rm -fdr /var/lib/mysql/DATABASENAME/
БУДЬТЕ ОЧЕНЬ ВНИМАТЕЛЬНЫ, НЕ ЗАХВАТИТЕ НИЧЕГО ЛИШНЕГО!!!

7. Тут же создал директорию с таким же именем и задал её овнера и права:
mkdir /var/lib/mysql/DATABASENAME/
chown -R mysql:mysql /var/lib/mysql/DATABASENAME/
chmod -R 700 /var/lib/mysql/DATABASENAME/

8. Специальной утилитой mysql_install_db создал новые таблицы привилегий MySQL:
/usr/local/bin/mysql_install_db
и на всякий случай повторил присвоение овнера и установку прав:
chown -R mysql:mysql /var/lib/mysql/DATABASENAME/
chmod -R 700 /var/lib/mysql/DATABASENAME/

9. Убрал параметр innodb_force_recovery из конфигурационного файла - my.cnf

10. Запустил mysql:
/etc/init.d/mysql start

11. Импортировал данные обратно в базу данных:
mysql -uroot --compress < /usr/mydb.sql

12. Напоследок, обновил таблицы привилегий mysql:
/usr/bin/mysqladmin -uroot flush-privileges

Ну, вот и всё парни, а точнее мужики если дочитали эту статью до конца. Вы не поверите, но indexed_search у меня заработал.
Неужели для indexed_search так важно иметь движок InnoDB для некоторых своих таблиц?
Чтобы ответить себе на этот вопрос у меня уже не оставалось ни времени, ни сил, ни большого желания.

P.S. Все пути к директориям, которые есть в данной статье, скорее всего у вас будут другими. Поэтому, если вам нужно выполнить какую-то утилиту или найти файл, то используйте команду find / -name file_or_dir_name, она действительно рулит.

 

О себе

Моя фотография
Вадим Гиркало
Фрилансер, веб-разработчик сайтов на базе бесплатной, мощнейшей и очень гибкой CMS системы - TYPO3.
Просмотреть профиль

Позвонить мне в Skype

TOP - 3