Постраничный листер средствами TS без PHP и доп. расширений
Задача: Реализовать постраничное перелистование табличных данных, с навигационными кнопками «вперед», «назад», используя только средства typoscript
Реализация: Посредством контент элементов CONTENT, TEXT, LOAD_REGISTER, так же будут использованы функции stdWrap, if, select
Основная проблема: Если кто пытался реализовать данную функцию с помощью CONTENT элемента, то каждый сталкивался с тем, что напрямую реализовать не возможно, так как в функции select нет динамической обработки через stdWrap значений begin и max, поэтому никак не возможно передать туда значения аргументов из строки запроса.
Решение основной проблемы: Заключается в реализации не большого хака, а именно SQL-инъекции на уровне TS-кода, сразу оговорюсь будьте предельно внимательны при использование данного подхода, так как вы будете работать напрямую с запросом к БД, обязательно перед тем как передавать значения, убедитесь в том, что вы проверили (отфильтровали) передаваемые данные.
Основная идея:
... table = tx_tslister_data select{ ... andWhere = 1=1 LIMIT {register:begin},{register:end} # andWhere.insertData = 1 ... } ...
Из всех параметров функции select, только 2 могут быть обработаны через stdWrap, я выбрал andWhere потому что он прибавляется к запросу позже чем pidInList, и так в результате у нас получился запрос:
SELECT * FROM tx_tslister_data WHERE tx_tslister_data.pid IN (5) AND 1=1 LIMIT 1,10 # AND tx_tslister_data.deleted=0 AND tx_tslister_data.hidden=0 Так бы он выполнялся если бы мы не использовали данный подход: SELECT * FROM tx_tslister_data WHERE tx_tslister_data.pid IN (5) AND tx_tslister_data.deleted=0 AND tx_tslister_data.hidden=0
Рабочий пример:
Страница с uid 5 используется для хранения записей таблицы, с uid 4 страница на которой находиться листер.
page = PAGE sql{ table = tx_tslister_data select{ pidInList = 5 andWhere = tx_tslister_data.deleted=0 AND tx_tslister_data.hidden=0 {register:sql_limitpart} # andWhere.insertData = 1 } } page.1 = LOAD_REGISTER page.1{ #кол-во элементов в списке листера sql_perpage.cObject = TEXT sql_perpage.cObject.value = 10 #Передаем значение и фильтруем значения номера страницы из запроса к серверу sql_page.cObject = TEXT sql_page.cObject.data = GPvar:page sql_page.cObject.intval = 1 #Расчет начала ограничения запроса sql_start.cObject = TEXT sql_start.prioriCalc = 1 sql_start.cObject{ if.isPositive.data = register:sql_page value = {register:sql_perpage}*({register:sql_page} - 1) insertData = 1 } #Расчет конечного ограничения запроса sql_limit.cObject = TEXT sql_limit.prioriCalc = 1 sql_limit.cObject{ value = ({register:sql_perpage}*({register:sql_page} - 1))+{register:sql_perpage} insertData = 1 } #Формируем LIMIT, эмуляция IF(...){...}ELSE{...} sql_limitpart.cObject = COA sql_limitpart.cObject{ 10 = COA 10{ #IF 'limit' > 0 if.isPositive.data = register:sql_limit #IF 'limit' && 'start' > 0 10 = TEXT 10{ if.isPositive.data = register:sql_start value = LIMIT {register:sql_start},{register:sql_limit} insertData = 1 } #ELSE 'start' == False 20 = TEXT 20{ if.isFalse.data = register:sql_start value = LIMIT {register:sql_limit} insertData = 1 } } #IF limit == False 20 = TEXT 20{ if.isFalse.data = register:sql_limit value = LIMIT 10 } } #Общее кол-во записей sql_total.cObject = TEXT sql_total.cObject.numRows{ table < sql.table select < sql.select } } #Страница листера page.20 = CONTENT page.20{ table < sql.table select < sql.select renderObj = COA renderObj{ wrap = <div style="border-top:1px solid #999;padding:3px;">|</div> 10 = TEXT 10.field = title 10.wrap = |</br> 20 = TEXT 20.field = body } } #Навигация по листеру page.30 = COA page.30{ 1 = LOAD_REGISTER 1{ #Определяем предыдущую страницу pager_prev.cObject = TEXT pager_prev.cObject{ value = {register:sql_page}-1 insertData = 1 } pager_prev.prioriCalc=1 #Определяем следующуя страницу pager_next.cObject = TEXT pager_next.cObject{ value = {register:sql_page}+1 insertData = 1 } pager_next.prioriCalc=1 } #Кнопка назад 10 = TEXT 10{ if.isPositive.data = register:sql_start value = < back typolink{ parameter = 4 additionalParams.cObject = TEXT additionalParams.cObject{ value = &page={register:pager_prev} insertData=1 } } } #Кнопка вперед 30 = TEXT 30{ if.value.data = register:sql_limit if.isGreaterThan.data = register:sql_total value = forward > typolink{ parameter = 4 additionalParams.cObject = TEXT additionalParams.cObject{ value = &page={register:pager_next} insertData=1 } } } }
P.S. и не забудьте создать табличку в БД, вот такого плана
-- -- Структура таблицы `tx_tslister_data` -- CREATE TABLE IF NOT EXISTS `tx_tslister_data` ( `uid` int(11) NOT NULL AUTO_INCREMENT, `pid` int(11) NOT NULL DEFAULT '0', `tstamp` int(11) NOT NULL DEFAULT '0', `crdate` int(11) NOT NULL DEFAULT '0', `cruser_id` int(11) NOT NULL DEFAULT '0', `deleted` tinyint(4) NOT NULL DEFAULT '0', `hidden` tinyint(4) NOT NULL DEFAULT '0', `title` tinytext NOT NULL, `body` text NOT NULL, PRIMARY KEY (`uid`), KEY `parent` (`pid`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=13 ; -- -- Дамп данных таблицы `tx_tslister_data` -- INSERT INTO `tx_tslister_data` (`uid`, `pid`, `tstamp`, `crdate`, `cruser_id`, `deleted`, `hidden`, `title`, `body`) VALUES (1, 5, 1266902311, 1266902311, 1, 0, 0, 'title - 1', 'body - 1'), (2, 5, 1266902321, 1266902321, 1, 0, 0, 'title - 2', 'body - 2'), (3, 5, 1266902333, 1266902333, 1, 0, 0, 'title - 3', 'body - 3'), (4, 5, 1266902361, 1266902361, 1, 0, 0, 'title - 3', 'body - 3'), (5, 5, 1266902361, 1266902361, 1, 0, 0, 'title - 2', 'body - 2'), (6, 5, 1266902361, 1266902361, 1, 0, 0, 'title - 1', 'body - 1'), (7, 5, 1266902365, 1266902365, 1, 0, 0, 'title - 3', 'body - 3'), (8, 5, 1266902365, 1266902365, 1, 0, 0, 'title - 2', 'body - 2'), (9, 5, 1266902365, 1266902365, 1, 0, 0, 'title - 1', 'body - 1'), (10, 5, 1266902369, 1266902369, 1, 0, 0, 'title - 3', 'body - 3'), (11, 5, 1266902369, 1266902369, 1, 0, 0, 'title - 2', 'body - 2'), (12, 5, 1266902369, 1266902369, 1, 0, 0, 'title - 1', 'body - 1');
Нехватает только увидеть результат этой реализации, на боевом сайте.