Быть может странно, но, несмотря на свою полезность, неявное преобразование типов в PHP подставило мне подножку при разработке скрипта. Ситуация проста - мне было необходимо написать скрипт, который забирал настройки из таблицы БД MySQL — права и нужную директорию — и создавал в ней вложенную директорию с заданными правами, а также менять права доступа на существующие файлы.

Права хранятся в виде числа — 777, например (полный доступ к директории для всех пользователей в UNIX-like системах). Если я задам число в коде как восьмеричное, то все будет в порядке (Я опустил получение данных из базы, т.к. это принципиально не важно):

<?php

$dir="/path/to/dir/";
$createDir="somedir";
$permissions=0775; //так задается число в восьмеричной системе исчисления
mkdir ($dir.$createDir,$permissions);
// или при смене прав
chmod($dir.$createDir,$permissions);

Восьмеричные числа и права доступа к файлам

Функции mkdir и chmod в качестве второго параметра — прав доступа — принимают восьмеричное число. И видно, что это работает. Но, только до тех пор, пока нет необходимости получать это число откуда-нибудь еще, а не из переменной в скрипте, тип и система исчисления которой явно заданы. К чему это приводит? Посмотрим:

<?php 

$dir="/path/to/dir/";
$createDir="somedir";
$permissions=775; //десятичное число
mkdir ($dir.$createDir,$permissions);
// или при смене прав
chmod($dir.$createDir,$permissions);

Восьмеричные числа и права доступа к файлам

<?php

$dir="/path/to/dir/";
$createDir="somedir";
$permissions="775"; //строка
mkdir ($dir.$createDir,$permissions);
// или при смене прав
chmod($dir.$createDir,$permissions);

Восьмеричные числа и права доступа к файлам

Бах! И мы получили кривые права. В описании функции chmod мягонько так написано, что “возможна” ошибка в такой ситуации. Но не объясняется почему. А дело всё в неявном преобразовании типов данных PHP. Когда в функцию передается строковый параметр, он автоматически преобразуется в число (т.к. входной параметр — число). Но при этом почему-то не учитывается, в какой системе счисления это число. И это не смотря на то, что входной праметр прав у chmod и mkdir — восьмеричное число, и об этом указывается в документации. И, конечно же, по первому примеру видно, что PHP умеет работать с восьмеричными числами.

Для преобразования числа восьмеричной системы в PHP есть три функции — decoct (из десятичной в восьмеричную), octdec (из восьмеричной в десятичную) и base_convert (из какой-то в какую-то, например из двоичной в восьмеричную). octdec() возвращает действительное число, а вот две другие — decoct и base_convert — почему-то строку. И вот тут я напарываюсь на интересный момент — эти функции нормально отрабатывают, возвращают восьмеричные значения, но, похоже, что передать параметр с их помощью у меня не получится. А все потому, что возвращают они строковое значение, которое при передаче в функцию будет преобразовано в десятичный int, неправильно обработано функцией, и в результате — кривые права доступа к файлу. Получается, что всё равно придется что-то “хардкодить” — либо права доступа, либо команду UNIX-like систем chmod:

<?php 

`chmod {$permissions} {$pathToFile}`;

И то, и другое — те еще “костыли”: первый не позволит гибко менять права доступа, второй не будет работать, скажем, в Windows. Благо chmod в Windows вообще эффекта не имеет. Побочный плюс второго варианта в том, что можно использовать синтаксис команды chmod, который весьма мощен и позволяет гибко и просто выставлять права доступа на файлы. Минус второго варианта — в платформозависимости кода и возможных при этом проблемах.