Public Морозов и другие: антипаттерны в программировании. Использование ob_start при поддержке проектов на php Определение и применение

jQuery эффекты Определение и применение

jQuery метод .show() позволяет отобразить скрытые выбранные элементы. Для того, чтобы скрыть выбранные элементы вы можете воспользоваться методом .hide() .

Обращаю Ваше внимание, что когда метод .show() используется без параметров, то элемент отображается без анимации. Это эквивалентно * использованию метода .css() со следующим значением:

$(selector ).css("display ", "block ")

* - за исключением того, что значение свойства display сохраняется внутри jQuery и может позже быть восстановлено к первоначальному значению.

Если вы используете стили элемента с !important , то метод .show() не сможет отобразить элемент. В этом случае рекомендуется использовать такие методы как .addClass() , .removeClass() , .toggleClass() , или .attr() .

jQuery синтаксис: Синтаксис 1.0: $(selector ).show() // метод используется без параметров $(selector ).show(duration , complete ) duration - Number , или String complete - Function $(selector ).show({ options } ) // option: value (описание ниже) options - PlainObject Синтаксис 1.4.3: $(selector ).show(duration , easing , complete ) duration - Number , или String easing - String complete - Function Добавлен в версии jQuery 1.0 (синтаксис обновлен в версии 1.4) Значения параметров Параметр Описание
duration Строковое или числовое значение, которое определяет, как долго анимация будет продолжаться. Значение по умолчанию 400 (в миллисекундах). Строковые ключевые слова "fast" и "slow" соответствуют 200 и 600 миллисекундам соответственно (высокие значения указывают на медленную анимацию, а более низкие на быструю).
easing Ключевое слово (строка), которое опряеделяет кривую скорости для анимации (используется математическая функция - кубическая кривая Безье). Без использования внешних плагинов имеет только два значения - linear (эффект анимации с одинаковой скоростью от начала до конца) и swing (эффект анимации имеет медленный старт и медленное окончание, но скорость увеличивается в середине анимации). Значение по умолчанию swing .
complete Функция, которая будет выполнена после завершения анимации, она вызывается один раз для каждого соответствующего элемента. Внутри функции, переменная this ссылается на DOM элемент к которому применяется анимация.
options
  • duration (по умолчанию: 400 ).
    Тип: Number , или String .
    Строковое или числовое значение, которое определяет, как долго анимация будет продолжаться (смотри выше).
  • easing (по умолчанию: swing ).
    Тип: String .
    Ключевое слово (строка), которое определяет кривую скорости для анимации (смотри выше).
  • queue (по умолчанию: true ).
    Тип: Boolean , или String .
    Логическое значение, которое указывает следует ли размещать анимацию в очереди эффектов. Если указано false , то анимация начнется сразу же. С версии jQuery 1.7 опция queue также может принимать строку, в этом случае анимация будет добавлена к очереди, представленной этой строкой. Когда используется пользовательское имя очереди анимации, то она не запускается автоматически, вы должны при этом использовать метод .dequeue("имя очереди ") , чтобы запустить её.
  • specialEasing .
    Тип: PlainObject .
    Объект, содержащий одно или несколько свойств CSS, определенных параметром свойства и соответствующие им функции замедления. Добавлено в версии 1.4 .
  • step .
    Тип: Function (Number now, Tween tween).
    Функция вызывается для каждого анимируемого свойства каждого анимированного элемента. Эта функция дает возможность изменять Tween Object, чтобы изменить значение свойства, прежде чем оно будет установлено.
  • progress .
    Тип: Function .
    Функция, которая будет вызываться после каждого шага анимации, только один раз для каждого анимированного элемента, независимо от количества анимированных свойств. Добавлено в версии 1.8 .
  • complete .
    Тип: Function .
    Функция (callback ), которая будет выполнена после завершения анимации, она вызывается один раз для каждого соответствующего элемента (смотри выше).
  • start .
    Тип: Function (Promise Object animation).
    Функция, вызывается, когда анимация элемента начинается. Добавлено в версии 1.8 .
  • done .
    Тип: Function (Promise Object animation, Boolean jumpedToEnd).
    Функция вызывается, когда анимация элемента завершается. Добавлено в версии 1.8 .
  • fail .
    Тип: Function (Promise Object animation, Boolean jumpedToEnd).
    Функция вызывается, когда анимацию элемента не удается завершить. Добавлено в версии 1.8 .
  • always .
    Тип: Function (Promise Object animation, Boolean jumpedToEnd).
    Функция вызывается, когда анимация элемента завершается или останавливается незавершенной. Добавлено в версии 1.8 .
Пример использования Использование jQuery методов.hide() и.show() (без параметров) $("p ").hide(); // скрывыаем все элементы

$("p ").show(); // отображаем все элементы

} ); } ); Скрыть Показать

Первый абзац

Второй абзац

Третий абзац

.hide() и .show()

в документе.

Результат нашего примера:

.hide() и .show() различные значения продолжительности анимации:

Использование jQuery методов.hide() и.show() (различная скорость анимации) $(document ).ready(function (){ $(".hide ").click(function (){ // задаем функцию при нажатиии на элемент с классом hide $("p:first ").hide("slow "); // скрывыаем первый элемент

В документе $("p:nth-of-type(2) ").hide(2000 ); // скрывыаем второй элемент

В документе $("p:last ").hide("fast "); // скрывыаем последний элемент

В документе } ); $(".show ").click(function (){ // задаем функцию при нажатиии на элемент с классом show $("p:first ").show("slow "); // отображаем первый элемент

В документе $("p:nth-of-type(2) ").show(2000 ); // отображаем второй элемент

В документе $("p:last ").show("fast "); // отображаем последний элемент

В документе } ); } ); Скрыть Показать

Первый абзац

Второй абзац

Третий абзац

В этом примере с использованием jQuery методов .hide() и .show() мы при нажатии на определенную кнопку скрываем, либо отображаем все элементы

в документе. При этом первый элемент

скрывается, или отображается за 600 миллисекунд (ключевое слово "slow" ), второй элемент за 2000 миллисекунд, а третитй за 200 миллисекунд (ключевое слово "fast" ).

Результат нашего примера:

Рассмотрим следующий пример в котором зададим методам .hide() и .show() не только продолжительность анимации, но и укажем скорость анимации и функцию, которая будет выполнена после завершения анимации:

Использование jQuery методов.hide() и.show() (с callback функцией) $(document ).ready(function (){ $(".hide ").click(function (){ // задаем функцию при нажатиии на элемент с классом hide $("p ").hide(500 , "linear ", function (){ // скрывыаем элементы

В документе $(".status ").text("Элементы исчезли "); // задаем функцию при нажатиии на элемент с классом show $("p ").show(500 , "linear ", function (){ // отображаем элементы

В документе $(".status ").text("Элементы появились "); // добавляем текстовую информации в элемент с классом status } ); } ); } ); Скрыть Показать

Первый абзац

Второй абзац

Третий абзац

В этом примере с использованием jQuery методов .hide() и .show() мы при нажатии на определенную кнопку скрываем, либо отображаем все элементы

в документе. При этом мы указали для наших методов продолжительность анимации равную пол секунды (500 миллисекунд), эффект анимации происходит с одинаковой скоростью от начала до конца (linear ) и функцию, которая после завершения анимации находит элемент с классом status и добавляет текстовую информацию (jQuery метод .text()).

Результат нашего примера:

Рассмотрим следующий пример в котором передадим в качестве параметра методов .hide() и .show() объект, содержащий различные опции, которые будут контролировать анимацию:

Использование jQuery методов.hide() и.show() (объект с опциями в качестве параметра) $(document ).ready(function (){ $(".hide ").click(function (){ // задаем функцию при нажатиии на элемент с классом hide $("p ").hide({ // скрывыаем элементы

В документе duration: 800 , easing: "linear ", // скорость анимации Элементы исчезли "); } , queue: false // не ставим в очередь } ); } ); $(".show ").click(function (){ // задаем функцию при нажатиии на элемент с классом show $("p ").show({ // отображаем элементы

В документе duration: 800 , // продолжительность анимации easing: "linear ", // скорость анимации complete: function (){ // callback $(".status ").text("Элементы появились "); } , queue: false // не ставим в очередь } ); } ); } ); Скрыть Показать

Первый абзац

Второй абзац

Третий абзац

В этом примере с использованием jQuery методов .hide() и .show() мы при нажатии на определенную кнопку скрываем, либо отображаем все элементы

в документе. При этом мы в качестве параметров метода передаем объект содержащий следующие параметры:

  • продолжительность анимации равную 800 миллисекунд (duration: 800 )
  • эффект анимации происходит с одинаковой скоростью от начала до конца (easing: linear )
  • функция, которая после завершения анимации находит элемент с классом status и добавляет текстовую информацию (complete: function ).
  • анимация не размещается в очереди эффектов (queue: false ).

Результат нашего примера.

Привет, Хабр!

Сегодня я бы хотел познакомить начинающих вебмастеров с разнообразными изящными способами использования буферизации вывода в php. Опытные вебмастера для себя здесь врят ли найдут что-то полезное. Хотя - кто знает?

Как вы все знаете, буферизацией вывода в php управляет набор функций, начинающихся на «ob_». Самая главная из них - ob_start. При запуске она собирает последующий вывод, то есть всевозможные print(), echo и прочее, что потом отдастся посетителю в форме html-странички. И если перед тем, как выводить, мы запустили буферизацию, то с этой, почти готовой уже, страничкой, можно будет напоследок что-нибудь сотворить.


Например, мы хотим отфильтровать все ссылки на посторонние сайты.

На нашем, древнем как топор австралопитека, форуме, роится великое множество спамеров, заманивающих посетителя в места, заполненные развратом, однорукими бандитами и политической агитацией. Можно было бы использовать js со слежением, но мы хотим вместо этого изменить все эти ссылки так:

"http://blackjack-hookers.com" => "http://myoldforum.ru/redirect.php?url=blackjack-hookers.com"

Способ может быть и не самый эффективный, но действенный. Мы написали redirect.php с фильтром и черным листом, и теперь нам надо преобразовывать все ссылки на тысячах страниц форума. С помощью ob_start и парочки регулярных выражений мы сделаем это всего в несколько строк:

Function f_callback($buffer){ $buffer = preg_replace("#http://(www.)?myoldforum\.ru/#","/",$buffer); $buffer = preg_replace("#href="http://([^"]*)"#","#href="/redirect\.php\?url=$1",$buffer); return $buffer; } ob_start(f_callback);

Теперь, подключив этот код в начале index.php, или другого файла, к которому обращается сервер при просмотре страниц, мы получим то, что нам нужно.

Меняя контент таким образом, мы не ограничены рамками методов движка. Это бывает весьма ценно. Можно, например, добавить плагин:

Function generate_plugin(){ /*что-то генерируем*/ } function f_callback($buffer){ /*...*/ $buffer = str_replace ("",generate_plugin(),$buffer); /*...*/ return $buffer; } ob_start("f_callback");

Теперь, там, где мы добавили в контент появится то, что мы хотели получить. Одно из применений - вставка виджета js на страницу сайта. Например, яндекс-карты. Обычно это не составляет никакого труда, но иногда криво написанный редактор страниц сайта экранирует кавычки и фигурные скобки, ломая виджет. Как видим, эта проблема легко решается.

Набор инструментов php для работы с буффером вывода богат, и не ограничивается одним лишь ob_start. Вышеописанные приемы в некоторых случаях излишне ресурсоемки и громоздки, поскольку оперируют со всей страницей. Мы можем обработать только ее часть, создав в шаблоне оболочку вокруг генерации чего-то, в дебри чего нам не хочется лезть, но что обязательно нужно поправить:

{GENERATE BIG CRAZY THING}

Должно быть, вы уже заметили все эти обороты: «не хочется лезть», «древний, как стул тиранозавра», «криво написанный редактор»… В идеальном мире оболочки вокруг буфера вывода не нужны. Все что можно сделать с помощью ob_start, теоретически можно было бы сделать и без него. Этот прием иной раз вносит путанницу в код проекта, многие видят его смысл лишь в том, что бы отдать вывод в ob_gzhandler для сжатия, и считают его применение в иных случаях опасным. Но часто без управления выводом просто не обойтись.

Особенно если не хочется копать вглубь.

Что мы знаем о классификации приёмов "как-не-надо-делать" или анти-паттернов в программировании? Обычно приходит на ум только знаменитый Паблик Морозов :

Антипаттерн Паблик Морозов. Класс-потомок, созданный в соответствии с этим антипаттерном, выдает по запросу все данные класса-предка, независимо от степени их сокрытия. /* a.h */ class A { private: int papini_dengi; }; /* main.cpp */ #include #define private public /**/ #define protected public /**/ #include "a.h" #undef private /**/ #undef protected /**/ int main() { A *a = new A(); std::cout papini_dengi; /*А papini_dengi-то были приватным свойством:) */ system("pause>nul"); return 0; }

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

  • Abstraction inversion (Инверсия абстракции): реализованные функции системы, нужные пользователям, не представлены, что вынуждает их реализовывать эти функции заново с помощью функций более высокого уровня
  • Action at a distance (Дальнодействие): Неожиданное взаимодействие между далёкими частями системы.
  • Analysis paralysis (Аналитик-паралитик): Неоправданное внимание и затраты времени/ресурсов на стадию анализа
  • Big ball of mud (Большой комок грязи), Yo-yo problem (Проблема йо-йо), Spaghetti code (Спагетти-код), Индусский код: Структура системы отсутствует или не поддаётся пониманию
  • Bystander effect (Эффект наблюдателя): сама постановка задачи неверна, но те, кто это знают, молчат, потому что имеющимися силами всё равно не справимся
  • Call super (Позови папочку): Для реализации функциональности методу класса-потомка требуется в обязательном порядке вызывать те же методы класса-предка
  • Cargo cult programming (культ Мохнатого Гуру): Использование решений и методик без понимания причин
  • Cash cow (Денежная корова): Продукт прибылен и успешен, новые версии делаются через одного место и просто для галочки, как у Мелкософта
  • Circular dependency (Кольцо дружбы): взаимосвязь между двумя или более модулями, которые прямо или косвенно зависят друг от друга для правильной работы (взаимно рекурсивны)
  • Coding by exception (Клопомор): Добавление нового кода для поддержки каждого специального распознанной ошибки
  • Continuous obsolescence (Вечно старый): мы вынуждены только и адаптировать программу к новым версиям чего-то там, тратя на это непомерно много времени
  • Copy and paste programming (копипаста) - Копирование или небольшая модификация существующего кода вместо создания общих решений
  • Database-as-IPC (база вместо данных): Использование базы данных для обмена сообщениями между процессами там, где можно использовать более легковесные способы
  • Death march (Марш смерти): Все знают, что проект обречён, кроме начальника, узнающего об этом последним. Также обычно связано с бесплатной сверхурочной работой для достижения заведомо невозможного результата
  • Design by committee (Комитет по разработке): Делали многие, а видение у каждого своё. Результат - отсутствие даже намёка на целостность в продукте
  • DLL Hell (библиотечный ад) - Проблемы с совместно используемыми библиотеками
  • Error hiding (Концы в воду): Перехват сообщения об ошибке до того, как она показывается пользователю, в следствие чего пользователь не получает сообщения об ошибке или получает бессмысленное сообщение
  • Escalation of commitment (Эскалация обязательств): Неспособность отказаться от решения даже тогда, когда его ошибочность доказана
  • Feature creep (Футурит): "улучшения, приводящие к чрезмерному усложнению системы в ущерб качеству
  • Finnish profanity (Финская матерщина): не знаю, почему не русская... имеется в виду агрессивный, хамский стиль управления
  • God object (Блоб): Концентрация слишком большого количества функций в одном классе
  • Gold plating (Мартышкин труд): проект давно не приносит прибыли, но работа над ним продолжается; основной отечественный метод работы
  • Groupthink (Политбюро): Никто не хочет выдвигать идеи, противоречащие комфортному консенсусу
  • Hard coding (Хард-код): встраивания входных или конфигурационных данных непосредственно в исходный код программы или другого исполняемого объекта или фиксированное форматирование данных вместо того, чтобы получать эти данные из внешних источников
  • Inner-platform effect (Раздувание платформы): неоправданное усложение системы, попытка излишней универсальности
  • Input kludge (Затычка ввода): Отсутствие коректной обработки возможного неверного ввода. Классическое переполнение буфера, например, сюда же
  • Knight in shining armor (Рыцарь в сверкающих доспехах): появляется, когда всё сломали и пытается всё починить, не объясняя, как и почему он это сделает
  • Lava flow (потоки говн): Сохранение нежелательного (лишнего, низкокачественного) кода по причине того, что его удаление слишком дорого или будет иметь непредсказуемые последствия
  • Loop-switch sequence (циклы-переключатели): Кодирование последовательности шагов с помощью цикла и оператора выбора
  • Magic number (Волшебное число): константы в коде без пояснений, зачем они
  • Magic pushbutton (Волшебная кнопка): Написание бизнес-логики в коде пользовательского интерфейса (например в обработчике события нажатия на кнопку)
  • Moral hazard ("Эффективный менеджмент"): Тот, кто принимает решения, не отвечает за их последствия
  • Mushroom management (Грибной менеджмент): менеджеры держат тех, кто работает, в темноте и кормят навозом, иначе говоря, сотрудники не имеют достаточно достоверной информации, чтобы произвести нечто осмысленное
В PHP имя переменной всегда начинается со знака доллара ($), за которым обязательно должна следовать буква, после которой можно использовать буквы, цифры и знак подчёркивания. Имена чувствительны к регистру символов, т.е. переменные $value, $Value, $VALUE и $VaLuE - четыре РАЗНЫХ переменных, хотя их имя и читается одинаково.

Примеры синтаксически правильных имён переменных:

Пример некорректных имён:

Есть одно общее правило (для всех языков программирования), касающееся именования переменных. Правило очень простое: имена всегда должны быть осмысленными.

Пример плохо читаемого кода

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

Пример хорошо читаемого кода

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

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

Рассмотрим пример:

Передача переменных по значению

Для работы с переменными есть в PHP особые функции:

isset() - проверяет, была ли объявлена переменная и отличается ли её значение от NULL;
empty() - аналог isset()
unset() - встроенная функция языка, удаляющая значение переменной и удаляющая саму переменную из списка доступных переменных (уничтожающая переменную).

$name = "Иван Иваныч";
if(isset($name))
{
// Выводим сообщение с именем
echo "Моё имя: $name";
// уничтожаем переменную
unset($name);
}
else "Имя ещё не определено";

echo $name;
// ничего не выведет,
// т.к. значение переменной $name
// ещё не определено
// или переменная уже уничтожена

Область видимости переменных
Очень важная характеристика переменной - её область видимости (область действия), т.е. описание того, из каких мест программы (скрипта) можно прочитать или изменить её значение. Следует всегда помнить, что переменная, объявленная внутри блока программы, видна только в пределах этого блока, а для того, чтобы обратиться к переменной, объявленной снаружи блока, необходимо её особым образом объявить.

Блоками программы в данном случае являются "скрипт", "функция" или "класс". Например:

Вроде бы всё правильно, но - не работает. Почему? Потому что если явно не сказать, что переменная $name внутри функции - это в действительности глобальная переменная $name, то интерпретатор создать временную копию переменной с именем $name и пустым значением. А так как значение пустое (неопределённое), то и результат сложения строк будет неопределён (пуст).

Исправить положение очень легко, достаточно добавить всего одну строку (выделена жирным шрифтом):

В данном примере переменная $name имеет область видимости, равную всему скрипту, а переменная $fullName, объявленная внутри функции, имеет область определения равную этой самой функции. Это значит, при выходе их функции переменная $fullName будет уничтожена, а все попытки прочитать её значение приведут к ошибке.

Примеры работы с классами мы рассмотрим в разделе "Классы и наследование".

Переменные переменные
Да-да, здесь нет ошибки, именно так (двумя словами) называются некоторые переменные в PHP. Смысл в том, что текстовая часть имени переменной (т.е. имя без знака доллара) может сама быть именем. Например:

Настоятельно не рекомендуется пользоваться подобными приёмами без острой необходимости. Код, напичканый такими трюками, очень сложно сопровождать. Особенно это важно при работе с данными, вводимыми пользователями. Главная причина сложностей - неявные зависимости. Например, что случится, если вместо имени "Вася" написать что-то вроде """""_;%//^q""? Правильно! Скрипт в большинстве случаев не сможет выполниться! Можно, конечно, добавить кучу проверок на наличие "неправильных" символов, но проще вообще не пользоваться такими трюками.

Константы
Константа - это некая неизменная величина. Константа объявляется одновременно с именем и значением. Для объявления константы служит функция define(), а для определения наличия константы (т.е. была она определена или нет) - функция defined(). Имя константы строится по тем же правилам, что и имена переменных.

Примеры констант:

Отдельный вид констант PHP - так называемые "магические константы". Это системные константы, значение которых определяет и устанавливает интерпретатор. Таких констант немного:

LINE__ Содержит номер текущей строки в текущем файле.
__FILE__ Содержит полное имя текущего файла
__FUNCTION__ Содержит имя текущей функции.
__CLASS__ Содержит имя текущего класса.
__METHOD__ Содержит имя текущего метода текущего класса.
Эти константы очень удобны при отладке, но во всех других случаях их лучше не использовать, заменяя на вызовы соответствующих функций