Быть может странно, но, несмотря на свою полезность, неявное преобразование типов в 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
, который весьма мощен и позволяет гибко и просто выставлять права доступа на файлы. Минус второго варианта — в платформозависимости кода и возможных при этом проблемах.
А если сваять обертку подобного типа:
function chmodx($file,$p_user,$p_group,$p_other) { $perm = $p_user * 64 + $p_group * 8 + $p_other; chmod($file,$perm); }
И запускать как chmodx($file,7,7,5)?
Ilviann Zed, отличный вариант, лучше чем то, что я предлагал))