Авг 282013
 

Изучаем PHP. Пишем parser похожих запросов Yandex.

В жизни программиста очень часто возникает задача получения полезной информации из других источников. Это может быть всесторонняя оценка цен конкурентов по определённому товару, сбор изображений и описаний для автоматизации процесса загрузки новых позиций в интернет – магазин, поиск аудио и видео — информации и многое другое.

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

Рассмотрим на примере так называемый «parser – spider» (парсер – паук), в задачу которого будет входить сбор информации со страниц yandex для поиска похожих ключевых слов, которые мы будем использовать в раскрутке нашего проекта. И напишем данный парсер на PHP

Как же нам может помочь parser?
Мы получаем список сходных фраз, которыми пользуются посетители яндекса при поиске нашей тематики, и в дальнейшем сможем ориентироваться на них при написании материалов на нашем сайте, оцениваем спрос к тематике нашего сайта. А так же это даст нам возможность определить поисковые запросы с меньшей конкурентной борьбой сходной тематики, чтобы выйти по ним в ТОП поисковой системы Yandex. Как следствие, благодаря этой информации мы расширим аудиторию нашего проекта.

А откуда мы можем получить информацию по похожим поисковым запросам Yandex?
Дело в том, что при поиске Яндекс подсказывает сам, отображая блок внизу страницы: Вместе с «[фраза для поиска]» ищут — несколько подобных поисковых запросов.

Вверху в левой части каждой страницы указывает, сколько нашлось вариантов, например:
создать сайт — Нашлось 104 млн ответов

Итак, какие же задачи поставим перед скриптом – парсером?

Возможность рекурсивного парсинга похожих поисковых запросов с определением уровня вложенности
Если не найдено ни одного похожего запроса по указанной фразе (а такое тоже бывает), попробуем просмотреть запросы по её сокращению:

Например, если ввести фразу Создать Сайт Харьков, то похожих поисковых запросов не будет в выдаче поисковика, но если ввести: создать сайт – они появятся. Ограничимся урезанием фразы на одно слово вконце.

Обходить парсер будет не только одну фразу, а займётся обработкой целого списка из фраз (передадим массивом)
Сохранение найденных поисковых фраз и их встречаемостью в файл
Нюансы:

Поставим задержку на опрос поисковой системы (не меньше 2 секунд, а то и до 30 секунд в случайном порядке) на каждый поисковый запрос. Мы же не хотим, чтобы Яша нас «отругал» за плохое поведение?

<?php
function getURIContent($url){
        $tuCurl                         = curl_init();
        $tuData                         = '';
        if($tuCurl && is_resource($tuCurl)){
                $opts                   = array(
                CURLOPT_URL             => $url,
                CURLOPT_HTTPGET         => 1,
                CURLOPT_HEADER          => 0,
                CURLOPT_RETURNTRANSFER  => 1,
                CURLOPT_FOLLOWLOCATION  => 1,
                CURLOPT_BINARYTRANSFER  => 1,
                CURLOPT_AUTOREFERER     => 1,
                CURLOPT_CONNECTTIMEOUT  => 90,
                CURLOPT_USERAGENT       => $_SERVER['HTTP_USER_AGENT'],
                CURLOPT_COOKIEJAR       => dirname(__FILE__)."/cookie.txt",
                CURLOPT_COOKIEFILE      => dirname(__FILE__)."/cookie.txt",
                CURLOPT_REFERER         => $url
                                         );
        foreach($opts as $key=>$value){
          curl_setopt($tuCurl,$key,$value);
        }
        $tuData   = curl_exec($tuCurl);
        curl_close($tuCurl);
        }
        return $tuData;
}
function parseRecursive($question,$max_depth,$first = true){
    global $time_wait;
    $time_wait  = $time_wait < 2 ? 2 : $time_wait;
    $rand       = mt_rand($time_wait, $time_wait + 30);
    sleep($rand);
    $question   = urlencode($question);
    $where      = 'http://yandex.ua/yandsearch?text='.$question;
    $content    = getURIContent($where);
    $found      = false;
    if(!empty($content)){
        $how_many= array();
        preg_match_all('~<strong[^>]*?class="b-head-logo__text"[^>]*?>(.*?)</strong>~is',$content,$how_many);
        $numbers= '';
        if(is_array($how_many)
                     && isset($how_many[1][0])
                           && !empty($how_many[1][0])){
            $numbers   = trim($how_many[1][0]);
            $numbers   = preg_replace("~<br[^>]*?>~is",' ', $numbers);
            $numbers   = str_ireplace("&nbsp;",' ', $numbers);
            $numbers   = str_ireplace("\r\n",' ', $numbers);
            $numbers   = str_ireplace("\r",' ', $numbers);
            $numbers   = str_ireplace("\n",' ', $numbers);
            $numbers   = str_ireplace("\t",' ', $numbers);
            $numbers   = str_ireplace("\p",' ', $numbers);
            $numbers   = str_ireplace("\b",' ', $numbers);
            $numbers   = html_entity_decode($numbers,ENT_QUOTES,'UTF-8');
            $numbers   = strip_tags($numbers);
        }
        if(!empty($numbers)){
            $numbers = urldecode($question) . ' - ' . $numbers. "\n";
            $fp = fopen(WHERE_TO_SAVE,'a+');
            if($fp && is_resource($fp)){
                echo 'ADDING '.$numbers. "<br />\n";
                flock($fp,LOCK_EX);
                fwrite($fp,$numbers);
                flock($fp,LOCK_UN);
                fclose($fp);
            }
        }
        $related= array();
        $links  = array();
        preg_match_all('~<table[^>]*?class="b-related__table"[^>]*?>(.*?)</table>~is',$content,$related);
        /* <a[^>]*?href=("|\')([^"\']*?)(\1)[^>]*?>(.*?)</a> */
        if(is_array($related[1]) &&
                    isset($related[1][0])
                        && $max_depth){
            --$max_depth;
            preg_match_all('~<a[^>]*?href=("|\')([^"\']*?)(\1)[^>]*?>(.*?)</a>~is',$related[1][0],$links);
            if(is_array($links)
                           && isset($links[2])
                                && isset($links[4])
                                     && sizeof($links[2])
                                && sizeof($links[4])
                                     && $max_depth){
                $sizeof     = sizeof($links[4]);
                for($i = 0; $i < $sizeof; $i ++){
                    $text   = '';
                    $text   = trim($links[4][$i]);
                    $text   = preg_replace("~<br[^>]*?>~is",' ', $text);
                    $text   = str_ireplace("&nbsp;",' ', $text);
                    $text   = str_ireplace("\r\n",' ', $text);
                    $text   = str_ireplace("\r",' ', $text);
                    $text   = str_ireplace("\n",' ', $text);
                    $text   = str_ireplace("\t",' ', $text);
                    $text   = str_ireplace("\p",' ', $text);
                    $text   = str_ireplace("\b",' ', $text);
                    $text   = html_entity_decode($text,ENT_QUOTES,'UTF-8');
                    $text   = strip_tags($text);
                    if(!empty($links[2][$i]) && !empty($text)){
parseRecursive($text,$max_depth,false);
                    }
                }
            }
        } elseif (is_array($related[1]) && $max_depth){
            $question    = urldecode($question);
            $words= array();
            $words= explode(' ',$question);
            $sizeof= sizeof($words);
            $words= array_map('trim',$words);
            --$sizeof;
            $words= array_slice($words,0,$sizeof);
            $question    = join(' ',$words);
            if(strlen($question) > 4){
                --$max_depth;
                if($max_depth){
                parseRecursive($question,$max_depth,false);
                }
            }
        }
    }
}
ini_set('max_execution_time',999999);
ini_set('max_input_time',999999);
$max_depth      = 2;
$time_wait      = 2;
$questions      = array('создать сайт',
                          'сайт на joomla',
                          'создать сайт Харьков',
                          'сайт на wordpress');
define('WHERE_TO_SAVE',dirname(__FILE__).'/prases.txt');
if(!is_file(WHERE_TO_SAVE)){
    $fp  = fopen(WHERE_TO_SAVE,'w+');
    if($fp && is_resource($fp)){
        fclose($fp);
    }
    if(is_file(WHERE_TO_SAVE) && !is_writable(WHERE_TO_SAVE)){
        chmod(WHERE_TO_SAVE,0777);
    }
}
if(is_file(WHERE_TO_SAVE)){
    $fp  = fopen(WHERE_TO_SAVE,'w+');
    if($fp && is_resource($fp)){
        fclose($fp);
    }
}
if(is_file(WHERE_TO_SAVE) && is_writable(WHERE_TO_SAVE)){
    $sizeof     = sizeof($questions);
    for($i = 0; $i < $sizeof; $i ++){
        parseRecursive($questions[$i],$max_depth);
    };
};
?>

Итак, что же здесь происходит:

Для начала с помощью ini_set установим побольше время выполнения для скрипта.

В переменной $max_depth укажем, сколько вложенных уровней «обходить» (на какую глубину «погружаться») для сбора похожих фраз.

Например: $max_depth = 2; — находим похожие поисковые фразы, переходим по каждой из них, и собираем результаты по похожим уже на них поисковым фразам.

Совет: не делайте слишком большим уровень вложенности. Иначе сильно отклонитесь от первоначальной тематической фразы.

Переменной $time_wait указываем, сколько секунд ждать до следующего запроса к поисковику.

Обратите внимание – 2 секунды – это минимальное значение. Иначе сайт выдаст вам капчу или наложит бан по ай-пи адресу.

В массив $questions = array(‘создать сайт’,’сайт на joomla’,’создать сайт Харьков’,’сайт на wordpress’); — списком строк через запятую добавляем запросы для обработки parser ом.

Далее, определяем, существует ли файл prases.txt – в который мы и добавим найденный результат. Если не существует, создаём его и делаем доступным на запись.

После этого обходим массив $questions и передаём каждый запрос функции parseRecursive вместе с уровнем вложения.

(void) function parseRecursive($question,$max_depth,$first = true): принимает одну поисковую фразу (string)$questions[$i] и уровень вложенности поиска $max_depth, а так же неявный флаг (bool) $first, для определения, в какой раз подряд вызывается функция (для чего, рассмотрим ниже).

В функции мы кодируем для возможности передачи в виде запроса нашу ключевую фразу с помощью urlencode и получаем содержимое запроса в функции getURIContent, основанной на curl. После чего регулярным выражением ~]*?class=»b-head-logo__text»[^>]*?>(.*?)~is узнаём, сколько раз встречается данный поисковой запрос.

Очищаем полученный запрос от html и спец символов. Помещаем выражение и количество найденных страниц по этой поисковой фразе в файл prases.txt.

Исследуем содержимое полученной страницы на предмет содержания «похожих поисковых запросов» ~]*?class=»b-related__table»[^>]*?>(.*?)

~is.

Если похожие поисковые фразы найдены, извлекаем ссылки на них и их анкоры: ~]*?href=(«|’)([^»‘]*?)(\1)[^>]*?>(.*?)~is

При этом уменьшая на единицу наш уровень вложенности —$max_depth

Если уровень вложенности позволяет (отличен от нуля), передаём анкоры (текст, заключённый в тег a) рекурсивно в функцию parseRecursive. Обрабатываем следующий уровень.

Если же на странице не было найдено по указанной поисковой фразе ни одного результата, и вызов функции parseRecursive был осуществлён впервые (неявный флаг $first со значением true) то проверяем, содержит ли слова поисковый запрос? (Разбиваем по пробельному символу фразу на слова). Исключаем последнее слово, и передаём полученное словосочетание заново функции parseRecursive.

Примечание автора: для получения содержимого страниц по указанным поисковым запросам используется функция getURIContent, которая принимает адрес страницы и возвращает её содержимое.

Её работа основывается на curl, что даёт ряд преимуществ перед url wrapper ами функции file, fopen, file_get_contents и т.п.:

Более быстрый процесс получения информации
Передача referrer, cookie, user agent
Управление временем ожидания (таймаутом) на получение информации
Возможность корректно перейти по всем пере направлениям (Location:), если таковые встречаются
Бинарная передача данных
В следующих статьях мы поведаем Вам более подробно о возможностях функции curl и приведём другие интересные примеры её использования.

Замечание: каждый программист должен задаваться не только вопросом, что было сделано хорошо, но и «а что можно было бы сделать лучше» (оптимизация кода, повышение качества результата, удобная подача информации и т.п.).

Убрать дубли фраз, обнаруженные при поиске.
Для получения более достоверных вариантов проверять, встречается хотя бы одно слово из целевого поискового словосочетания, заданного в $questions в фразах, обнаруженных при многоуровневом обходе страниц
Каждый результат поиска записать в отдельный файл.
Визуализировать результат при помощи графиков
Задание для тех, кто учит parser ы на PHP:
Для выполнения этой же задачи напишите парсер, который обходит wordstat yandex

Авг 282013
 

Изучаем PHP. Тонкости экстремальной отладки скриптов.

Иногда сайт ведёт себя неадекватно. А разработка сайта всё затягивается. Очень трудно разобраться, в чём проблема, когда вообще выпадает Белый лист, и нигде нет никаких ошибок.

Дело в том, что многие проекты находятся на обычных хостингах, администрация которых действует по правилу «меньше знаешь, лучше спишь». Обычно под выполнение скриптов зарезервированы довольно скудные ресурсы. А вывод ошибок подавляется, или перенаправляется. Как же быть в этой ситуации?

Чем нам может помочь PHP при отладке скриптов?
Но, как показывает практика, для разработчиков администраторы предусматривают переопределение многих параметров.

Примечание автора: здесь будут рассмотрены подходы, которые касаются самого языка программирования PHP. Этот способ является более универсальным, чем рассмотрение методов, связанных с конфигурацией определённого серверного П.О.

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

<?php
ini_set("error_reporting",E_ALL & ~E_NOTICE);
ini_set("display_errors",1);
ini_set("error_log","");
function errPrint(){
    print_r(error_get_last());
}
register_shutdown_function("errPrint");
 ...
?>

Примечание: подход актуален для полного перехвата даже критических ошибок при отладке в PHP версии, равной или выше 5.2. В ином случае обратите внимание на эту часть статьи.

Разберём приведённый выше PHP код:

Описание функции ini_set:

(string) ini_set ($server_var_name,$server_var_value) – устанавливает значение $server_var_value для переменной среды выполнения PHP $server_var_name, в случае удачного присвоения возвращает значение переменной, иначе возвращает false.

Примечание автора: со всеми переменными окружения, значение которых можно переопределить, Вы можете ознакомиться здесь

Для начала мы включаем отображение ошибок ini_set(«display_errors»,1).

После этого мы устанавливаем значение для вывода ошибок «error_reporting», E_ALL & ~E_NOTICE, равное отображению всех ошибок, но без подсказок E_NOTICE.

Примечание автора: E_NOTICE – подсказки, как «правильно программировать» на усмотрение PHP интерпретатора. Зачастую, подсказки могут быть очень полезны при отладке сайта в целом, но при отладке в критических ситуациях они, в основном, несут малополезную информацию да ещё и в огромном количестве.

Затем мы переопределяем вывод ошибок в стандартный поток браузера посетителя ini_set(«error_log»,»»);.

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

Всё бы хорошо, но есть определённые критические ошибки, связанные с работой самого интерпретатора, которые могут вызвать прерывание в работе скрипта, и не будут выведены в поток обозревателя посетителя. Вот такой загадочный он наш PHP.

Но, благо, с версии 5.2 (о чудо!), заявленная ещё в php 4, функция — перехватчик register_shutdown_function заработала!.

Описание функции register_shutdown_function:

(void) register_shutdown_function ( callback $function ) — принимает имя функции $function, которая выполняется по завершению исполнения кода, даже во время возникновения критической ошибки с прерыванием работы скрипта.

Примечание автора: в данном случае функция $function должна быть определена (или подключена) до передачи в register_shutdown_function.

Определим функцию errPrint, которая распечатает последнюю ошибку print_r(error_get_last()) после завершения скрипта. И передадим название этой функции обработчику register_shutdown_function:

<?php
register_shutdown_function("errPrint");
?>

Описание функции error_get_last:

(array) error_get_last ( void ) – возвращает в виде массива информацию о последней случившейся ошибке. Массив содержит ключи «type» – тип ошибки, «message» – подробное сообщение об ошибке, «file» – путь к файлу, в котором произошла ошибка, «line» – номер строки, в которой произошла ошибка и номер символа.

А в нашем случае, последняя «случившаяся» ошибка – и есть та самая, которая приводит к остановке выполнения скрипта.

Благодаря такому подходу можно будет «отловить» буквально любую ошибку и получить детальную информацию о ней.

Не забывайте отключать информацию о выводе ошибок в браузер пользователя!
Но, после отладки php скрипта и устранения критической ошибки, не забывайте отключить полностью информацию о выводе ошибок в браузер пользователя. Связано это как с соображениями безопасности (многие ошибки и предупреждения могут доступной для злоумышленника конфиденциальную информацию, например: об абсолютном пути на сервере к Вашим скриптам, их местоположении и т.п.), а так же могут препятствовать нормальной инициализации сессий и работе функций, передающих заголовки header, так и с эстетической точки зрения не стоит выводить много малопонятной информации в браузер посетителя Вашего сайта. Для этого можно подавить полностью вывод ошибок. Или же переопределить вывод ошибок в файл с помощью функции ini_set(«error_log»,»путь к файлу ошибок, доступному на запись»);. При этом желательно, чтобы этот файл находился вне папок Вашего сайта, или доступ к файлу извне был полностью ограничен.

Примечание автора:

Приведём код полного подавления ошибок:

<?php
ini_set("error_reporting",0);
ini_set("display_errors",0);
ini_set("error_log","путь к файлу хранения ошибок");
?>

Так же для некоторых функций, которые всё равно генерируют ошибки и предупреждения, можно использовать оператор подавления ошибок. Для этого достаточно перед именем функции указать: @, например:

<?php
@mkdir("/site/cahce",0777);
?>

Хотя, настоятельно рекомендую Вам вместо этого «ленивого» способа с помощью условных операторов обработать все ситуации, которые приводят к появлению данной ошибки. Это добавит стабильности и увеличит «запас прочности» Ваших скриптов во время возникновения внештатных ситуаций, и оставит меньше «почвы для размышления» злоумышленникам.
Я всё равно вижу белую страницу!

Здесь может быть несколько причин:

Данный подход универсален для php 5.2 и выше. Для того, чтобы узнать версию Вашего PHP интерпретатора, добавьте в Ваш скрипт вызов функции phpinfo();
В первых строках будет описана версия PHP.

Если версия php ниже 5.2:

Для более ранних версий php Дмитрием Котеровым было разработано гибкое решение по перехвату критических ошибок, с ним Вы можете ознакомиться здесь

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

Но если Вы не нашли ничего полезного и в логах, предоставленных хостером — самая последняя инстанция: пошаговая отладка с помощью функций принудительной остановки exit или die в «проблемных местах» и распечаткой нужной информации обнаружить «неустойчивый код», и переписать его с учётом меньшей нагрузки.

Приведём пример выполнения пошаговой отладки с простой установкой флагов состояний:

<?php
function add_user_avatar($user_id,$avatar_name,$watermark){
...
};
echo "вызов функции add_user_avatar";
add_user_avatar($user_id,$avatar_name,$watermark);
echo "окончание работы функции add_user_avatar";
die();
?>

Если же Вы увидели белый лист раньше отображения «окончание работы функции add_user_avatar», значит проблему стоит искать именно в ходе выполнения данной функции add_user_avatar. Если же нет, мы «передвигаем» функцию die или exit ниже, обозначая вызов и завершение далее следующих функций подобным способом.

А в следующих статьях мы рассмотрим с Вами, как написать собственный перехватчик ошибок и расширить ресурсы, выделяемые хостингом для работы наших скриптов.

Авг 282013
 

Практикум PHP. Умная загрузка изображений.

Во время создания сайтов на PHP очень часто приходится работать с изображениями. Информация о работе с изображениями на PHP довольно разрозненная. Существует много громоздких и разноликих примеров.

Но на просторах интернета было найдено очень интересное решение.

Colin VEROT написал замечательный класс, который всего в несколько строк обработает загрузку изображения или выполнит действие над уже существующей фотографией на сервере. Класс основан на gd library и имеет множество настроек. Отлично справляется с php 4 + версии и изображениями png, gif, jpeg форматов.

Вот немногое из того, что класс умеет:

Обработка изображений из массива $_FILES
Работа над изображениями на сервере
Изменение размеров изображений (с сохранением пропорций или с «растягиванием» изображений). При этом доступны такие фильтры, как:
Не изменять/изменять изображения меньше указанной длинны/высоты
Не изменять/изменять изображения больше указанной длинны/высоты
Дополнение изображений указанным цветом до определённых размеров
Преобразования всех входящих изображений к одному типу
Переименование изображений или их перезапись, если указанный путь сохранения уже содержит такой файл
«Обрезка» области изображений по указанным параметрам
Наложение водяного знака watermark а и текста
Даёт управлять именем нового изображения, его расширением, правами, устанавливаемыми на файл
Обладает множеством встроенных эффектов — управляет яркостью и контрастностью, имеет несколько предопределённых эффектов (отражение, замена цветов – инвертирование, оттенки серого, размытие, поворот, рамки, скос и т.п.).
Кроме загрузки изображений, управляется и с загрузкой файлов (может контролировать загружаемые файлы по mime типам).
Скрипт ведёт статистику изменений, которую можно просмотреть в режиме отладки. И множество переменных для контроля.
А теперь давайте рассмотрим примеры обработки изображений из массива $_FILES с помощью данного класса, и почувствуйте, насколько всё просто:

Примечание автора: более подробные примеры и полное описание на английском Вы можете обнаружить прямо вначале файла класса class.upload.php

Для начала скачаем класс и поместим его в web директорию нашего сайта, подключаем его в нужном месте:

require_once(dirname(__FILE__)."/class.upload.php");

Создадим сам объект класса:

$handle = new Upload($file);

Где $file – путь к файлу, может быть так же объектом из массива $_FILES.

После чего укажем, куда сохранять файл:

$savepath = dirname(__FILE__)."/images";

Обработаем и сохраним файл:

$handle->Process($savepath);
$handle->Clean();

Вот и всё! Файл загружен. Осталось только проверить Его наличие по указанному пути $savepath с помощью функции file_exists().

bool file_exists ( string $filename ) — проверяет существование файла, указанного в строковой переменной $filename, если файл существует: возвращает true, иначе – false.

Переменные, которые можно просмотреть до обработки изображения и вызова [имя объекта]->Process([путь сохранения файла]): и до вызова [имя объекта]->clean():

$handle-> file_src_name – имя файла до обработки;
$handle->file_src_name_body – имя файла без расширения до обработки;
$handle->file_src_name_ext – расширение файла до обработки;
$handle->file_src_pathname – полный путь к файлу;
$handle->file_src_size – размер файла;
$handle->file_src_error – ошибка во время обработки/загрузки файла;
$handle->file_is_image – является ли файл изображением?
$handle->image_src_x – ширина изображения?
$handle->image_src_y – высота изображения?
$handle->image_src_pixels – сколько пикселей всего?
$handle->image_src_type – тип изображения.
Переменные, которые можно просмотреть после обработки изображения и вызова [имя объекта]->Process([путь сохранения файла]): и до вызова [имя объекта]->clean():

$handle-> file_dst_path – путь к файлу после обработки;
$handle->dst_name_body – имя файла без расширения после обработки;
$handle->file_dst_name_ext – расширение изображения после обработки;
$handle->file_dst_name – имя файла после обработки;
$handle->file_dst_pathname – полный путь к файлу после обработки;
$handle->image_dst_x – ширина обработанного изображения;
$handle->image_convert – тип преобразованного изображения.
А теперь давайте рассмотрим настройки, которые мы задаём после инициализации объекта класса Upload и до вызова [имя объекта]->Process([путь сохранения файла]):

Загрузить только «изображения»:

$handle->allowed = array("image/*");

Добавим ещё разрешение на загрузку для zip архивов:

$handle->allowed[]   = "application/x-zip";

А что делать, если Файл с таким именем уже существует? Не проблема:

$handle->file_auto_rename = true;

И файл будет переименован.
А как задать имя файла?

$handle->file_new_name_body  =  $image_name;

Преобразовать все загружаемые изображения к типу jpeg?

$handle->image_convert       = "jpg";

А как перезаписать файл, если он уже существует?

$handle->file_overwrite      = true;

Добавить к изображению Watermark слева внизу? Нет проблем!

$handle->image_watermark                 = PATH_SITE."/".$watermark_bigger;
$handle->image_watermark_position            = "LR";

Изменить размеры изображения до 500 на 500 с соблюдением пропорций?

$handle->image_resize        = true;
$handle->image_x             = 500;
$handle->image_y             = 500;
$handle->image_ratio         = true;

«Дополнить» изображения до указанного размера фоновым цветом при изменении размера?

$handle->image_resize            = true;
$handle->image_ratio_fill        = true;
$handle->image_ratio             = true;
$handle->image_background_color  = "#FF00FF";

Запретить изменять размеры изображений меньше 500 пикселей в ширину и длину?

$handle->image_ratio_no_zoom_in  = true;

«Растянуть» изображение без соблюдения пропорций?

$handle->image_ratio             = false;

Сменить права на файл после его обработки?

$handle->dir_chmod = 0777;

Попробуем сменить размер загружаемого файла (в байтах)?

$handle->file_max_size = "1024";

Запретим загрузку только определённых файлов по mime type?

$handle->forbidden = array("application/*");

Изменяем яркость изображения?

$handle->image_brightness = 40;

Отражаем изображение по горизонатли?

$handle->image_flip = "h";

Повернём изображение на 90 градусов?

$handle->image_rotate = 90;

Урежем изображение по заданному образцу на 50 пикселей сверху, 40 срава, 30 снизу и 20 слева?

$handle->image_crop = array(50,40,30,20);

Добавим к изображению белую рамку?

$handle->image_border = "3px";
$handle->image_border_color = "#FFFFFF";

Добавим эффект растворения к чёрному с отражением и 60 процентной прозрачностью отражения?

$handle->image_reflection_height = "25%";
$handle->image_default_color = "#000000";
$handle->image_reflection_opacity = 60;

А в следующей статье мы расширим класс с помощью curl (если поддерживается) или url wrapper ов функции fopen, file_get_contents для загрузки и сохранения изображений, расположенных на других сайтах.