Вялый userinfo php. Принимая PHP всерьёз
Фильтры в Revolution позволяют манипулировать тем, как будут обрабатываться те или иные теги. Они позволяют вам изменять значения прямо внутри ваших шаблонов.
Фильтры ввода
В настоящее время фильтры ввода используются при подготовке к обработке фильтров вывода. Обычно они используются только внутри движка MODX.
Фильтры вывода
В Revolution фильтры вывода ведут себя так же, как и PHx в Evolution, только фильтры теперь встроены прямо в движок MODX. Синтаксис выглядит так:
[]
Фильтры могут применяться последовательно. Для этого напишите их подряд (слева направо):
[]
Также фильтры могут применяться для модификации вывода сниппетов. Фильтр нужно прописывать перед всеми параметрами (перед знаком вопроса):
[]
Модификаторы вывода
В таблице представлены некоторые модификаторы и примеры их использования. В примерах модификаторы применяются к плейсхолдерам, но вы должны помнить, что они могут применяться к любым тегам MODX. Убедитесь, что используемый тег выводит хоть что-то, что модификатор будет обрабатывать.
Условные модификаторы вывода
Модификатор | Описание | Пример использования |
---|---|---|
if, input | Передаёт произвольный текст на ввод, для следующего модификатора | [[*id:input=`[[+placeholder]]`:is=`1`:then=`Да`:else=`Нет`]] |
or | ИЛИ | [[+numbooks:is=`5`:or:is=`6`:then=`Здесь 5 или 6 книг`:else=`Не уверен, сколько книг`]] |
and | Объединение нескольких модификаторов связью И | [[+numbooks:gt=`5`:and:lt=`10`:then=`Здесь от 5 до 10 книг`:else=`Книг или меньше 5, или больше 10`]] |
isequalto, isequal, equalto, equals, is, eq | Сравнивает передаваемое значение с установленным. Если значения совпадают, выводится значение «then», если нет - «else» | [[+numbooks:isequalto=`5`:then=`Здесь 5 книг`:else=`Не уверен, сколько книг`]] |
notequalto, notequals, isnt, isnot, neq, ne | Сравнивает передаваемое значение с установленным. Если значения НЕ совпадают, выводится значение «then», если нет - «else» | [[+numbooks:notequalto=`5`:then=`Не уверен, сколько книг`:else=`Здесь 5 книг`]] |
greaterthanorequalto, equalorgreaterthen, ge, eg, isgte, gte | То же, только условие «Больше или равно» | [[+numbooks:gte=`5`:then=`Здесь 5 книг или больше`:else=`Здесь меньше пяти книг`]] |
isgreaterthan, greaterthan, isgt, gt | То же, только условие «Строго больше» | [[+numbooks:gt=`5`:then=`Здесь больше пяти книг`:else=`Здесь 5 книг или меньше`]] |
equaltoorlessthan, lessthanorequalto, el, le, islte, lte | То же, только условие «Меньше или равно» | [[+numbooks:lte=`5`:then=`Здесь 5 книг или меньше`:else=`Здесь больше пяти книг`]] |
islowerthan, islessthan, lowerthan, lessthan, islt, lt | То же, только условие «Строго меньше» | [[+numbooks:lte=`5`:then=`Здесь меньше пяти книг`:else=`Здесь 5 книг или больше`]] |
hide | Скрывает элемент, если условие выполняется | [[+numbooks:lt=`1`:hide]] |
show | Отображает элемент, если условие выполняется | [[+numbooks:gt=`0`:show]] |
then | Используется для составления условий | [[+numbooks:gt=`0`:then=`Книги в наличии!`]] |
else | Используется для составления условий (совместно с «then») | [[+numbooks:gt=`0`:then=`Книги в наличии!`:else=`Простите, но все продано.`]] |
memberof, ismember, mo | Проверяет, является ли пользователь членом указанной группы пользователей | [[!+modx.user.id:memberof=`Administrator`]] |
Модификаторы для работы со строками
Модификатор | Описание | Пример использования |
---|---|---|
cat | Добавляет значение после тега | [[+numbooks:cat=`книг`]] |
lcase, lowercase, strtolower | Переводит все буквы в нижний регистр | [[+title:lcase]] |
ucase, uppercase, strtoupper | Переводит все буквы в верхний регистр | [[+headline:ucase]] |
ucwords | Делает первую букву в словах заглавной | [[+title:ucwords]] |
ucfirst | Делает первую букву в строке заглавной | [[+name:ucfirst]] |
htmlent, htmlentities | Преобразует все символы в соответствющие HTML-сущности | [[+email:htmlent]] |
esc, escape | Безопасно экранирует символы, используя регулярные выражения и `str_replace()`. Также экранирует теги MODX. | [[+email:escape]] |
strip | Заменяет все переносы, табуляции и любое количество пробелов только одним пробелом | [[+textdocument:strip]] |
stripString | Вырезает из строки указанную подстроку | [[+name:stripString=`Mr.`]] |
replace | Производит замену подстрок | [[+pagetitle:replace=`Mr.==Mrs.`]] |
striptags, stripTags,notags,strip_tags | Вырезает все теги (можно указать разрешенные теги). Не используйте для обеспечения безопасности. | [[+code:strip_tags]] |
len,length, strlen | Выводит длину строки | [[+longstring:strlen]] |
reverse, strrev | Переворачивает строку символ за символом | [[+mirrortext:reverse]] |
wordwrap | Вставляет перенос строки после каждого n-ого символа (слова не разбиваются) | [[+bodytext:wordwrap=`80`]] |
wordwrapcut | Вставляет перенос строки после каждого n-ого символа, даже если этот символ будет внутри слова | [[+bodytext:wordwrapcut=`80`]] |
limit | Выводит определенное количество символов с начала строки (значение по умолчанию - 100) | [[+description:limit=`50`]] |
ellipsis | Добавляет многоточие и обрезает строку, если она длиннее, чем указанное количество символов (по умолчанию - 100) | [[+description:ellipsis=`50`]] |
tag | Экранирование. Отображает элемент так как он есть, без:tag. Для использования в документации | [[+showThis:tag]] |
add, increment, incr | Прибавляет указанное число (значение по умолчанию +1) | [[+downloads:incr]] [[+blackjack:add=`21`]] |
subtract, decrement, decr | Вычитает указанное число (значение по умолчанию -1) | [[+countdown:decr]] [[+moneys:subtract=`100`]] |
multiply, mpy | Умножает на указанное число (значение по умолчанию *2) | [[+trifecta:mpy=`3`]] |
divide,div | Делит на указанное число (значение по умолчанию /2) | [[+rating:div=`4`]] |
modulus,mod | Возвращает модуль числа (по умолчанию: %2, возвращает 0 или 1) | [[+number:mod]] |
ifempty,default,empty, isempty | Возращает значение модификатора, если значение тега пусто | [[+name:default=`anonymous`]] |
notempty, !empty, ifnotempty, isnotempty | Возращает значение модификатора, если значение тега не пусто | [[+name:notempty=`Hello [[+name]]!`]] |
nl2br | Заменяет символы новой строки \n на HTML-тег br | [[+textfile:nl2br]] |
date | Переводит таймстамп в текст, в соответствии с указанным форматом (формат даты) | [[+birthyear:date=`%Y`]] |
strtotime | Переводит дату в виде текста в UNIX таймстамп | [[+thetime:strtotime]] |
fuzzydate | Принимает таймстамп и возвращает дату в виде "Сегодня в 16:20 PM" | [[+createdon:fuzzydate]] |
ago | Возвращает число секунд, минут, недель или месяцев, прошедших с даты, указанной в теге. | [[+createdon:ago]] |
md5 | Создает MD5-хеш значения | [[+password:md5]] |
cdata | Оборачивает вывод тегами CDATA | [[+content:cdata]] |
userinfo | Возвращает запрашиваемое значение из профиля пользователя. Необходимо указывать ID пользователя | [[!+modx.user.id:userinfo=`username`]] |
isloggedin | Возвращает 1, если пользователь авторизован в текущем контексте | [[!+modx.user.id:isloggedin:is=`1`:then=`Yes`:else=`No`]] |
isnotloggedin | Возвращает 1, если пользователь не авторизован в текущем контексте | [[!+modx.user.id:isnotloggedin:is=`1`:then=`No`:else=`Yes`]] |
urlencode | Конвертирует значение как URL, то есть применяет PHP фнукцию `urlencode()` | [[+mystring:urlencode]] |
urldecode | Конвертирует значение как из URL, то есть применяет PHP фнукцию `urldecode()` | [[+myparam:urldecode]] |
Модификаторы для работы с пользователями нужно вызывать некэшированными, чтобы каждый юзер видел актуальные данные.
Использование модификаторов вывода совместно с параметрами
Если у тега есть параметры, то их необходимо прописывать сразу после модификатора:
[[!getResources:default=`К сожалению, ничего не найдено`? &tplFirst=`blogTpl` &parents=`2,3,4,8` &tvFilters=`blog_tags==%[[!tag:htmlent]]%` &includeTVs=`1` ]]
Создание пользовательского модификатора
Любой сниппет может использоваться как модификатор вывода. Для этого просто укажите имя сниппета вместо модификатора. К примеру, создадим сниппет [] , добавляющий к выводу определенное количество восклицательных знаков:
[[*pagetitle:makeExciting=`4`]]
Такой вызов тега передаст в сниппет makeExciting следующие параметры для обработки:
Параметр | Значение | Значение в примере |
---|
Ракета Союз, доставленная на поезде на пусковую площадку. Фото из общественного достояния NASA.
Добродетели PHP
PHP имеет несколько очень глубоких и, однозначно, верных особенностей.Первая, состояние . Каждый веб-запрос начинается с совершенно чистого листа. Его пространство имён и глобальные переменные не инициализированы, за исключением некоторых стандартных глобальных переменных, функций и классов, которые предоставляют примитивную функциональность и жизнеобеспечение. Начиная каждый запрос с известного состояния, мы получаем своего рода изоляцию от возможных ошибок; если запрос t сталкивается с неполадкой ПО и завершается с ошибкой, данный баг не оказывает никакого влияния на выполнение последующего запроса t+1. В действительности, конечно же, помимо программной кучи, состояние приложения находится и в других местах, и вполне возможно полностью испортить базу данных, memcache или файловую систему. Но PHP разделяет эту слабость со всеми мыслимыми средами, которые позволяют сохранять состояние. В то же время, разделение программных куч между запросами снижает цену большинства программных ошибок.
Вторая, параллелизм . Индивидуальный запрос работает в одном PHP потоке. На первый взгляд, это кажется глупым ограничением. Но так как наше приложение выполняется в контексте веб-сервера, мы имеет натуральный источник параллелизма: веб запросы. Просто отправляя асинхронные запросы самим себе, мы легко получаем параллелизм с изолированными состояниями и вызовами по копированию-восстановлению. На практике, это безопаснее и устойчивее к ошибкам, чем подход с блокировками и разделяемым состоянием, который используется в других языках общего назначения.
В заключении, тот факт, что PHP программы оперируют на уровне запросов, означает, что рабочий процесс программиста является быстрым и эффективным, и остаётся быстрым после изменения приложения. Множество языков продуктивной разработки претендуют на это, но если они не очищают своё состояние при каждом запросе, и основной поток событий разделяет программный уровень состояния между запросами, они почти всегда требуют некоторое время на запуск. Для типичного сервера приложений на Python"е, типичный цикл отладки будет выглядеть примерно как «подумать, отредактировать, перезапустить сервер, отправить несколько тестовых запросов». Даже если «перезапустить сервер» занимает всего несколько секунд из общего количества часов, это забирает большой срез из 15-30 секунд наших человеческих мозгов на необходимость удержания в голове самой ненужной части текущего состояния.
Я утверждаю, что разработка на PHP в стиле «подумать, отредактировать и перезагрузить страницу» делает разработчиков более продуктивными. В долгих и сложных циклах разработки проектов это даёт ещё больший прирост.
Доводы против PHP
Если всё это является правдой, почему же его так ненавидят ? Когда вы уберёте все красочные гиперболы в сторону, что основные жалобы о PHP кластере сведутся к следующим проблемам:
Чтобы не показаться нерефлективным апологетом PHP: всё это серьёзные проблемы, которые позволяют более вероятно создавать дефекты. Они являются явными ошибками (unforced errors). Здесь нет присущего компромисса между Хорошими Частями PHP и данными проблемами. Должна быть реализована возможность создать PHP, который разрешит данные недостатки, сохранив при этом все хорошие стороны.
HHVM и Hack
Этот преемник системы PHP зовётся HackHack - это такой язык программирования, который люди называют «постепенная система типов» для PHP. «Система типов» значит, что он позволяет программисту составлять автоматически проверяемые инварианты о данных, которые протекают через код: данная функция берёт строку или число и возвращает лист Fribbles, как например в Java или C++ или Haskell, или в любом другом статически типизированном языке, который вы выберете. «Постепенная» означает, что некоторые части вашей кодовой базы могут быть статически типизированными, в то время как другие её части могут всё ещё находится в беспорядочном, динамическом PHP. Возможность совмещать эти подходы позволяет постепенно мигрировать большие кодовые базы.
Вместо того чтобы разлить здесь тонны чернил в описании системы типов Hack и того, как она работает, просто поиграйтесь с ним . Я буду здесь, когда вы вернётесь.
Это аккуратная система, и она весьма амбициозна в том что она позволяет вам выразить. И наличие возможности постепенной миграции проекта на Hack, в случаях когда он разрастается сильнее, чем вы ожидали изначально, является уникальным преимуществом экосистемы PHP. Проверки типов Hack сохраняют рабочий процесс в стиле «думать, отредактировать, перезагрузить страницу», потому что они запускаются в фоне, постепенно обновляя модель кодовой базы, когда он видит модификации в файловой системе. Проект Hack предоставляет интеграции со всеми популярными редакторами и IDE, так что вы сможете увидеть обратную связь об ошибках типов уже тогда, когда завершите печатать код, также как в веб-демонстрации.
Давайте рассмотрим совокупность реальных рисков, которые создаёт PHP, в свете Hack:
Hack предоставляет возможность, которой не имеют другие популярные члены семьи MPDPL: возможность ввести систему типов уже после основной разработки, и только частично, в тех частях системы, где значение перевешивает цену.
HHVM
Hack изначально был разработан как часть виртуальной машины HipHop , или HHVM, виртуальной среды с открытым исходным кодом для PHP. HHVM предоставляет другую важную опцию для успешного проекта: возможность запустить ваш сайт быстрее и более экономно. Facebook- Перегрузка свойств классов
- Перегрузка методов
- Интерфейсы
Интерфейсы объектов позволяют программисту создавать код, который указывает, какие методы и свойства должен включать класс, без необходимости описывания их функционала.
Интерфейсы объявляются так же, как и обычные классы, но с использованием ключевого слова "interface "; тела методов интерфейсов должны быть пустыми. Для включения интерфейса в класс программист должен использовать ключевое слово "implements " и описать функционал методов, перечисленных во включаемом интерфейсе. Если это требуется, классы могут включать более одного интерфейса путём их перечисления через пробел.
Если класс включает какой-либо интерфейс и не описывает функционал всех методов этого интерфейса, выполнение кода с использованием такого класса завершится фатальной ошибкой, сообщающей, какие именно методы не были описаны. Пример интерфейса:
interface ITemplate
{
public function setVariable ($name , $var );
public function getHtml ($template );
}Class Template implements ITemplate
{
private $vars = array();Public function setVariable ($name , $var )
{
$this -> vars [ $name ] = $var ;
}Public function getHtml ($template )
{
foreach($this -> vars as $name => $value ) {
$template = str_replace ("{" . $name . "}" , $value , $template );
}Return $template ;
}
}
?> - Оператор instanceof
Поддержка проверки зависимости от других объектов. Функцией is_a(), известной из PHP 4, пользоваться теперь не рекомендуется.
if ($obj instance of Circle ) {
print "$obj is a Circle" ;
}
?> - Метод final
Ключевое слово final позволяет вам помечать методы, чтобы наследующий класс не мог перегрузить их. Разместив перед объявлениями методов или свойств класса ключевое слово final , вы можете предотвратить их переопределение в дочерних классах, например:
class BaseClass {
public function test () {
echo "Вызван метод BaseClass::test()\n" ;
}Final public function moreTesting () {
echo "Вызван метод BaseClass::moreTesting()\n" ;
}
}Class ChildClass extends BaseClass {
public function moreTesting () {
echo "Вызван метод ChildClass::moreTesting()\n" <<< НазадСодержание Вперед >>> Есть еще вопросы или что-то непонятно - добро пожаловать на наш
Обращения к свойствам объекта могут быть перегружены с использованием методов __call , __get и __set . Эти методы будут срабатывать только в том случае, если объект или наследуемый объект не содержат свойства, к которому осуществляется доступ. Синтаксис такой:
void __set (string имя, mixed значение)
Void __get (mixed имя)
С помощью этих методов обращения к свойствам класса могут быть перегружены с целью выполнения произвольного кода, описанного в классе. В аргументе имя передаётся имя свойства, к которому производится обращение. Аргумент значение метода __set() должен содержать значение, которое будет присвоено свойству класса с именем имя.
__get и __set :
class
Setter
{
public
$n
;
private
$x
= array("a"
=>
1
,
"b"
=>
2
,
"c"
=>
3
);
Function
__get
($nm
) {
print
"Читаем [$nm]\n"
;
If (isset($this
->
x
[
$nm
])) {
$r
=
$this
->
x
[
$nm
];
print
"Получили: $r\n"
;
return
$r
;
} else {
print
"Ничего!\n"
;
}
}
Function
__set
($nm
,
$val
) {
print
"Пишем $val в [$nm]\n"
;
If (isset($this
->
x
[
$nm
])) {
$this
->
x
[
$nm
] =
$val
;
print
"OK!\n"
;
} else {
print
"Всё плохо!\n"
;
}
}
}
$foo
= new
Setter
();
$foo
->
n
=
1
;
$foo
->
a
=
100
;
$foo
->
a
++;
$foo
->
z
++;
var_dump
($foo
);
?>
Результатом выполнения рассмотренного скрипта будет:
Пишем 100 в [a]
OK!
Читаем [a]
Получили: 100
Пишем 101 в [a]
OK!
Читаем [z]
Ничего!
Пишем 1 в [z]
Всё плохо!
object(Setter)#1 (2) {
["n"]=>
int(1)
["x:private"]=>
array(3) {
["a"]=>
int(101)
["b"]=>
int(2)
["c"]=>
int(3)
}
}
Вызовы методов могут быть перегружены с использованием методов __call , __get и __set . Эти методы будут срабатывать только в том случае, если объект или наследуемый объект не содержат метода, к которому осуществляется доступ. Синтаксис:
mixed __call (string имя, array аргументы)
С использованием этого метода, методы класса могут быть перегружены с целью выполнения произвольного кода, описанного в классе. В аргументе имя передаётся имя вызванного метода. Аргументы, которые были переданы методу при обращении, будут возвращены чере аргументы. Значение, возвращённое методом __call() , будет передано вызывающему оператору.
Пример перегрузки с использованием __call :
class
Caller
{
private
$x
= array(1
,
2
,
3
);
Function
__call
($m
,
$a
) {
print
"Вызван метод $m:\n"
;
var_dump
($a
);
return
$this
->
x
;
}
}
$foo
= new
Caller
();
$a
=
$foo
->
test
(1
,
"2"
,
3.4
,
true
);
var_dump
($a
);
?>
Результат выполнения рассмотренного примера:
Вызван метод test:
array(4) {
=>
int(1)
=>
string(1) "2"
=>
float(3.4)
=>
bool(true)
}
array(3) {
=>
int(1)
=>
int(2)
=>
int(3)
}