

Узнать подробнее о файловой структуре папок «core» и «engine» более подробно можно из документации CodeIgniter.Рассмотрим более детально модульную систему.
Компоненты классифицируются по трем видам:
Использование памяти: 3.18Мб
Запросов к базе данных: 0
Запросов в кеш: 2
Время работы: 0.0994
Использование памяти: 3.17Мб
Запросов к базе данных: 0
Запросов в кеш: 3
Время работы: 0.0743
Использование памяти: 0.89Мб
Запросов к базе данных: 0
Запросов в кеш: 2
Время работы: 0.0901
Использование памяти: 0.88Мб
Запросов к базе данных: 0
Запросов в кеш: 3
Время работы: 0.0655
Приведем данные о производительности cogear при конфигурации сайта usemac.ru (главная страница сайта — вывод ноды из сообществ и блогов, множество сложных шестеренок):Запросы в кэш, когда он выключен, обусловлены хранением в нем системных данных. Все показатели являются средними для данной конфигурации движка.
- Без ускорителя, кэш выключен
Использования памяти: 7.75Мб
Запросов к базе данных: 15
Запросов в кеш: 9
Время работы: 0.4225- Без ускорителя, кэш включен
Использования памяти: 7Мб
Запросов к базе данных: 2
Запросов в кеш: 27
Время работы: 0.3505- eAccelerator, кэш выключен
Использования памяти: 3.5Мб
Запросов к базе данных: 15
Запросов в кеш: 9
Время работы: 0.3653- eAccelerator, кэш включен
Использования памяти: 2.75Мб
Запросов к базе данных: 2
Запросов в кеш: 27
Время работы: 0.2676
;================================================== ; Название вашего компонента. ;================================================== ;-------------------------------------------------- ; Обязательные данные ;-------------------------------------------------- ; Название на английском title = Editor ; Описание на английском языке description = Add editor plugin for textarea ; Принадлежность к группе group = plugins ; Версия системы, необходимая для работы компонента core = 1.x ; Активность enabled = TRUE ; Позиция ; Определяет порядок очереди при загрузке системы position = 10 ;-------------------------------------------------- ; Любые другие параметры, которые будут доступны внутри системы. ;--------------------------------------------------
; Пути для роутера routes[] = "blogs/([\w_-]+)/(\w+)/? = community/$1/$2" ... ; Заменяет все пути routes[] = ":any = blogs/$1" .. ; Заменяет отсутствующий путь routes[] = ":empty = index/" routes[] = "(\d+)/? = index/page/$1" ; ============================================ ; Неверно ; ============================================ ; [routes] ; ============================================
Обратите внимание на то, что при возникновении конфликтных ситуаций будет использован путь того компонента, который загружается раньше (конфигурационный параметр position определяет порядок загрузки компонентов).
/* * Скрипт загрузится на всех версиях Internet Explorer */ myScript[ie].js /* * Скрипт загрузиться только на Internet Explorer 8, Opera 9.54, Chrome */ myScript[ie8|opera9.54|chrome].js /* * Аналогично работают стили * * Стиль загрузится только в FireFox 3.5 */ myStyle[firefox3.5].css /* * Стиль загрузится только в IE6 и IE7 */ myStyle[ie6|ie7].css
#element { /* Неправильно! background: url(../images/background.png); */ }
/* * Constructor * * @return void */ function __construct(){ parent::Controller(); } // ------------------------------------------------------------------------
/* * Show nodes on index page * * @param int $page Page to show. * @return void */ function index($page = 0){ ... } // ------------------------------------------------------------------------
/user_guide/introduction/Если метод introduction отсутствует у основного контроллера компонента user_guide, то основной метод index этого компонента получает строку «introduction» в качестве аргумента.
Если ваш модуль называется «example», то его иконка должна лежать по адресу "/gears/example/img/example.png".
/* * Созданная модель расположена по адресу /gears/test/models/test.php * * Вызовем модель из контроллера или другой модели. */ $this->test->some_method(); /* * Как видно из примера, модель загрузилась автоматически. */
/* * Модель расположена по адресу /gears/test/models/submodels/test.php */ $this->load->model('test submodels/test'); $this->test->some_method();
/* * Библиотека расположена по адресу /gears/test/library/sublibrary/mylib.php */ $this->load->library('test sublibrary/mylib');
[gears] editor = "Редактор" editor_description = "Описание модуля 'Редактор'" [editor] button = "Кнопка" ...
; Хорошо [editor] ... [editor_buttons] ... ; Плохо [editor] ... [buttons]
/* * Языковой файл */ [test] hello = "Приветствую тебя, Гость!"
/* * В коде контроллера, модели, библиотеки, хуков */ t('test.hello'); // равнозначно t('test hello'); // равнозначно t('test > hello'); // равнозначно t('!test hello'); /* * Вы можете задать активный раздел, чтобы не указывать его каждый раз явно */ d('test'); /* * Вызвав функцию d без аргумента, мы вернемся к предыдущему разделу перевода (если его не было, то к разделу 'global') */ d(); /* * % -- короткий суффикс для раздела global * * Данная запись аналогична t('global new'); */ /* * Вспомогательная функция * * Вторым аргументом идет значение по-умолчанию, если перевод не обнаружен * Третьим аргументом идет секция перевода, в которой следует поискать, если не установлено значение по-умолчанию */ // Если перевода переменной нет, то будет использовано значение аргумента at($field.'_description',$field['description']); /* * Если третий аргумент не указан, то ищется в разделе 'edit' * Если перевода переменной нет в текущем или указанном разделе, * то поиск будет произведен в разделе 'edit'. */ at($field.'_description',FALSE,'edit');
Помните, что в css-файлах необходимо прописывать абсолютный путь к изображениям.
; Выключен модуль или включен? enabled = TRUE
class Gear_Install extends Model{ /* * Constructor * * @return void */ function Install(){ parent::Model(); } // ------------------------------------------------------------------------ /* * Make everything you want during install * * @return void */ function install(){ ... // Вы можете вернуть строку по окончании установки // Она отобразится пользователю в оповещении о результате установки return t('gear.install_msg'); } // ------------------------------------------------------------------------ /* * Make everything you want during deinstall * * @return void */ function deinstall(){ ... return t('gear.deinstall_msg'); } // ------------------------------------------------------------------------
/** * Хук компонента comments для компонента nodes, контроллера index (по-умолчанию опускается в названии), метода show. * Исполняется до вызова адресуемого метода. * * @param object $CI Сущность движка. * @param int $id Первый аргумент обрабатываемого метода. * ... * @return void */ function comments_nodes_show($CI,$id[,$param,...]){ ... } // ------------------------------------------------------------------------
Если вы хотите изменить входящий аргумент для передачи его далее в адресуемый метод, то следует указать, что нужный аргумент проходит по ссылке, и вернуть все полученные аргументы.
/** * Хук компонента comments для компонента nodes, контроллера index (по-умолчанию опускается в названии), метода show. * Исполняется до вызова адресуемого метода. Изменяет аргументы адресуемого метода. * * @param object $CI Сущность движка. * @param int &$id Первый аргумент обрабатываемого метода. * ... * @return void */ function comments_nodes_show($CI,&$id[,$param,...]){ ... } // ------------------------------------------------------------------------
/** * Хук компонента comments для компонента nodes, контроллера index (по-умолчанию опускается в названии), метода show. * Выполняется после метода, поскольку функция хука имеет суффикс _after. * Дополнительный аргумент функции хука -- возвращаемое значение * исполненного адресуемого метода show (например, return $node). * * @param object $CI Сущность движка. * @param object $node Элемент, который возвращает адресуемый метод. * @param int $id Первый аргумент обрабатываемого метода. * ... * @return void */ function comments_nodes_show_after($CI,$node,$id[,$param,...]){ ... } // ------------------------------------------------------------------------
/** * Глобальный хук компонента mail. * Выполняется перед добавлением шаблона шапки сайта. * * @param object $CI Сущность движка. * ... * @return void */ function mail_header($CI){ ... } // ------------------------------------------------------------------------
/** * Глобальный хук компонента mail. * Выполняется после добавления шаблона шапки сайта. * * @param object $CI Сущность движка. * ... * @return void */ function mail_header_after($CI){ ... } // ------------------------------------------------------------------------
/** * Глобальный хук компонента mail. * Выполняется после выполнения вызываемого метода контроллера. * * @param object $CI Сущность движка. * ... * @return void */ function mail_after($CI){ ... } // ------------------------------------------------------------------------
/** * Глобальный хук компонента mail. * Выполняется перед добавлением шаблона подвала сайта. * * @param object $CI Сущность движка. * ... * @return void */ function mail_footer($CI){ ... } // ------------------------------------------------------------------------
/** * Глобальный хук компонента mail. * Выполняется после добавления шаблона подвала сайта. * * @param object $CI Сущность движка. * ... * @return void */ function mail_footer_after($CI){ ... } // ------------------------------------------------------------------------
Чтобы сделать метод модели подвластным системе хуков, необходимо добавить перед его именем "_".
class User extends Model{ ... /** * С данным методом хуки работать не будут. * * return void */ function login(){ ... } // ------------------------------------------------------------------------ /** * А вот с этим будут. Нижнее подчеркивание перед названием метода * только лишь обозначает его для системы хуков. Вызываться метод должен * по-прежнему $user->login(). * * return void */ function _login(){ ... } // ------------------------------------------------------------------------
Нижнее подчеркивание перед названием метода только лишь обозначает его для системы хуков. Вызываться метод должен по-прежнему (например, $user->login()).Поскольку названия моделей в системе не повторяются, то вызов хука выглядит следующим образом.
Внимание! Функция хука модели отличается знаком "_" после ее названия.
/** * Хук компонента mail модели User для метода login. * Компонент в данном случае не важен, т.к. модели имеют уникальные имена. * * @param object $User Объект модели. * @param int $id Первый аргумент обрабатываемого метода. * ... * @return void */ function mail_user_login_($User,$id[,$param,...]){ ... } // ------------------------------------------------------------------------
/** * Хук компонента mail модели User для метода login. * Компонент в данном случае не важен, т.к. модели имеют уникальные имена. * Изменяет параметр адресуемого метода. * * @param object $User Объект модели. * @param int $id Первый аргумент обрабатываемого метода. * ..... * @return void */ function mail_user_login_($User,&$id[,$param,...]){ ... } // ------------------------------------------------------------------------
/** * Хук компонента mail модели User для метода login. * Компонент в данном случае не важен, т.к. модели имеют уникальные имена. * Выполняется после адресуемого метода, поскольку имеет суффикс "_after". * * @param object $User Объект модели. * @param mixed $result Результат выполнения адресуемого метода. * @param int $id Первый аргумент обрабатываемого метода. * ... * @return void */ function mail_user_login_after_($User,$result,$id[,$param,...]){ ... } // ------------------------------------------------------------------------
Помните, виртуальные методы уникальны.
У одного класса не может быть два метода.
Если реальный метод существует, то виртуальный будет игнорироваться.
/** * Виртуальный метод Comments для контроллера Index компонента Nodes. * * @param object $CI Сущность движка. * @param object $id Номер ноды. * ... * @return void */ function nodes_comments($CI,$id){ $CI->comments->show($id); } // ------------------------------------------------------------------------ ... /* * Использование */ $CI->nodes->comments($id);
/** * Виртуальный метод captcha для модели Form. * * @param object $Form Объект модели. * ... * @return void */ function form_captcha_($Form,$name,$options){ $options['type'] = "captcha"; $options['template'] = "/captcha/templates/captcha.tpl"; $Form->add($name,$options); } // ------------------------------------------------------------------------ ... /* * Использование */ $CI->form->captcha($name,$options);
/** * Функция базового контроллера, отвечающая за вызов хука. * * @param string $class Класс. * @param string $method Метод. * @param string $class Суффикс. * @param array $args Аргументы. * @return void * */ function _hook($class,$method,$suffix,$args){ ... } // ------------------------------------------------------------------------
/* * Пример. * В любом месте любого контроллера бросаем "ловушку". */ ... ... /** * Вызовем хук из компонента mail. * /gears/mail/_hooks.php * * @param object $CI Сущность движка. * @param mixed $data Входные данные. * ... * @return void */ function mail_hkclass_hkmethod_hksuffix($CI,$data){ ... } // ------------------------------------------------------------------------
/* * Пример. * Изменим параметр, передаваемый хуку. * В любом месте любого контроллера бросаем ловушку. */ ... ... /** * Вызовем хук из компонента mail. * Вернем измененный параметр. * /gears/mail/_hooks.php * * @param object $CI Сущность движка. * @param mixed $data Входные данные. * ... * @return void */ function mail_hkclass_hkmethod_hksuffix($CI,$data){ ... return $data; } // ------------------------------------------------------------------------
// По-умолчанию время кэширования равно нулю = бесконечности $data = $this->cache->get('name'); if(!$data){ ... $this->cache->set('name',$data,3600); /** * Теги * * Можно было указать теги для данного ключа */ $this->cache->tags('tags1,tag2,tag3')->set('name',$data); $this->cache->set('name',$data,3600,'tags1,tag2,tag3'); } ... // Удалить запись $this->cache->clear('name'); // Удалить теги $this->cache->tags('tag1,tag2,tag3')->clear(); // Сбросить весь кеш $this->cache->flush();
// Сохраняем в сессию $this->session->set('name',$data); // По-умолчанию вернет данные в виде объекта $data = $this->session->get('name'); // Форсированный возврат данных в виде массива $data = $this->session->get('name',TRUE); // Удаление данных $this->session->remove('name'); // Синоним $this->session->delete('name');
// Вернет прочитанный файл в виде массива // Вносим изменения $data['site_url'] = 'cogear.ru'; $extra_data['template'] = 'default'; // Используем настроек файл как текущий // расширение можно не указывать $this->info->set(GEARS.'global/global') // Вносим изменения ->change($data) ->change($extra_data) ... // Сохраняем информацию в файл. ->compile();

На этапе предзагрузки будут подключены библиотеки компонентов (файл из папок «library» работающих шестеренок за исключением файлов с суффиксом ".class").
Все классы и модели загружаются автоматически, поэтому они должны обладать уникальными именами.Классы должны располагаться в папке «library» и иметь в имени файла суффикс ".class".
/* * Автоматическая загрузка класса из файла /gears/test/library/test.class.php */ $this->test->some_method(); /* * Автоматическая загрузка класса из файла /gears/test/models/some_model.php */ $this->some_model->some_method();
// Загрузка модели из файла /gears/some_gear/models/subdir/some_model.php $this->load->model('some_gear subdir/some_model');
Главное, чтобы между названиями шестеренки и модели/библиотеки присутствовал пробел.Библиотеки CodeIgniter загружаются «по старинке».
$this->load->library('form_validation');
/* * Метод query модели node, определяющий составляющий базового запроса для получения нод. * Благодаря префиксу "_" становится подвластен системе хуков. */ ... function _query(){ return $this->db->select('nodes.*',FALSE) // второй параметр позволяет избежать экранизации символа * ->get('nodes'); } ... function get($id){ $this->db->where('id',$id); return $this->query()->row(); } ... /* * Воздействуем на запрос ноды из компонента user через хуки. * Обратите внимание, что хук выполняется до вызова метода query, * поскольку не имеет суффикса _after. */ function user_node_query_($Node){ $CI =& get_instance(); $CI->db ->select('user.name,user.url_name,user.avatar') ->join('users','node.aid = users.id','inner'); } ...
$this->db->select('users.*',FALSE)->from('users')->where('id',$id); // Выстроенная цепочка выглядит так: // SELECT users.* FROM users WHERE id = "$id" // Появилась необходимость узнать количество сообщений у пользователя. $this->db->swop(); // Прошлая цепочка хранится в запасе, новая пока пустая. $pm_count = $this->db->where('uid',$id)->count_all_results('pm'); // Новая цепочка обнуляется после вызова метода count_all_results. // Возвращаемся к предыдущей цепочке и завершаем запрос. $user = $this->db->swop()->get(); // Исходная цепочка обнуляется
... function show_nodes($page = 0){ // Вызываем метод модели ноды, составляющий запрос. $this->node->query(); // Получаем количество страниц для навигации. $pager = $this->pager($page,$this->db->count_all_results('nodes',FALSE)); // При указании FALSE вторым аргументом мы сохраняем исходную цепочку запроса $nodes = $this->db->get('nodes',$pager['start'],$pager['limit'])->result(); ... }
Совет: Рекомендуем использовать Active Record, что позволит сократить расходы при переходе на другие типы баз данных.
Внимание! Запрос на поддомен транслируется в обычный запрос внтури роутера.
http://user.cogear.ru/admin/ => http://cogear.ru/user/admin/
... ; Файл конфигурации любой шестеренки ; Использует поддомен совпадающий с названием шестеренки subdomain = TRUE; ; Использует поддомены указанные явно subdomain[] = user subdomain[] = users ... ;Дополним нужный запрос путями routes[] = 'users(.*) = user/list$1'
Внимание! Вы можете использовать поддомены для блогов/сообществ и всего что захотите. Для этого необходимо указать особый путь роутера в файле конфигурации шестеренки.
routes[] = "% = community" ; отправляет все не зарезервированные поддомены на главный контроллер community ; news.cogear.ru/123-post.html => cogear.ru/community/news/123-post.html
http://mail.cogear.ru/ => http://cogear.ru/user/check/ — такой запрос не пройдет.
http://mail.cogear.ru/ => http://mail.cogear.ru/ajax/user/check/ — правильный запрос. Будет перенаправлен по нужному адресу.
; Если бы мы вызывали этот параметр, то PHP выдал бы ошибку. ; Наследуя объект настроек от "пустого класса", мы с безболезненно можем делать такие вызовы, ; применяя их, например, в условных операторах.
/* * Панель информации под каждой нодой представлена объектом breadcrumb. * Текст # должен быть заменен соответствующим кодом. */ ... $data['node_info'] = $this->bc->set('node_info') ->add('#дата и время#') ->add('#аватар и ссылка на профиль автора#') ->compile(TRUE); ... $this->_template('node',$data); /* * Выводим в панель информации ноды иконку для управления избранным * /gears/favorite/_hooks.php */ function favorite_breadcrumb_compile_($Breadcrumb,$return,$replace){ if($Breadcrumb->name == 'node_info'){ $node =& $Breadcrumb->data; $Breadcrumb->add('<a href="/favorite/manage/'.$node->id.'/"><img src="/gears/favorite/img/icon/manage.pnf"></a>') } }
$this->builder->h1('Some title','class','id',TRUE);
Последний аргумент, указывающий на вывод в шаблон или возврат результата, является необязательным.
// Ссылка генерируется в строковую переменную $link = $this->builder->a('Текст ссылки','http://адрес_ссылки','class','id'); // Ссылка выводит прямо в шаблон $this->builder->a('Текст ссылки','http://адрес_ссылки','class','id', TRUE); // Можно опустить необязательные параметры -- они не будут участвовать в генерировании строки кода. $link = $this->builder->a('Текст ссылки','http://адрес_ссылки'); // Изображение $this->builder->img('путь_к_изображению','class','id','alt','width','height','border',TRUE);
$fieldset = $this->builder->fieldset(TRUE).$html.$this->builder->fieldset(FALSE);
$this->msg->set('Операция прошла успешно!'); $this->msg->set('Не получилось выполнить запрос.',FALSE); // Или через обертку функции msg('Операция прошла успешно!') msg('Не получилось выполнить запрос.',FALSE);
$this->userinfo_tabs = new Panel('userinfo_tabs',FALSE,FALSE,'tabs'); $this->userinfo_tabs->data =& $user; $this->userinfo_tabs->set_title = FALSE; $this->userinfo_tabs->links_base = '/user/'.$user->url_name.'/'; $this->userinfo_tabs->set_active($active); $this->userinfo_tabs->compile(5);
$this->storage->set('section/name',$value); $this->storage->get('section/name'); $this->storage->remove('section/name'); // Можно использовать wildcard $this->storage->remove('section/*'); // Обертки для класса store('section/name',$value); $name = retrieve('section/name'); remove('section/*');

// Обычная проверка. $this->acl->check('nodes edit'); // Сокращенная проверка acl('nodes edit');

Модель прав доступа хранит в себе только запреты на доступ, поэтому после создания новых правил не забывайте настроить права доступа для групп.
// Обычный способ // Простой способ t('gears mail'); /* * Определим раздел перевода */ d('gears'); // Теперь его можно не указывать явно t('mail');
/* * Еще один пример указания разделов перевода. */ // Раздел -- user. d('user'); /* * Внимание! Запись */ /* * равно сильна записи */ /* * потому что "%" есть указатель на глобальный раздел. "%" = "!global" */ /* * В то время как раздел определен, никто не мешает нам узнать * значение переменной из другого раздела. */ // Текущий раздел все еще -- user. // Перейдем в другой раздел -- form. d('form'); /* * Вернемся в прошлый раздел. * Можно вызвать d('user') или просто d(), * что вернет нас к предыдущему разделу, который был указан ранее. */ d();
/* * раздел user * переменная lost_password * [user] * lost_password = "Письмо с новым паролем было отправлено на ваш почтовый ящик (%s)."; * new_password = "Уважаемый <b>%s</b>, ваш новый пароль -- <b>%s</b>."; * */ d('user');
/* * раздел user * переменная lost_password * [user] * lost_password = "Письмо с новым паролем было отправлено на ваш почтовый ящик (%s)."; * new_password = "Уважаемый <b>%s</b>, ваш новый пароль -- <b>%s</b>."; * */ d('user');
<h1>Привет, {_user name}!</h1>
<p>{_user new_password@$user->name@$new_password}</p>
/* * [mail] * new_pm = "Вам пришло %d (новое сообщение|новых сообщения|новых сообщений)." * */ // Вам пришло 1 новое сообщение | Вам пришло 3 новых сообщения | Вам пришло 5 новых сообщений
/* * [mail] * new_pm = "(новое сообщение|новых сообщения|новых сообщений)." * */ // новое сообщение | новых сообщения | новых сообщений
_404(); // Страница не найдена. _403(); // Доступ запрещен. error('Текст ошибки','Заголовок ошибки'); info(); // По умолчанию выведет просто "Пусто". info('Информация, которую необходимо донести до пользователя');
/* * Задаем форму. */ $this->form->set('user/register') ->input('name', 'validation'=>'required|min_length[3]', 'js_validation'=>'required|length[3,-1]', ... ) ) ->password('password', 'validation'=>'required', 'js_validation'=>'required', 'md5'=>TRUE, 'via_cookies'=>TRUE ... ) ) ->password('confirm_password', 'validation'=>'required|matches[password]', 'js_validation'=>'required|confirm[password]', 'md5'=>TRUE, 'via_cookies'=>TRUE, '' ... ) ) ->buttons('send'); /* * По-умолчанию данные отправляются по этому же адресу. * Принимаем данные, если они проходят проверку. */ if($result = $this->form->result()){ // Данная функция покажет нам оповещение, если операция пройдет успешно. $this->form->save('user',$result); redirect('/users/show/'.$this->form->insert_id); } /* * Если данные не прошли проверку, под соответствующими элементами * появятся сообщения об ошибках. * Если данные не были отправлены -- отображаем форму. */ $this->form->compile();
class Index extends Controller{ ... function createdit($id = FALSE){ $this->form->set('nodes/createdit') ->textarea('body') ->buttons('save'); // Устанавливаем значения для элементов формы $this->form->set_values($node); } if($result = $this->form->result()){ // Режим редактирования -- обновляем информацию redirect('/nodes/'.$node->id); } else { $this->form->save('nodes',$result); redirect('/nodes/'.$this->form->insert_id); } } $this->form->compile(); } ...
/* * [node] * name = "Заголовок материала" * name_description = "Отражает суть всего материала." */ $this->form->set('nodes/createdit') ->input('name',...) ...

$this->form->input('name',array('label'=>t('!node name'),'description'=>t('!node name_description')));
$this->form->set('user/register') ->input('name', // Проверка на стороне сервера 'validation'=>'required|min_length[3]', // Проверка на стороне клиента 'js_validation'=>'required|length[3,-1]', ... ) )
$this->form->set('nodes/createdit') ... /* * Предопределенным названиями простых submit являются * save, create, update, send, submit, create */ ... ->buttons('save'); /* * Если в форме присутствует элемент textarea для ввода html-кода, * Можно сделать предпросмотр результата ввода при помощи кнопки preview. */ ... ->buttons('preview','save'); /* * Кнопка delete автоматически спросит JavaScript-подтверждение (confirm) при нажатии. */ ... ->buttons('preview','save','delete'); /* * Данный вид записи аналогичен следующему. */ ... /* * Можно явно указать свойства кнопки. */ 'preview'=>array('value'=>t('!edit preview'),'type'=>'button','onclick'=>'preview()'), 'save'=>array('value'=>t('save'),'type'=>'submit'), 'reset'=>array('type'=>'reset') ));
/* * Все базовые параметры являются необязательными. */ // Проверка на стороне сервера 'validation'=>'required|min_length[3]', // Проверка на стороне клиента 'js_validation'=>'required|length[3,-1]', // Прямое указание метки 'label'=>t('name'), // Прямое указание описания 'description'=>t('name_description'), // Класс элемента 'class'=>'myClass', // Смещение метки после элемента -- полезно для radio, checkbox 'label_after'=>TRUE, // Скрыть метку 'label_hidden'=>TRUE, // Указываем значение элемента // Лучше указывать массив/объект значений методу $this->form->set_values($data) 'value'=>$value, // Задать элементу собственный шаблон // Позволяет не вносить изменения в стандартный шаблон формы 'template'=>GEARS."captcha/templates/captcha.tpl", // Прямое указание типа элемент // Указывается автоматически по названию вызванного метода 'type'=>'input', ... // У некоторых элементов типа file или image есть свои, особенные параметры. );
$this->form->text('name'); //Аналогично $this->form->input('name');

... /* * Варианты выбора для элементов типа select, image_select */ 'options'=>array( '0'=>'Вариант один', // Если тип image_select '1'=>'/gears/select/img/some_folder/some_icon.png' // Если нужно установить title к изображению выбора '2'=>array('Some Title','/gears/select/img/some_folder/some_icon.png') ), // Если можно выбрать несколько вариантов за раз 'multiple'=>TRUE, // Значение должно указывать на ключ массива значений 'value'=>0, // Если значения множественные, возможны два варианта 'value'=>array(0,1,2,3,4), // Такой вариант можно хранить в виде строки 'value'=>'0,1,2,3,4', ... );
...->fieldset('name','legend') ->input('name') ... // Можно явно закрыть fieldset, вызвав метод без параметров. ->filedset()->compile(); /* * Если fieldset или div не будет закрыт -- модель закроет его автоматически. */ ->div('id') ->input('name') ... // Вместо того, чтобы закрыть, определяем следующий div. // Предыдущий закроется автоматически. ->div('info') ->input('address') ... ->compile(); // Указанное выше верно и для fieldset.
... // Не указывайте required 'validation'=>'file[doc]', 'js_validation'=>'file[doc]', // Функция _mkdir создает директорию, если она не существует 'upload_path'=>_mkdir('./uploads/files/info/') ));
... // Указывать allowed_types не надо 'max_size'=>500, // в килобайтах 'overwrite'=>TRUE, // перезаписать, если такой файл уже есть /* * Далее идут параметры для пост-обработки */ 'resize'=>'400x300', 'resize_aspect'=>TRUE, // сохранить пропорции 'watermark'=>TRUE, // водный знак, // миниатюры будут созданы в подпапках 100x100 и 200x200 директории оригинала 'thumbs'=>array('100x100','200x200'), // поскольку миниатюры небольшие, водный знак не стоит использовать 'thumbs_watermark'=>FALSE, 'thumbs_aspect'=>'auto', 'thumbs_ratio'=>TRUE, 'thumbs_crop'=>TRUE, // Подрезать по точного размера )) ...
$data['image'] = '/uploads/images/image.png'; // Результат будет следующим 'original'=>'/uploads/images/image.png', '100x100'=>'/uploads/images/100x100/image.png', '200x200'=>'/uploads/images/200x200/image.png' );
/* * @param string Заголовок * @param mixed Конфигурация * @param boolean Использовать в title страницы * @param boolean Заменять последний элемент в title страницы */ $this->form->title('Регистрация',FALSE,TRUE,TRUE); /* * Описание формы */ $this->form->description('В данной форме вам предстоит пройти регистрацию на сайте.',array('class'=>'info'));
/* * Параметры для элемента datetime */ ... // с 1970 по 2010 'range'=>2010, // с 2008 по 2010 'range'=>'2008-2010', // с 2007 по 2010, 'range'=>'2007,2008,2009,2010', // с 2006 по 2007 'range'=>array('2006','2007'), 'value'=>'2009-05-30 10:10',
// Укажем типы столбцов // имя элемента => (текст заголовка, тип элемента, ширина столбца,[адрес картинки, выравнивание]) 'position'=>array(FALSE,'dragndrop','5%'), // drag and drop // Массив информации должен содержать путь к картинке в ячейке image ); // Указываем параметры сетки // Куда указывает ссылка/иконка // Очередность в $header обуславливает очередность в данном массиве 'link'=>array('/path/to/link','/path/to/icon'), // Какой параметр подставляется после пути ссылки 'link_add'=>array('id','url_name'), // По какому параметру происходит удаление элементов 'primary'=>'id', // Прячем заголовок сетки 'noname'=>TRUE, // Активируем drag-n-drop по полю // Используется для простой смены порядка очередности 'dragndrop'=>'position', // Динамическая отправка запроса при клике на checkbox'ы 'ajax'=>FALSE, // Динамическое удаление элементов при клике на checkbox'ы 'ajax_delete'=>FALSE ); // Собираем информацию для сетки // Обязательно в виде массива $data = $this->db->get('elements',20)->result_array(); foreach($data as &$item){ // Достраиваем полный путь для картинки, если его нет // Название элемента массива информации должно совпадать с элементом в заголовке $item['image'] = '/gears/some_gear/img/'.$item['image']; } // Задаем сетку. /* * Внимание! Если вы хотите, чтобы базовые функции удаления или перетаскивания работали * имя элемента сетки должно совпадать с названием таблицы базы данных. */ $this->form->grid('elements',$header,$data,$info); // Выводим форму в шаблон $this->form->compile();
// Добавляет шаблон info текущего компонента в порядке очереди. // Передает ему параметры массива $data $this->_template('info.tpl',$data); // Можно не указывать расширение файла .tpl $this->_template('info',$data); // Можно указать позицию в глобальном массиве шаблона. // Если на этой позиции есть элемент, он будет смещен по номеру выше. $this->_template('info',$data,5); // Можно заменить элемент на указанной позиции добавлением еще одного параметра. $this->_template('info',$data,5,TRUE); // Можно заменить элементы в определенном диапазоне. $this->_template('info',$data,5,100); // Можно заменить все элемент от указанного и до "подвала". $this->_template('info',$data,5,'all'); // Также можно упразднить параметр с информацией, если он не нужен. $this->_template('info',5,'all'); // Можно указать на шаблоны другого компонента $this->_template('mail show',$data); // Можно указать шаблон из папки текущего шаблона сайта // /templates/текущий_шаблон/ $this->_template('%show',$data); /* * Если шаблон написан на PHP-Native, он не будет компилироваться */ // Также можно упразднить параметр с информацией, если он не нужен. $this->_template('info.php',$data); /* * Передача готово кода осуществляется при помощи массива. */
$output = $this->_template('some_template',$data,TRUE);
// Пример для модели Breadcrumb // Выведет результат в порядке очереди $this->breadcrumb->compile(); // Вернет результат $info = $this->breadcrumb->compile(TRUE); // Выведет результат на определенную позицию $this->bc->compile(10); // Дополнительно заменит элемент по факту его присутствия $this->bc->compile(10,TRUE);
/** * Для более быстрого написания кода шаблонизатор выступает в качестве "обертки" для PHP */ {foreach ($nodes as $node)} {$node->body} {/foreach} /** * Скобки условия указывать не обязательно */ {foreach $nodes as $node} {$node->body} {/foreach} /** * Данный код превращается в следующий PHP-код */ <?php foreach($nodes as $node): ?> <?php endforeach;?> /* * Еще несколько операторов */ {if $a > $b} {$var} {elseif $a == $b} Просто текст. {else if $a < $b} А можно и так! {else} Привет, Гость! {/if} {switch gettype($var)} {case 'string'} Это строка! {break} {default} Это что-то другое! {/switch} /** * Вы можете вызывать любые функции следующим образом * ! -- без вывода * ? -- с выводом */ // Выведет "200" {? (100/2)*4} // Ничего не выведет, но сохранит информацию {! $i = 0} /** * Можно подключать другие шаблоны */ {include file="comment.tpl"} /** * Или даже так */ {include file=$path} /** * Опциональные параметры -- выводятся только при существовании переменной внутри скобок */ <div[ class="{$class}"][ id="{$id}"]> {$text} </div> /** * Применение функций к переменным * * Вы можете использовать любые функции PHP для модификации выводимых переменных */ {$text|default:'Пусто'} {$text|strtolower} {$text|stripslashes|strtolower|default:'Пусто'}

$pager = $this->pager($current_page,$total_pages); /* * Получаем массив с двумя параметрами -- start и limit */ $this->db->limit($pager['limit'],$pager['start'])->get('nodes');
// Указав имя формы в файле конфигурации редактора // Все текстовые поля будут заменены на редакторы forms = node_createdit,create_mail,pages_createdit // Использовать метод вызова редактора, как элемента формы $this->form->set('nodes/createdit') ... ->editor('body') ... // Добавить в массив editors объекта формы имя элемента textarea $this->form->editors[] = 'body';

// /gears/upload/_hooks.php ... /** * Add image upload button * * @param object * @return void */ function upload_editor_compile_after_($Editor){ js('/gears/upload/js/inline/image',FALSE,TRUE); } // ------------------------------------------------------------------------ ... // /gears/upload/js/inline/image.js window.addEvent('domready',function(){ for(name in editor.editors){ var e = editor.editors[name]; e.addButton({hotkey:'g',background:'/gears/upload/img/icon/images.png',action:'upload_image("'+e.el.id+'")'}) } }); function upload_image(textarea){ ed = editor.get(textarea); textarea = $type(textarea) == 'string' ? $(textarea) : textarea; // Вызываем окно загрузчика loader.ed = ed; loader.value = textarea.value; loader.frame('/upload/image/',500,420); }
// Пост-процессная обработка информация $node['body'] = $this->parser->process($node['body'],'textarea'); $this->_template('!nodes node',$node); // Подготовка информации для запись в базу данных осуществляется автоматически $data = $this->parser->prepare($data,$type);
/** * Add parser rules for jevix processing. * * @param object $Parser * @return void */ function jevix_parser_construct_(&$Parser){ /* * Можно по простому * $Parser->prepare['input'][] = 'parse_jevix|comment'; * А можно и на определенное место в массиве */ array_insert($Parser->prepare['textarea'],'parse_jevix|node',0); array_insert($Parser->prepare['comment'],'parse_jevix|comment',0); /* * Обратите внимание на строку с названием функции parse_jevix|node * parse_jevix -- вызов функции без параметров * parse_jevix|node -- вызов функции с параметром node */ // Вызов метода определенной модели // Вызов метода (с параметрами) определенной модели } // ------------------------------------------------------------------------ /** * Parse code with jevix * * @param string $value Recieved data. ... * @return string */ function parse_jevix($value,[$type = 'node',$autobr = TRUE]){ ... return $value; } // ------------------------------------------------------------------------
$this->user->is_logged(); // Авторизирован ли пользователь? $this->user->set('name','Гость'); $name = $this->user->get('name'); $id = $this->user->get('id');
/** * Пример расширения дополнительной информации о ноде шестеренкой favorite. * Add link-icon to node_info breadcrumb. * * @param object $Breadcrumb * @return void */ function favorites_breadcrumb_compile_(&$Breadcrumb){ if($Breadcrumb->name == 'node_info' && acl('favorites manage')){ $Breadcrumb->add('<a href="javascript:void(0)"> <img class="favorite-action" id="node-'.$Breadcrumb->data->id.'" src="/gears/favorites/img/icon/'.$status.'.png" title="'.t('!favorites '.$status).')"/> </a> ',0); } } // ------------------------------------------------------------------------
/** * Show user blog nodes * * @param string $url_name * @param int $page * @return void */ function index($url_name = FALSE, $page = 0){ // Если указан ЧПУ-адрес имени пользователя // Если первый аргумент не цифра и пользователь действительно существует // Выводим в шаблон информацию о пользователе // и навигационную панель $this->user->head($user,'blog'); title($user->name); // Проверяем возможность видеть неопубликованные ноды if(acl('blogs view_unpublished') OR $user->id == $this->user->get('id')){ $this->nodes->published = FALSE; } // При помощи Active Record задаем дополнительные параметры запроса } // Если первый параметр -- цифра, просто выводим список // всех нод из блогов, находящихся на искомой странице else { $page = $url_name; } // Выводим список нод $this->nodes->get($page); } // ------------------------------------------------------------------------
function hook_breadcrumb_compile_($Breadcrumb){ if($Breadcrumb->name == 'comment_header'){ $comment =& $Breadcrumb->data; // Установим дату на первую позицию массива элементов заголовка комментария $Breadcrumb->add(t('!comment created_date').' '.df($comment->created_date),0); // df -- вспомогательный метод (сокращение от англ. DateFormat) } }
; widgets/stats.info. ; Пример файла с конфигурацией some_param = TRUE [group_params] param1 = 0 param2 = 1 param3 = 2
/** * Process stats widget * * @param object $CI * @param array $config * @return mixed */ function stats_widget($CI,$config){ if($config->some_param == TRUE){ $output = ''; foreach($config->group as $key=>$value){ $output .= 'Widget param <strong>'.$key.'</strong> = '.$value.' '; } return $output; } return FALSE; }
[widgets] stats="Статистика";

// Контроллер ... function __construct(){ parent::Controller(); $this->no_sidebar = TRUE; } ... // Файл конфигурации ... no_sidebar = TRUE; ...
// фрагмент файла конфигурации ... keywords = "движок, фреймворк, CMF" description = "cogear -- система управления сайтами." ... // код страницы ... <meta name="keywords" content="движок, фреймворк, CMF"/> <meta name="description" content="cogear -- система управления сайтами."/> ...
http://cogear.ru/blogs/admin/ http://cogear.ru/rss/blogs/admin/
// В контроллере/модели $link = l('/user/admin/'); // В шаблоне {? l('/user/admin/')} /* * Тогда при включенных поддоменах и параметре конфигурации subdomain = TRUE модуля users ссылки будут преобразованы в http://user.cogear.ru/admin/ */
window.addEvent('domready'){ new Request.JSON({ url: '/ajax/favorites/manage/', onComplete:function(re,reText){ /* * Если ответ в Json */ if(re.success){ ... // Do something } msg(re.msg,re.success); /* * Если ответ простым текстом -- тогда надо проверять второй аргумент reText */ } }).post(); }); }); }
... function manage(){ $data['id'] = $this->input->post('id'); $data['name'] = $this->input->post('name'); ... // Автоматически переводит массив/объект в json и отдает его // Укажем текст оповещения $data['msg'] = t('!some_department some_message'); // Удача ajax(TRUE,$data); // Неудача ajax(FALSE); // Можно отдать простой текст, для этого тип переменной должен быть "string" ajax(t('!some_department some_message')); } ...
http://mail.cogear.ru/ajax/blogs/show/1/ => http://cogear.ru/blogs/show/1/

CREATE TABLE IF NOT EXISTS `favorites` ( `id` int(10) unsigned NOT NULL auto_increment, `nid` int(10) unsigned NOT NULL, `uid` int(10) unsigned NOT NULL, `created_date` timestamp NOT NULL default CURRENT_TIMESTAMP, ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
; Файл /gears/favorites/favorites.info ; Помним, что название и описание по-умолчанию идут на английском языке. title=Favorites description=Allow user to add topics to favorites ; Важно! Обязательно требует указать группу компонента -- core | modules | plugins group=modules ; Указываем позицию. Она может быть не уникальна. ; Шестеренки с одинаковой позицией сортируются по названию. position=5 ; Включаем компонент enabled = TRUE ; Резервируем поддомен subdomain[] = favorites
[gears] favorites = "Избранные" favorites_description = "Позволяет пользователю заносить публикации в Избранное" [favorites] favorite = "Закладки" add = "Добавить в закладки" remove = "Удалить из закладок" add_success = "Материал добавлен в закладки!" remove_success = "Материал удален из закладок!"
/** * CoGear * * Content management system based on CodeIgniter * * @package CoGear * @author CodeMotion, Dmitriy Belyaev * @copyright Copyright © 2009, CodeMotion * @license http://cogear.ru/license.html * @link http://cogear.ru * @since Version 1.0 * @filesource */ // ------------------------------------------------------------------------ /** * Favorites controller * * @package CoGear * @subpackage Favorites * @category Gears controllers * @author CodeMotion, Dmitriy Belyaev * @link http://cogear.ru/user_guide/ */ class Index extends Controller{ /** * Constructor * * @return void */ function __construct(){ parent::Controller(); } // ------------------------------------------------------------------------ /** * Show user favorite nodes * * @param string $url_name * @param int $page * @return void */ function index($url_name, $page = 0){ // If user exists if($url_name && $user = $this->user->info($url_name)){ // Show user profile main info $this->user->head($user,'favorites'); // Check for acl to view unpublished items if(acl('blogs allow_view_unpublished') OR $user->id == $this->user->get('id')){ $this->nodes->published = FALSE; } // Add active record condition // Show list of nodes with pagination $this->nodes->get($page,FALSE,TRUE); } else return _404(); } // ------------------------------------------------------------------------ /** * Add/remove node to user favorites via ajax * * @return json */ function action(){ // Set i18n department d('favorites'); // Get POST variables $nid = $this->input->post('nid'); $action = $this->input->post('action'); // Check for request if(!$nid OR !$action) ajax(FALSE); // Get current user id $uid = $this->user->get('id'); // Switch action switch($action){ case 'add': ajax(FALSE); } ajax(TRUE,t('add_success')); } break; case 'remove': ajax(TRUE,t('remove_success')); } break; } // If no switch option matches return false ajax(FALSE); } // ------------------------------------------------------------------------ } // ------------------------------------------------------------------------
function _show(&$node,$type = 'full',$return = FALSE){ ... $info =& $this->breadcrumb; //'!/gears/nodes/img/icon/time.png! ' $info->set('node_info')->data($node) ->add('<span>'.df($node->created_date).'</span>') ->add('<a href="'.l('/blogs/'.$node->author_url_name).'"> <img class="avatar" src="'.$avatar.'"> <a href="'.l('/user/'.$node->author_url_name).'">'.$node->author.'</a>'); $node->info = $info->compile(); ... }
/** * Add link-icon to node_info breadcrumb * * @param object $Breadcrumb * @return void */ function favorites_breadcrumb_compile_(&$Breadcrumb){ if($Breadcrumb->name == 'node_info' && acl('favorites manage')){ $Breadcrumb->add(' <a href="javascript:void(0)"> <img class="favorite-action" id="node-'.$Breadcrumb->data->id.'" src="/gears/favorites/img/icon/'.$status.'.png" title="'.t('!favorites '.$status).')"/> </a> ',0); } } // ------------------------------------------------------------------------
/** * Show head panel with userinfo * * @param object * @param string * @return void */ function head($user,$active = 'profile'){ d('user'); $CI =& get_instance(); $CI->breadcrumb->set('userinfo_panel')->wrapper(); $CI->breadcrumb->data($user); $CI->breadcrumb->add('<a href="'.$user->avatar['original'].'" target="_blank"> <img src="'.$user->avatar['64x64'].'" border="0" class="avatar"/></a> <h1><a href="'.l('/user/'.$user->url_name).'">'.$user->name.'</a></h1>'); if($CI->user->get('user_group') == 1 OR $CI->user->get('id') == $user->id){ $CI->breadcrumb->add('<a href="'.l('/user/'.$user->url_name.'/edit/').'"> <img src="/gears/global/img/icon/edit.png"/></a>'); } $CI->breadcrumb->compile(4); $CI->userinfo_tabs = new Panel('userinfo_tabs',FALSE,FALSE,'tabs'); $CI->userinfo_tabs->data =& $user; $CI->userinfo_tabs->set_title = FALSE; $CI->userinfo_tabs->links_base = '/user/'.$user->url_name.'/'; $CI->userinfo_tabs->set_active($active); $CI->userinfo_tabs->compile(5); d(); } // ------------------------------------------------------------------------
/** * Add userinfo_tabs tab for favorites link * * @param object * @return void */ function favorites_panel_compile_(&$Panel){ $CI =& get_instance(); if($Panel->name == 'userinfo_tabs'){ ->count_all_results('favorites'); $count = $count > 0 ? ' ('.$count.')' : ''; 'text'=>fc_t('!favorites favorite').$count, 'link'=>l('/favorites/'.$Panel->data->url_name))); if($CI->name == 'favorites') { $Panel->set_active('favorites'); } } } // ------------------------------------------------------------------------
window.addEvent('domready',function(){ new Request.JSON({ url: '/ajax/favorites/action/', data: 'nid='+nid+'&action='+action, onComplete: function(re){ if(re.success){ switch(action){ case 'add': img.src = '/gears/favorites/img/icon/remove.png'; img.set('title',lang.favorites.remove); break; case 'remove': img.src = '/gears/favorites/img/icon/add.png'; img.set('title',lang.favorites.add); break; } } msg(re.msg || lang.errors.error); } }).post(); return false; }); }); });
