6 CodeIgniter Hacks для мастеров

25 января 2018

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

Отказ от ответственности

    Не рекомендуется применять эти хаки к существующему проекту. Поскольку они меняют некоторые из основных функциональных возможностей CodeIgniter, это может сломать существующий код. Начиная с этой записи CodeIgniter 1.7.2 является последней стабильной версией. Эти хаки не гарантируют работу для будущих (или прошлых) выпусков. Даже если CodeIgniter разработан как совместимый с PHP 4, некоторые из этих хаков - нет. Таким образом, вам понадобится сервер с установленным PHP 5. nПри внесении каких-либо изменений в файлы внутри системной папки вы должны документировать его где-нибудь для дальнейшего использования. В следующий раз, когда вы обновите CodeIgniter (даже если они не выпускают обновления очень часто), вам может потребоваться повторное применение этих изменений.

1. Автозагрузка моделей PHP 5 Style

Цель

С левой стороны вы видите обычный способ загрузки модели в CodeIgniter изнутри контроллера. После этого взлома мы сможем создавать объекты напрямую. Код чище, и ваша IDE сможет распознавать типы объектов. Это позволяет использовать функции IDE, такие как автозаполнение или предварительная документация.

Есть еще два побочных эффекта этого взлома. Во-первых, вам больше не требуется расширять класс Model:

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

Hack

Все, что нам нужно сделать, это добавить функцию автозагрузчика в стиле PHP 5.

Добавьте этот код в конец системного приложения config config.php:

<?php
// ...
function __autoload($class) {
    if (file_exists(APPPATH."models/".strtolower($class).EXT)) {
        include_once(APPPATH."models/".strtolower($class).EXT);
    }
}
?>

Если вы заинтересованы в применении этого взлома для контроллеров, вы можете использовать этот код:

<?php
// ...
function __autoload($class) {
    if (file_exists(APPPATH."models/".strtolower($class).EXT)) {
        include_once(APPPATH."models/".strtolower($class).EXT);
    } else if (file_exists(APPPATH."controllers/".strtolower($class).EXT)) {
        include_once(APPPATH."controllers/".strtolower($class).EXT);
    }
}
?>

Каждый раз, когда вы пытаетесь использовать класс, который не определен, эта функция __autoload вызывается первой. Он позаботится о загрузке файла класса.

2. Предотвращение столкновения имени контроллера модели-

Цель

Обычно вы не можете иметь одно и то же имя класса для модели и контроллера. Предположим, вы создали название модели Post:

class Post extends Model {
    // ...
}

Теперь у вас не может быть URL-адрес:

http: www.mysite.com после отображения 13

Причина в том, что это потребует от вас также иметь класс контроллера с именем «Почта». Создание такого класса приведет к фатальной ошибке PHP.

Но с этим взломом это станет возможным. И контроллер для этого URL-адреса будет выглядеть так:

// application/controllers/post.php
class Post_controller extends Controller {
    // ...
}

Обратите внимание на суффикс '_controller'.

Hack

Чтобы обойти эту проблему, обычно большинство людей добавляют суффикс '_model' к именам класса Model (например, Post_model). Объекты модели создаются и ссылаются по всему приложению, поэтому может показаться немного глупым, что все эти имена будут перемещаться с помощью «_model». Я думаю, что лучше добавить суффикс к Контроллерам вместо этого, поскольку они почти никогда не ссылаются на их имена классов в вашем коде.

Сначала нам нужно расширить класс Router. Создайте этот файл: «библиотеки приложений MY_Router.php»

class MY_Router extends CI_Router {
    var $suffix = '_controller';
    function MY_Router() {
        parent::CI_Router();
    }
    function set_class($class) {
        $this->class = $class . $this->suffix;
    }
    function controller_name() {
        if (strstr($this->class, $this->suffix)) {
            return str_replace($this->suffix, '', $this->class);
        }
        else {
            return $this->class;
        }
    }
}

Теперь отредактируйте строку «system codeigniter CodeIgniter.php» 153:

if ( ! file_exists(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->controller_name().EXT))

Тот же файл, строка 158:

include(APPPATH.'controllers/'.$RTR->fetch_directory().$RTR->controller_name().EXT);

Затем отредактируйте: «системные библиотеки Profiler.php», строка 323:

$output .= "<div style='color:#995300;font-weight:normal;padding:4px 0 4px 0'>".$this->CI->router->controller_name()."/".$this->CI->router->fetch_method()."</div>";

Вот и все. Имейте в виду, что с помощью этого хака вы должны поместить суффикс «_controller» во все имена классов контроллера. Но не в именах файлов или URL-адресах.

3. Проверка формы для уникальных значений

Цель

CodeIgniter имеет класс Form_validation. Он содержит несколько правил проверки:

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

С помощью этого хака вы сможете легко добавить это правило проверки в обработчик отправки формы:

$this->form_validation->set_rules('username', 'Username',
        'required|alpha_numeric|min_length[6]|unique[User.username]');

Обратите внимание на последнюю часть, в которой говорится «unique [User.username]». Это новое правило проверки просто называется «уникальным» и принимает параметр в квадратных скобках, который является «tablename.fieldname». Поэтому он будет проверять столбец «имя пользователя» таблицы «Пользователь», чтобы убедиться, что представленное значение еще не существует.

Аналогичным образом вы можете проверить наличие дубликатов электронной почты:

$this->form_validation->set_rules('email', 'E-mail',
        'required|valid_email|unique[User.email]');

И ваше приложение может отвечать надлежащими сообщениями об ошибках:

Hack

Это может считаться скорее расширением, чем взломом. Тем не менее, мы собираемся взять основную библиотеку CodeIgniter и улучшить ее.

Создать: "библиотеки приложений MY_Form_validation.php"

class MY_Form_validation extends CI_Form_validation {
    function unique($value, $params) {
        $CI =&get_instance();
        $CI->load->database();
        $CI->form_validation->set_message('unique',
            'The %s is already being used.');
        list($table, $field) = explode(".", $params, 2);
        $query = $CI->db->select($field)->from($table)
            ->where($field, $value)->limit(1)->get();
        if ($query->row()) {
            return false;
        } else {
            return true;
        }
    }
}

Теперь вы можете использовать уникальное правило проверки.

4. Запуск CodeIgniter из командной строки

Цель

Как и в названии, наша цель - запустить приложения CodeIgniter из командной строки. Это необходимо для создания заданий cron или выполнения более интенсивных операций, поэтому у вас нет ограничений на ресурсы веб-скрипта, таких как максимальное время выполнения.

Вот как это выглядит на моей локальной машине Windows:

Вышеупомянутый код будет похож на вызов этого URL-адреса:

http: www.mysite.com привет мир foo

Hack

Создайте файл «cli.php» в корне вашей папки CodeIgniter:

if (isset($_SERVER['REMOTE_ADDR'])) {
    die('Command Line Only!');
}
set_time_limit(0);
$_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'] = $argv[1];
require dirname(__FILE__) . '/index.php';

Если вы находитесь в среде Linux и хотите сделать этот сценарий самостоятельно выполнимым, вы можете добавить это как первую строку в cli.php:

#!/usr/bin/php

Если вы хотите, чтобы конкретный контроллер был только командной строкой, вы можете заблокировать веб-вызовы в конструкторе контроллера:

class Hello extends Controller {
    function __construct() {
        if (isset($_SERVER['REMOTE_ADDR'])) {
            die('Command Line Only!');
        }
        parent::Controller();
    }
    // ...
}

5. Добавление Doctrine ORM в CodeIgniter

Цель

Doctrine - популярный реляционный сопоставитель объектов для PHP. Добавив его в CodeIgniter, вы можете иметь очень мощный слой модели в своей структуре.

Hack

Просто установка Doctrine не очень «хакерская» сама по себе, поскольку мы можем просто добавить ее в качестве подключаемого модуля. Однако, после добавления, вашим классам модели необходимо будет расширить базовые классы Doctrine, а не класс CodeIgniter Model. Это полностью изменит способ работы слоя модели в рамках. Объекты, которые вы создаете, будут иметь постоянство базы данных, а также смогут связывать базы данных с другими объектами.

Выполните следующие действия:

    Create folder: application pluginsnCreate folder: plugins приложения doctrineDownload Doctrine (1.2 из этой статьи) nCopy из папки «lib» из Doctrine в: «приложения-домены приложений» nCreate »plugin-приложения doctrine_pi.php«
// system/application/plugins/doctrine_pi.php
// load Doctrine library
require_once APPPATH.'/plugins/doctrine/lib/Doctrine.php';
// load database configuration from CodeIgniter
require_once APPPATH.'/config/database.php';
// this will allow Doctrine to load Model classes automatically
spl_autoload_register(array('Doctrine', 'autoload'));
// we load our database coections into Doctrine_Manager
// this loop allows us to use multiple coections later o
foreach ($db as $coection_name => $db_values) {
    // first we must convert to dsn format
    $dsn = $db[$coection_name]['dbdriver'] .
        '://' . $db[$coection_name]['username'] .
        ':' . $db[$coection_name]['password'].
        '@' . $db[$coection_name]['hostname'] .
        '/' . $db[$coection_name]['database'];
    Doctrine_Manager::coection($dsn,$coection_name);
}
// CodeIgniter's Model class needs to be loaded
require_once BASEPATH.'/libraries/Model.php';
// telling Doctrine where our models are located
Doctrine::loadModels(APPPATH.'/models');

Затем отредактируйте «app config autoload.php», чтобы автозагрузить этот плагин Doctrine

$autoload['plugin'] = array('doctrine');

Также убедитесь, что ваша база данных настроена в «application config database.php».

Вот и все. Теперь вы можете создать Doctrine Models в своем приложении CodeIgniter. Прочтите мои учебные пособия по этому вопросу для получения дополнительной информации.

6. Запуск нескольких сайтов

Цель

Этот хак позволит вам запускать несколько сайтов из одной установки CodeIgniter. Каждый веб-сайт будет иметь свою собственную папку приложений, но все они будут иметь одну и ту же системную папку.

Hack

Установите CodeIgniter в любом месте сервера. Он не должен находиться под папкой веб-сайта. Затем выньте папку приложения из системной папки. И сделайте дополнительные копии, как показано на изображении выше, для каждого веб-сайта, который вы хотите запустить. Вы можете размещать эти папки приложений в любом месте, например, в каждой отдельной папке веб-сайта.

Теперь скопируйте файл index.php в корень каждой папки веб-сайта и отредактируйте его следующим образом:

На строке 26 поместите полный путь в системную папку:

$system_folder = dirname(__FILE__) . '../codeigniter/system';

На строке 43 поместите полный путь к папке приложения:

$application_folder = dirname(__FILE__) . '../application_site1';

Теперь вы можете иметь независимые веб-сайты, используя отдельные папки приложений, но используя одну и ту же системную папку.

Аналогичная реализация в Руководстве пользователя CodeIgniter вы также можете прочитать.

7. Разрешение всех типов файлов для загрузки

Цель

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

$this->load->library('upload');
$this->upload->set_allowed_types('jpg|jpeg|gif|png|zip');

Если вы не укажете какие-либо типы файлов, вы получите сообщение об ошибке от CodeIgniter: «Вы не указали допустимые типы файлов».

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

$this->load->library('upload');
$this->upload->set_allowed_types('*');

Hack

Для этого взлома мы собираемся изменить поведение класса Upload.

Создать файл: библиотеки приложений My_Upload.php

class MY_Upload extends CI_Upload {
    function is_allowed_filetype() {
        if (count($this->allowed_types) == 0 OR ! is_array($this->allowed_types))
        {
            $this->set_error('upload_no_file_types');
            return FALSE;
        }
        if (in_array("*", $this->allowed_types))
        {
            return TRUE;
        }
        $image_types = array('gif', 'jpg', 'jpeg', 'png', 'jpe');
        foreach ($this->allowed_types as $val)
        {
            $mime = $this->mimes_types(strtolower($val));
            // Images get some additional checks
            if (in_array($val, $image_types))
            {
                if (getimagesize($this->file_temp) === FALSE)
                {
                    return FALSE;
                }
            }
            if (is_array($mime))
            {
                if (in_array($this->file_type, $mime, TRUE))
                {
                    return TRUE;
                }
            }
            else
            {
                if ($mime == $this->file_type)
                {
                    return TRUE;
                }
            }
        }
        return FALSE;
    }
}

Вывод

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

Если вы знаете какие-либо другие интересные хаки или модификации, сообщите нам об этом в комментариях. Спасибо!

Получить нас в Твиттере или подписаться на Nettuts + RSS-канал для лучших учебных пособий по веб-разработке в Интернете. Готово

Готовы ли вы перейти на следующий уровень и начать получать прибыль от ваших скриптов и компонентов? Посмотрите наш сестра-рынок, CodeCanyon.