программирование
Загадки PHP
Да что это я всё о себе, да о себе? Давайте я вам лучше о PHP расскажу! PHP, несмотря на кажущуюся простоту, язык уникальный своими загадками. Возникают, они, в основном
Ссылки в PHP — совершенно особая сущность. Небольшой ликбез. Ссылка — это способ «соединить» две переменные так, что меняя значение одной, меняется значение второй и наоборот. Записывается ссылка очень просто: $foo = &$bar. Кажущаяся простота ссылок обманчива. Я сейчас буду рассматривать PHP5, поскольку мне кажется, что четвёртая версия должна умереть как можно скорее. Все примеры были проверены под PHP 5.1.4 и PHP 5.2.0RC1 под Windows и Linux.
<?php
$a = new stdClass();
function Bar($bar)
{
$bar->val = 1;
}
Bar($a);
print_r($a);Проблема номер раз. Как вы думаете, что напечатает print_r? Отвечу сразу: он покажет свойство «val» со значением «один». Почему так произошло? Дело в том, что в PHP5 (как и во многих других языках) все объекты передаются по ссылке. Это значит, что переменная $bar в функции ссылается на переменную $a, которую мы указали в качестве параметра и все изменения $bar коснутся переменной $a. Если мы вызовем функцию «Bar» с другим параметром, то $bar будет ссылаться на этот новый параметр.
Ситуация, когда объект в функцию нужно передать по значению, на практике — почти невероятна, впрочем, если она и возникнет, объект всегда можно клонировать — в PHP5 есть специальные конструкции.
<?php
$v = array(1);
$b = &$v[0];
$c = $v;
$v[0] = 100;
echo $c[0];Проблема номер два. Что же будет внутри $c[0]? Странно, но — 100. Как же так? Всё просто. В PHP, если мы создали ссылку на переменную, то оба имени переменных становятся ссылками. Получается, что присваивая $c внутренность $v, я его присваиваю вместе с $v[0], которая стала ссылкой.
Странно? Совсем нет. Дело в том, что имя переменной — это тоже ссылка. Ссылка на область памяти, где записано её значение. Если ссылок на место, занимаемое переменной, больше чем одна, то все её имена ведут себя как «ссылка», если же удалить «лишние», то последнее имя теряет свою «ссылочность». Пример:
<?php
$v = array(1);
$b = &$v[0];
var_dump($v);
unset($b);
var_dump($v);Первый «var_dump» покажет нам ссылку, второй — нет.
<?php
$bar = 1;
function Foo()
{
global $bar;
$test = 100;
$bar = &$test;
}
Foo();
echo $bar;Проблема номер три. Кстати говоря, когда вы используете конструкцию «global», на деле вы используете ссылку. Дело в том, что «global $bar» полностью эквивалентна «$bar =& $GLOBALS[’bar’]». Если вы не знаете что такое $GLOBALS, самое время открыть руководство по PHP и узнать. Так вот. Проблема заключается в том, что «магическое» слово «global» прячет от нас всю эту операцию, поэтому кажется, что в глобальной переменной $bar должно быть значение 100. Это не так.
На деле, «$bar = &$test» вызовет переназначение ссылки. То есть, прежняя ссылка «$bar — это $GLOBALS[’bar’]» пропадёт и на её место встанет «$bar — это $test». Значение $GLOBALS[’bar’], естественно, не изменится.
Ну а теперь, вооружённые этими новыми знаниями, мы рассмотрим следующий интересный пример.
<?php
$v = array(1);
foreach ($v as &$item) echo $item;
function Bar($foo)
{
$foo[0] = 100;
}
Bar($v);
var_dump($v);Итак! Что выведет «var_dump»? Правильно — 100. Почему? Вполне логично — в цикле мы проходим по элементам массива, причём $item ссылается на текущий элемент как ссылка. После цикла остаётся ссылка «$item — это $v[0]», поэтому, когда я передал в «Bar» переменную $v, её нулевой элемент остался ссылкой. Остальное понять труда не составляет. Давайте пойдём дальше.
<?php
$v = array(1, 2);
foreach ($v as &$item) echo $item;
function Bar($foo)
{
$foo[0] = 100;
$foo[1] = 100;
}
Bar($v);
var_dump($v);Что же тут покажет «var_dump»? Странно, но в обоих элементах массива будет… 100. Казалось бы — bug PHP (впрочем, я не настаиваю — может это и баг). Оказывается, не совсем. Дело в том, что ссылка в PHP уничтожается конструкцией unset и только ей. При переприсвоении ссылки прежняя ссылка не удаляется, точнее, PHP не трогает счётчик ссылок. В моём следующем примере все три переменные будут ссылкой (в чём легко убедиться, сделав «var_dump переменной $GLOBALS»):
<?php
$v = 1;
$k = 2;
$b = &$v;
$b = &$k;Первый же unset «восстановит справедливость»:
<?php
$v = 1;
$b = &$v;
$t = &$v;
$k = 2;
$b = &$k;
unset($t);Теперь переменные $k и $b — ссылочные, а $v — нет. Видимо, «пересчёт» ссылок при пересвоении вызывает
Explorer Canvas
IE не обновлялся очень давно и не поддерживает тег CANVAS, предоставляющий интересные возможности — рисование через JavaScript вектором. Интересно, что Microsoft
Вероятно некоторая схожесть технологий VML и CANVAS вдохновила Emil A Eklund на создание Explorer Canvas — трансляцию вызовов CANVAS в теги VML. Поддержка пока ограниченная, но ведётся активная работа по расширению возможностей. На сайте есть небольшая демонстрация возможностей. Кстати, хорошо видно, что в браузерах Opera и FireFox canvas ведёт себя
IE и HTTPS
Следующая проблема — некорректное поведение IE при использовании протокола HTTPS. Иногда (особенно на сайтах, где используются технологии изменения содержимого страницы без её перезагрузки), в странице используется тег iframe без содержимого или с указанием about:blank. IE считает, что такой IFRAME загружает содержимое не по протоколу HTTPS (формально он прав — конечно не загружает,
От этого раздражающего предупреждения можно избавиться следующим образом: указать в качестве src для iframe конструкцию
javascript:''Т. е.
<iframe src="javascript:''></iframe>javascript — это протокол, который позволяет выполнять JavaScript. Когда страница грузится по HTTPS этот скрипт выполняется в текущем протоколе — HTTPS, а указание пустой строки позволяет создать фрейм именно с пустым содержимым.
Панель на картинке
Ещё одно изобретение Microsoft — панель, которая появляется при наведении на картинку. Функция хорошая, но на элементах оформления эта панель здорово портит кровь, особенно в тех случаях, когда нужно отобразить диалог, заблокировав и затемнив остальное содержимое сайта полупрозрачной картинкой — такой метод изготовления модальных диалогов всё чаще используется в вебе.
Вот в этих случаях не нужно, чтобы при наведении на картинку пользователь видел эту панель. Есть два способа избавиться от неё.
<img src="/img/image.jpg" width="100" height="100" alt="" galleryimg="no" >Выполнение JS только в IE
Кстати говоря, есть два способа выполнения
<script language="JScript">alert('1')</script>cработает только в Opera и Internet Explorer.
Второй способ — так называемая «условная компиляция». Был придуман Microsoft, чтобы прятать новые конструкции языка (например, try … catch) от предыдущих версий браузера. Следующий код выполнится только в Internet Explorer. Остальные браузеры посчитают его комментарием в коде JavaScript
/*@cc_on
alert(1)
@*/В «условной компиляции» можно выполнять ещё ряд действий, например, проверять версию jscript и т.д, всё это легко найти в любом поисковике.
Условные комментарии
Одна из проблем — как подключать
Специальная конструкция
<--[if IE...] ... <![endif]-->позволяет не только прятать
Кстати, от Internet Explorer так же можно прятать
<comment> … </comment>Этот нестандартный тег Internet Explorer считает комментарием и, соответственно, не показывает и не обрабатывает его содержимое.
Борьба с Activating ActiveX Controls
Одно из новшевств, которое появилось в последних обновлениях Internet Explorer — это «Activating ActiveX Controls» (KB912945). После обновления Internet Explorer позволяет управлять элементами, которые находятся на ActiveX (а к ним относится и Flash) только после клика на объект, сам объект до клика выделяется рамкой, если над ним провести мышкой. Само по себе это не так уж и мешает, только если этот ActiveX (Flash, например) не находится
Оказывается есть метод борьбы с этой проблемой. Всё что нужно сделать — обойти все теги object и присвоить их outerHTML самому себе. Например, так:
// When the page loads:
window.onload = function(){
if (document.getElementsByTagName) {
// Get all the tags of type object in the page.
var objs = document.getElementsByTagName("object");
for (i=0; i<objs.length; i++) {
// Get the HTML content of each object tag
// and replace it with itself.
objs[i].outerHTML = objs[i].outerHTML;
}
}
}
// When the page unloads:
window.onunload = function() {
if (document.getElementsByTagName) {
//Get all the tags of type object in the page.
var objs = document.getElementsByTagName("object");
for (i=0; i<objs.length; i++) {
// Clear out the HTML content of each object tag
// to prevent an IE memory leak issue.
objs[i].outerHTML = "";
}
}
}Триграфы в Си
Век живи, век учись, больше заработаешь. Язык C я недолюбливаю, преимущественно
Вообще триграфы были придуманы для терминалов, в которых некоторых символов не хватает. В итоге вместо #define можно написать ??=define. Триграфы подменяются на нужные символы в самом начале, поэтому эти записи эквивалентны. Вместо { можно написать ??< , вместо } использовать ??>
Остальные триграфы можно найти в статье Елены Сагалаевой «Триграфы и альтернативные символы» на её персональном блоге. Кстати, очень рекомендую сам блог — отличное чтиво на темы связанные с программированием.
PHP для PocketPC
Одной из особенностей языка PHP является то, что существует ровно один интерпретатор этого языка. Это хорошо — никакого разночтения стандартов и прочих проблем наличия интерпретаторов от разных команд. Или, по крайней мере, другие мне не попадались. До сих пор.
Некие умельцы написали Pocket HPH — интерпретатор для PocketPC. Конечно, реализованы далеко не все функции, но и того набора, что есть, хватит, чтобы реализовать
XSS
Одна из известных проблем безопасности
Похоже, фирма Microsoft первая, кто озаботился поиском принципиально новых возможностей решения этой проблемы. Microsoft добавила в свой браузер поддержку так называемых «
Set-Cookie: USER=123; expires=Wednesday, 09-Nov-99 23:12:40 GMT; HttpOnlyПредельно понятно и достаточно действенно. Пока в PHP, в setcookie нет поддержки этого флага, такую cookie можно ставить через вызов header.
Библиотека для работы с XBM и моно-BMP
Одним словом,
Тотализатор для «Электроники МК85»
Я из этой машинки выжимал всё что можно, а первым моим развлечением был тотализатор — по экрану ползли точки, которые обозначали лошадей, в конце выводился номер победившей «лошади». Неизбалованные «пентиумами» одногрупники (дело было, примерно, в году
Вот, когда я узнал, что знания — сила. На тотализатор ставились деньги, а в программе была секретная комбинация, позволявшая указать какой из лошадей придти к финишу…
Регулярные выражения наглядно

Увидел у Cooler’a ссылку на замечательную программу — The Regex Coach. Есть версия для Linux и Windows. Программа позволяет визуально проверять регулярные выражения — смотреть дерево, замены, совпадения и т. п. Очень рекомендую.
Разделяемая память и PHP
В основном на PHP пишут небольшие проекты, поэтому литература кишит примерами «как сделать сайт в три странички». Но, тем не менее, только простыми сайтами дело не ограничивается. Когда приходится делать производительные проекты, существует множество ухищрений и решений, одно из которых — использовать разделяемую память, там где кешировать данные в статические файлы не получается. Различных API для использования разделяемой памяти много, только в одном PHP есть shmop, shm_* и Memcache, что несколько осложняет дело.
Я сделал
В настоящий момент поддерживаются следующие API:
- eAccelerator
- Turck MMCache
- APC
- Shmop
- Apache Notes
- Memcached
- System V (имена переменных до 4х символов)
- SQLite (база данных создаётся в памяти)
- Sharedance
- File (данные хранятся в файлах)
Brainfuck
Дело давнее, но около месяца назад, поддавшись
Модуль к PHP написан в формате PEAR, т. е. его можно либо использовать непосредственно, либо исталлировать в составе PEAR.
Нельзя сказать, что я компилятор проводит глубокую оптимизацию, но, например, код
<?php
$in = array(0, $id = 0);
$d = array_fill(-65535, 65535, $di = 0);
$d[$di+1]+= $d[$di];
$d[$di+2]+= $d[$di]*2;
$d[$di] = 0;
$d[$di+1]+= $d[$di];
if ($d[$di]) $d[$di+2] = 0;
$d[$di] = 0;
$d[$di+1]+= $d[$di];
$d[$di] = 0;В сам
Тег для календаря

Лично для меня событие недели — появление Opera 9.0 Technology Preview 1. Помимо поддержки XSLT, появления аналога настроек FireFox, только сделанных для человека, а не робота, поддержки Canvas, некоторых селекторов CSS3 и прочего, несомненный интерес представляет поддержка стандарта WebForms 2 — обратносовместимого расширения HTML для разработки различных интерфесов ввода. В частности, картинка на скриншоте делается
<input type="datetime" step="120" name="start">и это далеко не самая впечататляющая демострация — просмотрите стандарт, хотя бы по диагонали. Жаль, что это всё удасться использовать не ранее чем лет через пять, прежде всего
Блоки и локальные переменные в PHP
Давайте я опять про программирование, ага? Вообще, пусть это будет основной темой моего блога. Общечеловеческие ценности, безусловно, меня тоже волнуют, но это насколько скользкая тема, что так и норовишь вляпаться
Рассуждал я
Не хватает мне возможности изоляции переменных. Чтобы можно было, не задумываясь нет ли вверху
<?php
{
var $i;
echo $i = 1;
}
echo $i;Пояснять нужно? Переменная, объявленная в фигурных скобках, перестаёт существовать за их пределами и не влияет на значения переменной с тем же именем, объявленной уровнем ниже. Я даже согласен на специальную конструкцию (хотя вот эта была бы предельно совместимой), чтобы это включили в PHP6, вместо пространств имён, которые, на мой взгляд, успешно подменяются объектами.
Наверное, нужно пояснить зачем, собственно, это нужно. Поясняю. Для уменьшения расхода памяти, чтобы объект, однажды объявленный в начале файла для локальных нужд, который забыли удалить не тянулся по всему коду, как смрад за народным ополчением, а сразу же, по выходу из блока, попал б в кандидаты на удаление.
Вторая причина — у вас никогда такого не было, что вы перетёрли переменную, которая используется
На мой взгляд, реализовываться это должно довольно просто. Ведь это, по сути, просто анонимная функция со ссылками на все глобальные переменные внутри, где var просто очищает такую ссылку.
Формат графики XBM
Есть такой интересный принцип дарить подарки — покупать в подарок то, что люди сами бы себе никогда не купили. У меня, похоже, одно из хобби — копать там, где ничего не растёт. В том смысле, что меня больше увлекают проекты, где практической пользы меньше, чем льда на Солнце.
Было время, меня увлёк графический формат XBM, единственное достоинство которого (впрочем, вполне достаточное, на мой взгляд) — безумная простота, позволяющая манипулировать графикой в этом формате из любого хоть
И вот я узнаю, что Internet Explorer 6.0SP1 и выше не поддерживает мой любимый формат! Причину цитирую:
A change was made to Internet Explorer for Windows XP Service Pack 2 and Windows Server 2003 Service Pack 1 so that it does not render the XBM image file format. This update adds this change to all other supported versions of Internet Explorer. This change has been made to help prevent the Internet Explorer process from closing unexpectedly when users view
invalidly-formed images. The XBM format is no longer supported by Internet Explorer.
Что переводится, примерно, так: «у нас
Image_MonoBMP — модуля для работы с монохромными изображениями в формате BMP. А чтобы подтвердить, что я опять дарю вам то, что вы себе сами бы не купили, скажу, что этот формат, конечно, поддерживается Internet Explorer и Opera, но FireFox плевать на него хотел, да,
Кстати, есть у меня идея сделать поддержку WBMP, но как же быть с принципом? Впрочем, я его уже нарушил, но об этом
Basic auth в Apache
Знаете ли вы, что в пароле при basic auth в Apache используются только первые восемь символов? Цитата с сайта Apache:
This is a feature of the crypt library on your system: in only looks at the first 8 characters of the password. To avoid it, use
the -m option to htpasswd to create md5 passwords.
Maxthon
В качестве эксперимента попробовал браузер FireFox (основанный на Mozilla). Увы. Сразу же нашёл целых три бага. Кроме того, путанница с плагинами (extension), которые конфликтуют между собой и подходят только к той версии, для которой были созданы, радости не добавляет. Единственное, что порадовало — RSS reader (Sage), но недостатки, пожалуй, перевесили достоинства.
Решил попробовать новый Maxthon — надстройку на Internet Explorer, программу которую я использую очень давно, но уже не обновлял около года. С радостью узнал, что в новой версии появилось много нужных нововведений, в том числе — RSS reader. Вывод: остаюсь на Maxthon — движок IE меня вполне устраивает, поскольку на данный момент является стандартом de facto, а всё, что ему нехватает в плане дополнительных удобств, добавляет Maxthon.