2010-12-14

SunSpider 0.9.1 на лезвиях

Мое предыдущее сравнение производительности браузеров Firefox оставляло желать лучшего. Визуально восприятие информации было просто ужасным. По прошествии некоторого времени мне опять захотелось посмотреть, кто же быстрее ныне в исполнении JavaScript. Я взял последние нестабильные (кроме Safari) версии популярных браузеров и прогнал на них SunSpider 0.9.1
Современные браузеры в бенчмарке SunSpider 0.9.1
Интересен тот факт, что Firefox серьезно отстает от своих основных конкурентов, но не стоит забывать, что этот браузер является наиболее удобным при разработке веб-приложений. Впереди планеты всей оказался Chrome от компании Google, которому в свою очередь успевает наступать на пятки Opera.

2010-09-18

Нововведения MySQL 5.5

Возможно, вы уже слышали о СУБД MySQL 5.5, которая находится еще в стадии разработки. В новой версии ожидается довольно впечатляющий список вкусных нововведений, о которых и пойдет речь. На своем домашнем сервере я использую последнюю стабильную версию 5.1 и очень жду выхода новой версии этой СУБД.
Итак, перейдем к деталям. Нас ожидает:
  1. Улучшена производительность на многоядерных процессорах. Теперь уже не те времена, когда процессорная мощь наращивалась частотами и можно было спокойно говорить: “Ждите, с новым процессором ваша СУБД станет быстрее”. Ныне разработка MySQL направлена на использование возможностей многоядерных процессоров. Основные усилия сосредоточены на улучшении производительности движка InnoDB и особенно блокировки таблиц.
  2. Подсистема ввода / вывода движка InnoDB оптимизирована для эффективного использования ресурсов устройств ввода / вывода.
  3. Улучшена производительность MySQL Server для ОС Solaris.
  4. Возможность просматривать более полную информацию о используемых системных ресурсах с помощью команды SHOW ENGINE INNODB STATUS.
  5. Поддержка стандартных для SQL: SIGNAL и RESIGNAL операторов.
  6. Поддержка новых многобайтовых кодировок: utf16, utf32, utf8mb4.
  7. Улучшена работа с XML, в том числе введен новый оператор LOAD XML.
  8. Добавлена функция TO_SECONDS(). Эта функция преобразует дату или дату и время в количество секунд, прошедшее с начала 0 года.
Также нас ждут улучшения в плане партицирования. Но, к сожалению, мой опыт не позволяет писать о них, поэтому я не стану вникать в подробности этих улучшений.

2010-08-26

3 совета для Zend Studio

Сегодня хотел бы поделиться парочкой полезных и не очевидных советов, которыми я пользуюсь в Zend Studio.
Комментарии
Комментировать код, расставляя вручную // не очень-то удобно. Можно использовать одну из 2 комбинаций:
  • Ctrl + Shift + C
  • Ctrl + /

До комментария


После
CamelCase и Autocomplete
Autocomplete также работает, если набирать заглавные буквы названий классов:
Набираем ZFEC для подсказки Zend_Form_Element_Captcha


Авто обновление рабочего пространства
Каждый раз выбирать папку и нажимать F5, чтобы студия считала с файловой системы изменения - утомительно, и, порой, неудобно (например, при использовании SVN, мы можем забыть закоммитить файл, добавленный вне студии). Есть одна замечательная опция, которая позволяет это делать автоматически, отслеживая изменения самостоятельно:
Ставим галочку Refresh automatically

2010-08-23

Пошаговый дебаг PHP в Zend Studio (разбираемся с Ubuntu)

Давно была интересна эта тема, но руки никак не доходили до того, чтобы привести это в действие: научиться устраивать пошаговый дебаг в Zend Studio.
Итак, мне удалось настроить работу Zend Debugger в Linux Ubuntu и в Windows 7. В этой части статьи будет приведен пример настройки в Ubuntu.
Нехитрое дело посмотреть в инструкцию по установке. Сразу оговорюсь, отключите eAccelerator, с ним Zend Debugger глючит.
Для начала качаем Studio Web Debugger с официального сайта. Также очень рекомендую поставить Studio Browser Toolbars для Firefox (качается оттуда же и сильно облегчает жизнь в последующем):
Studio Browser Toolbars в браузере Firefox 3.6
Zend Debugger является модулем для PHP. Далее некоторые нюансы для разных версий PHP могут различаться, в моем случае был рассмотрен PHP 5.3.3. Из архива достаем ZendDebugger.so, соответствующий нашей версии PHP и копируем его в директорию /usr/lib/php5/20090626+lfs. Прописываем в php.ini новый модуль и базовые настройки:
zend_extension = /usr/lib/php5/20090626+lfs/ZendDebugger.so

zend_debugger.allow_hosts = 192.168.1.1, 127.0.0.1
zend_debugger.expose_remotely = always
Опция allow_hosts в данном случае позволяет нам дебажить с локального хоста и с машины 192.168.1.1.
Запускаем Zend Studio. Выбираем место, в котором желаем остановиться во время выполнения (breakpoint). Делается это двойным щелчком по полоске левее номеров строк:
Breakpoint in Zend Studio


Производим следующие действия:
Действие над треугольничком
Действие над менюшкой

Далее открывается примерно такое диалоговое окно:
Указываем URL, по которому необходимо производить дебаг
Если все успешно - то дебагер после запуска встанет на первой адекватной строчке index.php (эту настройку тоже можно сменить, но не буду углубляться). Если дебагер не сработал, то, возможно, вам поможет мануал по установке, который я упомянул в самом начале. Основные горячие клавиши для работы с дебагом можно увидеть во всплывающих подсказках на кнопках управления непосредственно дебагом.
Таким образом, мне удалось запустить пошаговый дебаг в Zend Studio. Буду рад, если кому-то это сможет пригодиться.

2010-08-19

Установка Zen Coding в Zend Studio 8

Решил опробовать сегодня для себя Zen Coding. Скажу, что был приятно удивлен удобству и скорости набора HTML тэгов. Вы можете более подробно почитать о нем на просторах наших интернетов.
Сразу перейду к делу. Чтобы установить эту замечательную вещь в Zend Studio, необходимо сделать следующее:
  1. В студии в меню: Help -> Install new software... Вбиваем адрес http://download.eclipse.org/technology/dash/update/
  2. Выбираем Eclipse Monkey, и устанавливаем. Перезапускаем студию.
  3. Качаем скрипты Zen Coding для Aptana. Так как Aptana является плагином к Eclipse (как и наша Zend Studio) - эти скрипты нам подойдут.
  4. Распаковываем скрипты в корень проекта в папку scripts (да, проекта... централизованной установки нет).
  5. Обновляем все дерево проекта, чтобы плагин Eclipse Mokey "увидел" папку scripts.
Можно пользоваться. Но не очень это удобно без горячей клавиши.
Чтобы выставить горячую клавишу на скрипт Expand Abbreviation.js мне пришлось его немного подправить: строку
Key: M1+E
заменить
Key: M2+M3+E
Таким образом, комбинация для работы скрипта стала Shift + Alt + E. Прошлая комбинация Ctrl + E отказалась работать из-за конфликтов с уже существующими комбинациями, имеющими более высокий приоритет.

2010-08-08

SunSpider в Firefox (сравнение производительности JavaScript)

Решил провести тестирование скорости работы JavaScript трех версий популярного браузера:
  • Firefox 3.6.8
  • Firefox 4.0 beta 2
  • Minefield 4.0 beta 4 pre (ночная сборка 2010.08.08)
Потратив некоторое время в SunSpider, я получил довольно интересные и близкие к действительности результаты:

Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8

============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                  729.8ms +/- 1.7%
--------------------------------------------

  3d:                   118.6ms +/- 1.2%
    cube:                29.4ms +/- 3.8%
    morph:               36.6ms +/- 1.9%
    raytrace:            52.6ms +/- 2.7%

  access:               104.0ms +/- 2.4%
    binary-trees:        27.2ms +/- 3.8%
    fannkuch:            51.4ms +/- 1.3%
    nbody:               16.8ms +/- 3.3%
    nsieve:               8.6ms +/- 12.9%

  bitops:                29.4ms +/- 5.7%
    3bit-bits-in-byte:    1.0ms +/- 0.0%
    bits-in-byte:         8.2ms +/- 16.6%
    bitwise-and:          2.0ms +/- 0.0%
    nsieve-bits:         18.2ms +/- 3.1%

  controlflow:           31.0ms +/- 0.0%
    recursive:           31.0ms +/- 0.0%

  crypto:                37.2ms +/- 2.8%
    aes:                 22.0ms +/- 5.7%
    md5:                  9.6ms +/- 7.1%
    sha1:                 5.6ms +/- 12.2%

  date:                 126.0ms +/- 2.1%
    format-tofte:        62.4ms +/- 3.3%
    format-xparb:        63.6ms +/- 1.7%

  math:                  44.8ms +/- 20.7%
    cordic:              26.6ms +/- 35.1%
    partial-sums:        13.0ms +/- 0.0%
    spectral-norm:        5.2ms +/- 20.0%

  regexp:                40.8ms +/- 1.4%
    dna:                 40.8ms +/- 1.4%

  string:               198.0ms +/- 2.5%
    base64:               8.0ms +/- 0.0%
    fasta:               44.6ms +/- 3.2%
    tagcloud:            59.2ms +/- 3.8%
    unpack-code:         64.2ms +/- 3.2%
    validate-input:      22.0ms +/- 10.6%

Mozilla/5.0 (Windows; Windows NT 6.1; WOW64; rv:2.0b2) Gecko/20100720 Firefox/4.0b2

============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                  513.2ms +/- 0.9%
--------------------------------------------

  3d:                    77.8ms +/- 10.9%
    cube:                25.0ms +/- 0.0%
    morph:               21.0ms +/- 39.7%
    raytrace:            31.8ms +/- 1.7%

  access:                70.2ms +/- 1.9%
    binary-trees:        14.0ms +/- 0.0%
    fannkuch:            34.0ms +/- 0.0%
    nbody:               14.0ms +/- 6.3%
    nsieve:               8.2ms +/- 6.8%

  bitops:                22.4ms +/- 3.0%
    3bit-bits-in-byte:    0.4ms +/- 170.2%
    bits-in-byte:         7.0ms +/- 0.0%
    bitwise-and:          1.2ms +/- 46.3%
    nsieve-bits:         13.8ms +/- 4.0%

  controlflow:            6.2ms +/- 9.0%
    recursive:            6.2ms +/- 9.0%

  crypto:                28.8ms +/- 8.3%
    aes:                 17.6ms +/- 10.7%
    md5:                  7.2ms +/- 7.7%
    sha1:                 4.0ms +/- 0.0%

  date:                  68.8ms +/- 1.5%
    format-tofte:        43.4ms +/- 1.6%
    format-xparb:        25.4ms +/- 2.7%

  math:                  40.2ms +/- 4.0%
    cordic:              22.4ms +/- 3.0%
    partial-sums:        12.8ms +/- 4.3%
    spectral-norm:        5.0ms +/- 17.6%

  regexp:                45.0ms +/- 0.0%
    dna:                 45.0ms +/- 0.0%

  string:               153.8ms +/- 1.8%
    base64:               6.8ms +/- 8.2%
    fasta:               18.2ms +/- 3.1%
    tagcloud:            55.2ms +/- 2.9%
    unpack-code:         53.0ms +/- 1.7%
    validate-input:      20.6ms +/- 9.2%

Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0b4pre) Gecko/20100808 Minefield/4.0b4pre

============================================
RESULTS (means and 95% confidence intervals)
--------------------------------------------
Total:                  479.2ms +/- 1.5%
--------------------------------------------

  3d:                    76.6ms +/- 10.6%
    cube:                24.0ms +/- 3.7%
    morph:               18.8ms +/- 37.8%
    raytrace:            33.8ms +/- 3.1%

  access:                65.8ms +/- 1.6%
    binary-trees:        14.2ms +/- 7.3%
    fannkuch:            36.4ms +/- 3.1%
    nbody:                6.8ms +/- 8.2%
    nsieve:               8.4ms +/- 8.1%

  bitops:                18.8ms +/- 5.5%
    3bit-bits-in-byte:    0.2ms +/- 278.0%
    bits-in-byte:         7.6ms +/- 9.0%
    bitwise-and:          1.2ms +/- 46.3%
    nsieve-bits:          9.8ms +/- 5.7%

  controlflow:            6.0ms +/- 0.0%
    recursive:            6.0ms +/- 0.0%

  crypto:                26.4ms +/- 5.4%
    aes:                 15.4ms +/- 4.4%
    md5:                  7.4ms +/- 9.2%
    sha1:                 3.6ms +/- 18.9%

  date:                  66.2ms +/- 0.8%
    format-tofte:        40.4ms +/- 1.7%
    format-xparb:        25.8ms +/- 2.2%

  math:                  43.0ms +/- 2.0%
    cordic:              24.0ms +/- 0.0%
    partial-sums:        12.4ms +/- 5.5%
    spectral-norm:        6.6ms +/- 10.3%

  regexp:                43.6ms +/- 5.2%
    dna:                 43.6ms +/- 5.2%

  string:               132.8ms +/- 1.2%
    base64:               5.2ms +/- 10.7%
    fasta:               17.2ms +/- 3.2%
    tagcloud:            51.4ms +/- 4.4%
    unpack-code:         46.2ms +/- 7.5%
    validate-input:      12.8ms +/- 4.3%

Подводя итоги, становится видна тенденция, что новый браузер Firefox 4 от организации Mozilla будет обрабатывать JavaScript примерно в 1.5-2 раза шустрее, чем нынешний. Выход браузера запланирован на конец 2010 года.

2010-07-30

Права в Git и развертывание

Сегодня у меня был опыт, которым хотелось бы поделиться. Все началось с того, что наша контора (не без моей инициативы) перебралась с SVN на Git. То есть теперь в системе контроля версий мы помимо просто файлов еще храним и права доступа к ним.

Раньше было так: на девелоперской машине сайт /var/www/site был во владении основного пользователя и IDE могла спокойно работать с этими файлами. Если серверу нужны были права на запись в директорию, то директории выставлялись права 0777, благо через SVN дальше компьютера разработчика это не уходило. Был такой вот мелочный хак.

Все бы хорошо, но после перехода на Git, отправлять на продакшн права 0777 было бы совсем нехорошо. Решением этой дилеммы стал запуск сервера apache от основного юзера операционки. В Ubuntu ключевой файл находится в следующем месте:

/etc/apache2/envvars

В нем следует изменить строки


export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data


на


export APACHE_RUN_USER=user
export APACHE_RUN_GROUP=user

Где user - имя основного юзера системы.
И стало щастье и IDE, и веб-серверу. В итоге мы можем хранить в Git "правильные" права и разрабатывать приложение в любимом текстовом редакторе запущенном не от www-data или, что еще хуже root'а.


P.S. Под основным юзером я имел ввиду юзера, который собственно работает за компьютером.

2010-07-15

Игнорирование изменений пробельного пространства в svn diff

Иногда, работая над проектами, мы изменяем код так, чтобы он был более удобочитаем / больше подходил под выбранный стиль кодирования / удаляем пробелы с концов строк. Работая в команде, это порой может очень мешать просматривать логические изменения кода.

Команда svn diff не поддерживает функции игнорирования изменений пробелов и табов. Но зато GNU программа diff умеет это делать.

Чтобы использовать стороннюю diff команду в svn diff, нужно воспользоваться ключом -x.
Если мы желаем напрямую сравнить два файла, игнорируя пробелы, то нам следует использовать diff -uw /path/to/file1 /path/to/file2

Если мы желаем посмотреть наши локальные изменения, игнорируя пробелы, то нам нужна следующая команда:

svn diff --diff-cmd diff -x -uw /path/to/file

В этом случае мы больше не увидим изменений, которые были сделаны исключительно из эстетических соображений.

Это был относительно вольный перевод этой записки:
http://goo.gl/DnKh

2010-06-19

И снова коротко о множественных формах в Zend Framework

Довольно часто (сплошь и рядом) приходится выводить слова, принципы написания которых зависят от числительного, с которым они связаны.
В моем проекте http://spaceismine.org/ к каждой статье выводится количество просмотров. Если дописывать после количества слово "просмотров", то это не всегда будет корректно. Наверное, я достаточно сложно изъясняюсь. Попытаюсь поставить задачу и расписать способ ее решения.
Задача: сделать вывод вместо:
Прочитано раз: 1 / Прочитано раз: 3 / Прочитано раз: 11
такой:
Прочитано 1 раз / Прочитано 3 раза / Прочитано 11 раз
Не самый удачный пример на слове "раз", так как форма 1 и 11 не отличаются. В большинстве случаев они будут все же разными:
1 просмотр / 3 просмотра / 11 просмотров
В русском языке, таким образом, имеется три множественные формы: "просмотр", "просмотра", "просмотров". Начиная с версии 1.9, Zend Framework сильно облегчает решение такого рода задач.
Решение: итак, логика вывода у нас работает во view. И по такому случаю уже есть view helper translate. Пишем следующее:
Прочитано <?php
echo $article->views, ' ';
echo $this->translate(array('раз', 'раза', 'раз', intval($article->views), 'ru'));
?>
И получаем желаемый вывод.

2010-06-09

Медленный sendmail

Сегодня моя запись будет довольно короткой. Очередные грабли попались мне при отладке отправки сообщений на почту на локальной машине. Проблема была в очень медленной отправке почты посредством Zend_Mail, который по умолчанию использует транспорт Zend_Mail_Transport_Sendmail, то есть, грубо говоря, программу sendmail. Одно письмо отправлялось около минуты. Начав ковыряться в логах, я обнаружил, что в /var/log/maillog.err пишутся примерно следующие строчки (взяты не из моих логов, так как свои сейчас под рукой не имею):
Nov 16 18:15:32 desk sendmail[3106]: My unqualified host name (desk) unknown; sleeping for retry
Nov 16 18:16:32 desk sendmail[3106]: unable to qualify my own domain name (desk) -- using short name
Я для локальных адресов использую домены типа site.local (прописываю в /etc/hosts соответствие на петлю 127.0.0.1). При этом имя машины, ссылаясь на приведенные лже-записи логов, у меня desk - имя машины. Оно же записано в файле /etc/hostname

Решение: делаем vim /etc/hostname, меняем desk на desk.local, радуемся быстрой работе sendmail :)

2010-06-07

2 подводных камня и PHPUnit

С недавних пор решил встать на путь истинный и пока я еще совсем новичок в юнит-тестировании. Сегодня споткнулся на некоторых очень неприятных вещах. Использовал PHP 5.3.2 + PHPUnit 3.4.14 + Zend Framework 1.10.5
  1. Оказалось, что нельзя в классе, унаследованном от PHPUnit_Framework_TestCase, то есть в тест кейсе использовать свойства класса. Я пытался делать так: в одном методе-тесте в свойство записываю, в другом методе-тесте считываю. Это не работает. Свойство во втором тесте было пустым.
  2. Этот подводный камень очень близок к первому. Аннотация @dataProvider provider является поставщиком данных для тестового метода, но эти данные генерируются в момент создания объекта класса PHPUnit_Framework_TestCase, а не непосредственно перед запуском теста. То есть, опять же, если вы в провайдере используете свойства класса, которые заполняются во время прохождения тестов, то provider вернет пустое значение. Если быть точнее, он вернет значение таким, какое оно было на начало создания объекта класса.
  3. И еще один камень. Zend Studio генерирует тест кейсы и тесты, основываясь на существующих методах классов, что несомненно удобно. Но есть одна проблема: она также генерирует пустой конструктор, который является виной бага [#ZF-4496]. Суть бага в следующем. Если вы используете аннотацию @dataProvider в классе с конструктором, вы будете получать сообщение об ошибке тестов примерно следующего содержания Missing argument 1 for FooTest::testProvider(). Эта ошибка проявляется, если у класса, унаследованного от PHPUnit_Framework_TestCase существует конструктор. Конечно же от нее можно спастись, удалив ненужный конструктор.
Из первых двух "находок" можно сделать вывод: data provider методы могут быть спокойно описаны как static.
P.S. Ушел продолжать учить матчасть.

2010-06-02

Структура директорий и названия классов

Хотелось бы поведать свои находки в области наиболее удобной и даже несколько zend-way структуры директорий для проекта.
Глядя на исходники библиотеки ZF, мне хотелось использовать такое же именование классов внутри папки application. Я выбрал такой путь в котором папка application содержит в себе все классы, необходимые для работы проекта. Таким образом, у меня в папке application появились папки plugins, forms, models, controllers.
Как же правильно сделать так, чтобы все нормально функционировало и в файле Articles.php был класс Model_Articles вместо класса Articles? Это нужно, чтобы избавиться от старого метода автозагрузчика, который запускался следующим образом в файле Bootstrap.php и подключал все пространства имен (зачастую это совершенно излишне):
protected function _initAutoload()
{
  $loader = Zend_Loader_Autoloader::getInstance();
  $loader->setFallbackAutoloader(true);
}
В этом случае на помощь нам может прийти следующий метод нашего класса Bootstrap:
protected function _initAutoload()
{
  $loader = Zend_Loader_Autoloader::getInstance();
  $moduleLoader = new Zend_Application_Module_Autoloader(array(
    'namespace' => '',
    'basePath'  => APPLICATION_PATH,
  ));
  return $moduleLoader;
}
Таким образом мы создаем модуль автолоадера для загрузки файлов именно нашего приложения, то есть префикс неймспэйса у нас получается пустым и корневая директория - APPLICATION_PATH. Это позволит создавать классы (см. структуру директорий выше) с именами Model_Ratings, Model_Articles. А также уходить вглубь директорий, например положить класс Model_Row_Article в директорию application/models/Row/Article.php В стиле ZF? По-моему, вполне :)

2010-05-24

Дружим XAMPP с ImageMagick

Необходимо мне вдруг стало отлаживать мой хобби-проект http://spaceismine.org/ на Windows-машине, который в production-версии работает на Fedora. А на linux-системах нет проблем с установкой расширений, подобных imagick. Для Fedora, к примеру, достаточно установить расширение через yum и перезапустить apache:
yum install php-pecl-imagick
service httpd restart
В Windows же не все так просто. Менеджер пакетов PECL под окнами очень капризен и сразу работать не хочет. Для него нужны танцы с бубном, описанные в мануалах. Я решил пойти слегка другим путем: установить imagick, вручную прикрутив его к php.
В целом, ImageMagick - открытое бесплатное программное обеспечение, которое служит для обработки графической информации. А imagick - это php-wrapper (обвязка) для библиотек ImageMagick. Файлы, которые мне понадобились:

http://www.imagemagick.org/download/binaries/ImageMagick-6.6.2-0-Q16-windows-dll.exe
http://valokuva.org/builds/ext/vc9/ts/imagick/2010-05-24_1007/php_imagick_ts.dll

Был выбран wrapper thread-safe, так как версия php, которая была установлена в XAMPP была так же thread-safe. В итоге, я установил ImageMagick и скопировал скачанный php_imagick_ts.dll в место:
C:\xampp\php\ext\php_imagick_ts.dll
И тут мне попался огромный подводный камень. Проблемы возникли с тем, что php в XAMPP был скомпилирован с помощью Visual Studio 6.0, а модуль php_imagick_ts.dll - в Visual Studio 9.0 и из-за разных подписей они вместе напрочь отказались работать. А модуль imagick, скомпилированный в VC6 найти так и не удалось.
Я взглянул на версию php, она была 5.3.1, а на production'е у меня 5.3.2. Не очень страшно, но захотелось все же обновить и php. Итак моя, казалось бы безобидная идея, превращается в эпопею. :)
Что ж, я люблю все новое и решил выкачать thread-safe php, собранный в VC9, чтобы он был совместим с imagick. Долго искать не пришлось.

http://windows.php.net/downloads/releases/php-5.3.2-Win32-VC9-x86.zip

Итак, переименовав на случай отката C:\xampp\php в C:\xampp\php5vc6, я распаковал содержимое свежего php в чистую папку C:\xampp\php. Затем скопировал модуль imagick в C:\xampp\php\ext\php_imagick_ts.dll
Понадобилось скопировать C:\xampp\php\php.ini-development в C:\xampp\php\php.ini, так как последнего не было на месте. Также пришлось немного подкорректировать этот дефолтный php.ini, патч (unified diff) примерно такой:
--- C:\xampp\php\php.ini Mon May 24 16:09:59 2010 UTC
+++ C:\xampp\php\php.ini-development Wed Mar 3 13:40:56 2010 UTC
@@ -784,7 +784,7 @@
 ;include_path = ".:/php/includes"
 ;
 ; Windows: "\path1;\path2"
-include_path = ".;C:\xampp\php\PEAR"
+;include_path = ".;c:\php\includes"
 ;
 ; PHP's default setting for include_path is ".;/path/to/php/pear"
 ; http://php.net/include-path
@@ -806,7 +806,7 @@
 ; http://php.net/extension-dir
 ; extension_dir = "./"
 ; On windows:
-extension_dir = "ext"
+; extension_dir = "ext"
 
 ; Whether or not to enable the dl() function.  The dl() function does NOT work
 ; properly in multithreaded servers, such as IIS or Zeus, and is automatically
@@ -876,7 +876,7 @@
 
 ; Maximum allowed size for uploaded files.
 ; http://php.net/upload-max-filesize
-upload_max_filesize = 10M
+upload_max_filesize = 2M
 
 ; Maximum number of files that can be uploaded via a single request
 max_file_uploads = 20
@@ -948,7 +948,7 @@
 ;extension=php_curl.dll
 ;extension=php_dba.dll
 ;extension=php_exif.dll
-extension=php_fileinfo.dll
+;extension=php_fileinfo.dll
 ;extension=php_gd2.dll
 ;extension=php_gettext.dll
 ;extension=php_gmp.dll
@@ -956,17 +956,17 @@
 ;extension=php_imap.dll
 ;extension=php_interbase.dll
 ;extension=php_ldap.dll
-extension=php_mbstring.dll
+;extension=php_mbstring.dll
 ;extension=php_ming.dll
 ;extension=php_mssql.dll
-extension=php_mysql.dll
+;extension=php_mysql.dll
 ;extension=php_mysqli.dll
 ;extension=php_oci8.dll      ; Use with Oracle 10gR2 Instant Client
 ;extension=php_oci8_11g.dll  ; Use with Oracle 11g Instant Client
 ;extension=php_openssl.dll
 ;extension=php_pdo_firebird.dll
 ;extension=php_pdo_mssql.dll
-extension=php_pdo_mysql.dll
+;extension=php_pdo_mysql.dll
 ;extension=php_pdo_oci.dll
 ;extension=php_pdo_odbc.dll
 ;extension=php_pdo_pgsql.dll
@@ -985,7 +985,6 @@
 ;extension=php_xmlrpc.dll
 ;extension=php_xsl.dll
 ;extension=php_zip.dll
-extension=php_imagick_ts.dll
 
 ;;;;;;;;;;;;;;;;;;;
 ; Module Settings ;

Таким образом мне удалось подружить XAMPP и imagick, и обновить PHP в XAMPP до версии 5.3.2. Надеюсь, я смог спасти хотя бы кого-нибудь от граблей. :)

2010-05-23

Autocomplete в Zend Studio

Не всегда Zend Studio может определить тип переменной из контекста. Например, когда тип переменной становится ясен только во время интерпретации кода. Случается очень часто, на самом деле, например, когда мы пытаемся пробежаться по rowset'у в цикле foreach.
$usersRowset = $usersTable->fetchAll();
foreach ($usersRowset as $userRow) {
    $user->... // автокомплит в этом случае не сработает
}
И в таких случаях такая очень важная штука как автокомплит не работает. Класс может содержать огромное количество методов, названия которых вы вряд ли помните все наизусть.
Zend Studio большинство своих автокомплитов распарсивает из комментариев PHPDoc. Поэтому, чтобы заработал автокомплит, необходимо добавить комментарий PHPDoc
$usersRowset = $usersTable->fetchAll();
/* @var $userRow Zend_Db_Table_Row */
foreach ($usersRowset as $userRow) {
    $user->... // автокомплит работает :)
}