Couple of days ago, Vim team released new version of their great text editor. Once I had a little time, that’s today, I upgraded all my boxes. There couple of new features that are particularly interesting:

Read the rest of this entry

,

Usage of Zend_Http_Client is pretty straight-forward:

$client = new Zend_Http_Client($uri);
$client->request(Zend_Http_Client::HEAD); // HTTP HEAD request

However, today, on my Ubuntu box I had real problems as HTTP client constantly ended in segmentation fault (SIGTERM in apache logs). When debugging, I noticed that it does so only if $uri contains so called “unwise” characters, such as spaces, “{“, “}”, “^” etc.

Going deeper, I reviewed the source code of Zend_Http_Client::setUri($uri) method, only to discover that it relies on Zend_Uri::factory($uri), to initialize the URLs. From there it was pretty simple. Zend_Uri is aware of “unwise” chars problem and disallows them by default (why exception thrown by Zend_Uri ended in SIGTERM is yet to discover, however). In order to allow such a characters:

Zend_Uri::setConfig(array('allow_unwise' => true));
$client = new Zend_Http_Client($uri); // $uri may contain unwise chars now

After issuing above instruction Zend_Uri accepts those unwisely formed URIs. Plus, you have to URL-encode white-spaces (i.e. make sure that white-spaces in query string, or actually in URI part after the host name are replaced with “%20″ char) to make them acceptable.

Further info available in offical documentation.

Please note, that I still think that having unreliable chars in URI is really bad practice. If you work with some system that already gone far on this path, it’s nice to have a method to actually consume such a wildly formed URIs. Kudos to Zend_Uri maintainers!

,

Sometimes, especially when dealing with variations of factory pattern, single method (namely factory()) can return objects of different types, so NetBeans is unable to guess the exact type of returned instance and as such cannot auto-complete. Indeed, you can setup return type using phpDoc syntax:

/**
 * @return Some_Base_Abstract_Class_Name
 */
public function factory($adapter)

but that doesn’t work if returned objects are specifications of more general abstract class (exactly the case with factory).

As it turned out, you can easily resolve this issue – just document your variable with @var, before calling factory() method:

/**
 * @var Some_Specific_Class $foo
 */
$foo = Magic::factory('adapterName');
$foo-> // and NetBeans opens pop-up list with available attributes and methods

The good news, you can use this method in any scope – it just works :) I love NetBeans!!

UPD: Well, actually NetBeans seems to be picky of scope – as reported by others (and confirmed by myself).

UPD1: Actually NetBeans handles this quite well, just use vdoc (review this and this for details)

,

В случае когда определенные файлы/каталоги не должны попадать под контроль версий, достаточно установить свойство svn:ignore:

svn propset svn:ignore *.pyc dirname

В случае если такое свойство уже существует:

svn propedit svn:ignore dirname

Например, на UMapper‘е для игнорирования авто-сгенеренных CAPTCHA файлов находящихся в каталоге /files/captcha и имеющих названия вида “cap_RANDOM_STRING”, я использовал следующую комманду:

svn propset svn:ignore cap_* /files/captcha/
,

Еще кое-что о развертке приложения с использованием svn. Бывает что нужно изменить все файлы или каталоги (а также подкаталоги), скажем сменить permission mask. Это легко сделать используя:

find . [pattern] -exec chmod +x '{}' \;

Однако, в наших каталогах, кроме собственно данных, находяться также системные папки Subversion – .svn, и изменения в них вноситься вручную никак не должны. Чтобы игнорировать все .svn каталоги, используем опцию -prune:

find .  -path '*/.svn' -prune -o -type d -print

Возвратяться все каталоги кроме .svn.

,

В случае если вы решили развернуть web-приложение с использованием Subversion, стоит позаботиться о том чтобы административные каталоги .svn были недоступны через http-протокол. Для этого используется либо файл .htaccess, либо (что предпочтительнее, но не всегда возможно) вносятся изменения в httpd.conf.

Для защиты каталогов от внешнего доступа в корневую директорию помещается файл .htaccess со следующим содержимым:

<IfModule mod_rewrite.c>
  RewriteRule ^(.*/)?\.svn/ - [F,L]
  ErrorDocument 403 "Access Forbidden"
</IfModule>

Для защиты всех каталогов .svn (а также каталогов CVS) в конфигурационный файл Apache – httpd.conf – вносится следующая директива:

<DirectoryMatch "^/.*/(\.svn|CVS)/">
  Order deny,allow
  Deny from all 
</DirectoryMatch>

Буквально это ознaчает, что все пути содержащие .svn или CVS будут плеваться 403 – Forbidden.

Удачи на дорогах!

,

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

1
2
3
4
$myArr = array();
if (!isset($myArr['needle'])) {
    printf('Ключ "%s" не найден!!', 'needle');
}

легко решит эту задачу. Однако когда ключей несколько стоит использовать array_diff:

1
2
3
4
5
6
$requiredParams = array('needle', 'anotherOne'); // список ключей
$myArr = array('someKey');
 
if ($params = array_diff($requiredParams, array_keys($myArr))) {
    printf('Следующие ключи не найденны: %s!!', implode(', ', $params));
}

В случае если все обязательные ключи найденны, результат выполнения функции будет равен пустому массиву (при преобразовании в булев, которое происходит автоматом внутри if(), пустой массив интерпритируется как false), соответственно блок не будет выполнен. Если же массив непустой, то блок if() будет выполнен.

Данный метод очень удобен, если вы имеете функцию/метод, который получает одним из аргументов массив, в котором должны содержаться какие-либо обязательные ключи, для корректного исполнения дальшейшего кода.

Удачных выходных!

На самом деле проблема встречается очень даже часто:

Дано две таблицы (tableA, tableB), в которых присутсвует семантически эквивалентная колонка, для простоты предположим что поле id, таблицы A, указывает на поле uid, таблицы B (простейший внешний ключ). Далее предположим нам нужно получить список пользователей из таблицы А, которые не представленны в таблице B. Как это сделать? Легко! Используем LEFT JOIN (обратите внимание на IS NULL):

SELECT a.* FROM tableA a LEFT JOIN tableB b ON a.id = b.uid WHERE b.uid IS NULL

Удачного дня!

, ,

Хотя это очевидно и подчеркивается в PHP мануале, тем не менее поймал себя на мысли, что неверно интерпретировал следующий код:

1
2
3
4
5
$a = 12;
$b = &$a;
unset($b); // удаляем ссылку
var_dump($b);
var_dump($a);

Результат исполнения:

NULL
int(12)

Таким образом, при удалении ссылки, удаляется именно ссылка, оригинальная переменная остается нетронутой, и указывает на все то же значение. В общем, в PHP, ссылки (reference) являются не чем иным, как алиасами (alias) – думать о них как об указателях (pointers) неправильно.

UPDATE: When you unset the reference, you just break the binding between variable name and variable content. This does not mean that variable content will be destroyed. Т.е. когда ссылка удаляется, на деле уничтожается лишь связь между именем переменной и ее значением. Это значит, что при уничтожении переменной путем unset(), значение не уничтожается.

Вопрос: Как, используя PHP5, показать содержимое определенного каталога?

Рецепт:

Легко! Используйте итераторы (в данном случае DirectoryIterator):

1
2
3
foreach (new DirectoryIterator('./') as $Item) {
    echo $Item->current();
}

Для просмотра доступных методов DirectoryIterator – смотрите в мануал.

N.B. Итератор DirectoryIterator возвращает объект собственного типа, т.е. $Item является объектом класса DirectoryIterator.

, ,