четверг, 24 июля 2014 г.

Передать массив в функцию по ссылке

В PHP можно передавать массив в функцию по ссылке. Но что это значит? Лучше посмотреть на примере.
//Функция переводит фамилию в верхний регистр
function uppercase_surname ($person) {
    $person['surname'] = strtoupper($person['surname']);
}

$singer = array(
    'name' => 'Hilary',
    'surname' => 'Duff'
);

uppercase_surname($singer);
echo $singer['surname']; //"Duff" (т.е. регистр не изменился)

Здесь внутри функции происходит создание копии переданного массива. Разумеется, на это расходуется память и системные ресурсы сервера. Следовательно, при больших размерах передаваемого в функцию массива это может быть "тонким местом" производительности вашего скрипта.

Если функция предназначена для модификации данных, то разумно передавать в нее массив по ссылке. Это сэкономит ресурсы сервера на создание копии массива:
//Знак '&' просит php не копировать передаваемый массив, 
//а передать в функцию ссылку на него
function uppercase_surname (&$person) {
    $person['surname'] = strtoupper($person['surname']);
}

$singer = array(
    'name' => 'Hilary',
    'surname' => 'Duff'
);

uppercase_surname($singer);
echo $singer['surname']; //"DUFF" (регистр изменился)

Используйте тернарный оператор

В любом языке, в котором имеется тернарный оператор, хорошо его применять. Есть такой оператор и в php. Его синтаксис прост:
$age = 111;
echo $age > 65 ? 'Мудрец' : 'Юнец'; //Вернет 'Мудрец'

Применение этого оператора в некоторых случаях позволяет сократить код.

Плохо
function confidential_name ($confidential) {
    if ($confidential)
        return 'Ограниченный доступ';
    else
        return 'Без ограничений';
}

Хорошо
function confidential_name ($confidential) {
    return $confidential ? 'Ограниченный доступ' : 'Без ограничений';
}

вторник, 22 июля 2014 г.

Как грамотно настроить среду на стендах разработки

Как правило при разработки используются стенды:
1. develop - У каждого разработчика свой стенд. На нем он разрабатывает фичи для проекта.
2. test - Тестовый стенд, куда переносят разработанные фичи для тестирования.
3. production - Рабочий сайт.

Как в php можно сконфигурировать сервера, чтобы сервер автоматически подключал файлы конфигурации, специфичные для дева, теста и продакшена?

Вот один из возможных методов.

1. Создаем в корне сервера файл .htaccess и указываем в нем переменную для данного стенда:
 SetEnv APPLICATION_ENV develop

Это в том случае, если мы находимся на девелоперском стенде.
Для тестового стенда эта переменная задавалась бы так:
 SetEnv APPLICATION_ENV test

2. В файле конфигурации вашего приложения (к примеру, config.php) теперь можно использовать созданную переменную APPLICATION_ENV:
<?php
switch (getenv('APPLICATION_ENV')) {
    case 'production':
        require_once 'prod.php';
        break;
    case 'testing':
        require_once 'test.php';
        break;
    default:
        require_once 'dev.php';
        break;
}


Как видно, в зависимости от среды происходит подключение файла конфигурации, специфичного для данного стенда.

Другой способ задать переменную окружения - сделать это в php-скрипте, который будет отличаться на каждом из стендов:
//Определяем среду разработки
putenv("APPLICATION_ENV=production"); 

Здесь также в зависимости от среды можно производить подключение нужного файла конфигурации.

четверг, 3 июля 2014 г.

Не делайте лишний вызов функции

В данном фрагменте php-кода проверяется значение, возвращаемое функцией. При этом функция вызывается дважды, хотя можно было бы сохранить результат выполнения функции в переменную, и уже дальше работать с этой переменной.

Плохо

foreach($rules as $rule) {
    //1-й вызов функции
    if ($this->userMatchRule($user, $rule) === 'match') {
        return true;
    }
    //2-й вызов функции
    if ($this->userMatchRule($user, $rule) === 'notMatch') {
        return false;
    }
}

Хорошо

foreach($rules as $rule) {
    //Сохраняем результат работы ф-ции в переменную
    $matchResult = $this->userMatchRule($user, $rule);
    
    //Далее работаем с переменной
    if ($matchResult === 'match') {
        return true;
    }
    if ($matchResult === 'notMatch') {
        return false;
    }
}

Есть ли подстрока в строке

Иногда нужно проверить, есть ли какое-то слово в фразе. Например, есть ли слово "начальник" в названии должности сотрудника.

strpos() - регистрозависимый поиск:

Функция не найдет слово "начальник" во фразе "Начальник отдела продаж":

$text = 'Начальник отдела продаж';
$word = 'начальник';

//Регистрозависимый поиск
if (strpos($text, $word) !== false) {
    echo "Слово есть в тексте";
}

Данный скрипт ничего не выведет.

stripos() - регистроНЕзависимый поиск:

Здесь функция сможет найти слово "начальник" во фразе "Начальник отдела продаж":

$text = 'Начальник отдела продаж';
$word = 'начальник';

//РегистроНЕзависимый поиск
if (stripos($text, $word) !== false) {
    echo "Слово есть в тексте";
}

Этот скрипт найдет вхождение слова во фразе и выведет "Слово есть в тексте".

вторник, 1 июля 2014 г.

Это не проблема с кодировкой

Столкнулся однажды с такими результатами вывода на экран переменной php-скрипта:


Вот часть того скрипта, использующего класс системы Bitrix:
$res = CIBlockElement::GetList(
    Array("SORT"=>"ASC"),
    Array("IBLOCK_ID" => IBLOCK_AUTOFILL_GROUP_ID),
    false,
    false,
    Array("ID", "IBLOCK_ID", "NAME", "DATE_ACTIVE_FROM","PROPERTY_*")
);

while($ob = $res->GetNextElement()){
    $arFields = $ob->GetFields();
    //Вываодим переменную на экран
    echo $arFields['NAME'];
}

Чтобы браузер отобразил корректно русский текст, нужно ему помочь. В Firefox это делается так:


 После этого данные нашего echo отобразятся правильно:


В чем причина произошедшего?
Браузер не определил корректно кодировку по следующим причинам:
- не были переданы заголовки о кодировке;
- данные выводились на пустой странице без тега <meta charset="utf-8">.
Я попробовал добавить в вывод страницы указанный тег:
//Указываем тег кодировки
echo '<html><head><meta charset="utf-8"></head><body>';

while($ob = $res->GetNextElement()){

    echo '<pre>';
    $arFields = $ob->GetFields();
    echo $arFields['NAME'];
    echo '</pre>';
}
    
//Завершаем html-документ
echo '</body></html>';

Это привело к правильному отображению русских букв, поскольку браузер смог корректно определить кодировку благодаря наличию тега <meta charset="utf-8">

понедельник, 23 июня 2014 г.

Использование trigger_error()

Иногда в коде нужно сгенерировать пользовательское исключение.
Для этого отлично подходит встроенная в php функция trigger_error():

$jiraConn = getJiraConnection();
if(!$jiraConn) {
    trigger_error('No connection to Jira', E_USER_WARNING);
} 

При ошибке на страницу будет выведено сообщение:
Warning: No connection to Jira in /var/www/html/core/init.php on line 125

Благодаря такому написанию, можно быстро будет определить, почему ваше приложение не работает.