Підводний камінь у foreach($items as &$item). Опис структури шаблону com_content Безвихідний item php

Багато fatal і recoverable fatal errors буде спрямовано на exceptions в PHP 7. The error exceptions inherit from the Error class, which itself implements the Throwable interface (the new base interface all exceptions inherit).

Це означає, що custom error handlers не можуть бути тривалими, тому що тривають, тому що exceptions можуть бути тремтячими instead (відповідно про нові fall errors для uncaught Error exceptions).

У повному описі , якою є помилка в PHP 7 може бути знайдена на PHP 7 errors page . Ця migration guide will merely enumerate the changes that affect backward compatibility.

// PHP 5 era code that will break.
function handler (Exception $e) ( ... )
set_exception_handler ("handler");

// PHP 5 та 7 compatible.
function handler ($e ) ( ... )

// PHP 7 тільки.
function handler (Throwable $e) ( ... )
?>

Internal constructors always throw exceptions on failure

Спершу, деякі internal classes would return NULL or an unusable object when the constructor failed. Всі міжнародні класи будуть свідомі про те, що висновок в цьому випадку в той же час, які user classes already had to.

E_STRICT notices severity changes

All of the E_STRICT notices have been reclassified to інші рівні. 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 не error
Signature mismatch during inheritance E_WARNING
Same (compatible) property in two used traits Notice removed, triggers не error
Accessing static property non-statically E_NOTICE
Only variables should be assigned by reference E_NOTICE
Тільки variables should be passed by reference E_NOTICE
Calling non-static methods statically E_DEPRECATED

Changes to variable handling

PHP 7 зараз використовує abstract syntax tree коли parsing source files. Це означає, що багато рішень на мові, які були передусім неможливими для обмеження в parser used v earlier versions of PHP, але resulted in removal of feed special cases for consistency reasons, which has resulted in backwardakpati. Вони існують в цьому розділі.

Зміни до handling of indirect variables, properties, and methods

Indirect access to variables, properties, and methods will now be evaluated strictly в left-to-right order, як opposed to the previous mix of special cases. Table перед shows how the order 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"]()

Код, який використовує загальний правий-літр evaluation order повинен бути перевірений для explicitly use that evaluation order with curly braces (see the above middle column). Це буде зробити code both forwards compatible with PHP 7.x and backwards compatible with PHP 5.x.

var_dump (1 >> - 1);
?>

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будевсього результату в 0. Передусім, під частаких shifts був архітектура dependent.

Changes to Division By Zero

Перш за все, коли 0 був використаний як дивізій для будь-якого divide (/) або modulus (%) операторів, an E_WARNING would be emitted and false would be returned. Зараз, divide operator returns a float as ether +INF, -INF, або NAN, as specified by IEEE 754. The modulus operator E_WARNING буде been removed і буде кинути a DivisionByZeroError exception.

var_dump (3/0);
var_dump (0/0);
var_dump (0% 0);
?>

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

$str = "0xffff";
$int = filter_var ($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
if (false === $int ) (
throw new Exception ("Invalid integer!");
}
var_dump ($int); // int(65535)
?>

\u(мої cause errors

Due to the addition of the new Unicode codepoint escape syntax , strings containing a literal \u( followed by an invalid sequence буде викликати fatal error. Для того, щоб керувати backslash should be escaped.

Removed functions

Removed INI directives

xsl.security_prefs

The xsl.security_prefs directive has been removed. Instead, the XsltProcessor::setSecurityPrefs()метод повинен бути викликаний контролем охорони здоров'я на першому-процесорі basis.

Інші 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:

class C ()
$c =& new C ;
?>

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:

Попередній error: syntax error, unexpected "new" (T_NEW) в /tmp/test.php on line 3

Invalid class, interface and trait names

Наведені назви можуть бути використані в name classes, interfaces or traits:

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

Ужебільше, наступні назви не повинні бути використані. У той час, якщо вони не генерують будь-який error в PHP 7.0, вони будуть затверджені для майбутнього використання і повинні бути розглянуті.

  • object
  • mixed
  • numeric

ASP and script PHP tags removed

Support for using ASP and script tags to delimit PHP code буде переміщено. The affected tags are:

Removed ASP and script tags
Opening tag Closing tag
<% %>
<%= %>

Calls from incompatible context removed

Спершу розпізнано в PHP 5.6 , статечні дзвінки спричинені нестатичною методом з некомпетентним контекстом, що в цей час внесений в методи, що мають невизначений $this variable і deprecation warning being issued.

class A (
public function test () ( var_dump ($this ); )
}

// Note: Does NOT extend A
class B (
Public function callNonStaticMethodOfA () ( A :: test (); )
}

(new B )-> callNonStaticMethodOfA ();
?>

Output of the above example in PHP 5.6:

Deprecated: Non-static method A::test() не повинен бути названий статічним, оцінюваним $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 => . Це може бути результатом в зміненому стані:

echo yield-1;
echo (yield) - 1;
// And is now interpreted as
echo yield (- 1);

Yield $foo or die;
// був попередньо interpreted as
yield ($foo or die);
// And is now interpreted as
(yield $foo ) or die;
?>

Parentheses може бути використана для disambiguate those cases.

Functions cannot have multiple parameters with the same name

Це не довгий час, щоб define two or more function parameters with the same name. Для прикладу, following function will trigger an E_COMPILE_ERROR:

function foo ($a, $b, $unused, $unused) (
}
?>

Functions inspecting arguments report the current parameter value

func_get_arg(), func_get_args(), debug_backtrace()і виключення backtraces не буде тривалий час перегляду оригіналу значення, що було прописано до параметра, але буде зроблено в рамках поточного значення (який мить буде змінено).

function foo ($x) (
$x++;
var_dump (func_get_arg (0));
}
foo (1); ?>

Output of the above example in PHP 5:

Output of the above example in PHP 7:

Switch statements cannot have multiple default blocks

Це не довгий час, щоб визначити два або більше подробиць блоків в ситуації. Для прикладу, натиснувши на перемикання statement will trigger an E_COMPILE_ERROR:

switch (1 ) {
default:
break;
default:
break;
}
?>

JSON extension replaced with JSOND

The JSON extension has been replaced with JSOND, causing 3 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, коли using scientific notation, e exponent must not immediately follow a decimal point (i.e. 3.e3 must be changed to either 3.0e3 or 3e3). Finally, empty string is no longer valided JSON.

Internal function failure on overflow

Передусім, міжнародні функції були нескінченно 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 ha been improved, what may result in different sort order of elements, which compare as equal, than before.

Don't rely on the order of елементів, які 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. Код для вставки інформації про хіти буде таким:

item->hits?>

Тепер потрібно знайти у файлі шаблону category\blog_item.php місце, де цей код вставити. Наприклад, перед відображенням дати останнього редагування матеріалу. Шукаємо рядок:

item->modified) !=0 && $this->item->params->get("show_modify_date")) : ?>

І перед нею вставляємо рядок із кодом.

Приклад виведення списку категорій у кілька колонок .

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

Незвітно, інстинктивно, машинально, стихійно, сліпо. Див … Словник синонімів

Мимоволі, несвідомо, несвідомо, інстинктивно, машинально, механічно, сліпо, стихійно; ненавмисно, ненавмисно; волею неволею, хочеш не хочеш (volens nolens), по необхідності Це йому довелося зробити за не залежним від нього… Словник синонімів

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

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

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

Беззвітний, несвідомий, несвідомий; (коротк. чоловіч. не упот.) несвідома, несвідома. 1. Не підпорядковується ніякому контролю, який зобов'язаний звітувати. Він несвідомо (нареч.) розпоряджався в лавці. 2. Не залежить від розумних міркувань, ... Тлумачний словник Ушакова

- (Грець.). Особа, якій довірено торгувати несвідомо, за рахунок іншої особи. Словник іншомовних слів, що увійшли до складу російської мови. Чудінов А.Н., 1910. АНАГАЛІСТ Особа, якій довірено торгувати за рахунок іншої особи несвідомо. Пояснення… Словник іноземних слів російської мови

Несвідомо, несвідомо, механічно, мимоволі, автоматично, машинально, автоматично, механічно, автопілотом Словник російських синонімів. автоматично див. машинально Словник синонімів російської мови. Практичний довідник М.: Російська … Словник синонімів

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

Книжки

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

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

1. Створення функцій зі змінною кількістю аргументів

Швидше за все, ви знаєте, що PHP дозволяє нам створювати функції з необов'язковими аргументами. Зараз я покажу функцію, в якій кількість аргументів може змінюватися іноді.

Але для початку, згадаємо як ми створюємо функції звичайним чином:

// функція з двома необов'язковими параметрами function foo($arg1 = "", $arg2 = "") ( echo "arg1: $arg1\n"; echo "arg2: $arg2\n"; ) foo("hello", "Світ"); /* виведе: 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<10000000;$i++) { } $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: 1.424592 System time: 0.004204 */

Робота скрипта зайняла 1.4 секунд процесорного часу. В даному випадку час системних викликів взагалі низький.

Час роботи в привілейованому режимі (System Time) - це час, який процесор витрачає виконання системних запитів до ядру від імені програми. Приклад:

$ start = microtime (true); // Викликаємо microtime кожні 3 секунди while(microtime(true) - $start< 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: 1.088171 System time: 1.675315 */

Тепер системного часу витратилося набагато більше, ніж у попередньому прикладі. Все завдяки методу microtime(), який використовує ресурси системи.

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

5. Магічні константи

У PHP існує безліч магічних констант, таких як номер поточного рядка (__LINE__), шлях до файлу (__FILE__), шлях до каталогу (__DIR__), ім'я функції (__FUNCTION__), ім'я класу (__CLASS__), ім'я методу (__METHOD__) та простору імен (__NAMESPACE__).

Усі ми їх розглядати не будемо. Подивимося тільки парочку:

// цей скрипт залежить від поточного розташування файлу і // може викликати проблеми, якщо його використовувати з різних директорій require_once("config/database.php"); // цей скрипт не викликає проблем require_once(dirname(__FILE__) . "/config/database.php");

Використовуйте __LINE__ при налагодженні скриптів:

// код // ... my_debug("some debug message", __LINE__); /* виведе Line 4: some debug message */ // ще код // ... my_debug("another debug message", __LINE__); /* виведе Line 11: another debug message */ function my_debug($msg, $line) ( echo "Line $line: $msg\n"; )

6. Генерування унікальних ID

Бувають такі моменти, коли вам треба згенерувати унікальний рядок. Багато разів я бачив, що для вирішення цього завдання використовують функцію md5():

// генеруємо випадковий рядок echo md5(time(). mt_rand(1,1000000));

Але насправді для цих цілей у PHP є спеціальна функція uniqid()

// генеруємо випадковий рядок echo uniqid(); /* виведе 4bd67c947233e */ // ще раз echo uniqid(); /* виведе 4bd67c9472340 */

Неозброєним поглядом можна побачити, перші символи м'яко кажучи схожі… Так відбувається тому, що це метод використовує час сервера для генерації символів. Це корисно, т.к. всі згенеровані значення утворюються в алфавітному порядку, що дає можливість швидко їх сортувати.

Для того, щоб зменшити шанси отримання дубліката, ми можемо додати префікс або використати другий параметр (збільшить кількість символів):

// із префіксом echo uniqid("foo_"); /* виведе foo_4bd67d6cd8b8f */ // з другим параметром echo uniqid("", true); /* виведе 4bd67d6cd8b926.12135106 */ // обидва echo uniqid("bar_",true); /* виведе bar_4bd67da367b650.43684647 */

Цей метод генерує рядки розміром менше, ніж md5, тим самим ви зможете заощадити місце.

7. Серіалізація

Вам колись доводилося зберігати комплексні дані у базі чи файлі? Для того, щоб сконвертувати об'єкт у рядок у PHP, передбачена спеціальна функція.

Взагалі, цих методів 2: serialize() і unserialize()

// Складний масив $ myvar = array ("hello", 42, array (1, "two"), "apple"); // Конвертуємо в рядок $string=serialize($myvar); echo $string; /* виведе a:4:(i:0;s:5:"hello";i:1;i:42;i:2;a:2:(i:0;i:1;i:1;s) :3:"two";)i:3;s:5:"apple";) */ // отримуємо вихідне значення $newvar = unserialize($string); print_r($newvar); /* виведе Array ( => 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. , набір adipiscing elit.Aquaqua pretium ullamcorper urna quis iaculis. non mi metus, at lacinia augue. ."; $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 це ціла планета, яка не перестає нас дивувати своїм вмістом. А що думаєте ви про ці функції?

Багато хто любить писати такі конструкції в тому чи іншому вигляді, кожен стикався:
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. І всі вони обговорювалися. Однак, цей випадок, судячи з мого досвіду, так поширений на практиці, що заслуговує на окрему увагу.