Google Analytics в Kohana

Речь пойдёт не об установке счётчика GA на сайт. Тут и писать нечего. Гораздо более интересно наблюдать за статистикой из своего движка.

С одной стороны я видел такую фишку когда разбирал PyroCMS и ещё пару других CMS на CodeIgniter. С другой стороны как раз один заказчик попросил такую штуку к себе на сайт.

Читать далееGoogle Analytics в Kohana

Kohana ORM. Используем выражения

Я долго не мог понять, чего мне не хватает в штатном ORM от Kohana. А не хватало именно возможности использования выражений.

Бывало напишешь по-наивности какое-нибудь выражение прямо в where. Например, так:

where(‘concat(first_name,» «,last_name)’,»like»,»%$searchstring%»)…

А потом получаешь ошибку, что нет такого поля ‘concat(first_name,» «,last_name)’

И вот однажды я в недрах интернетов нашёл решение, которое конечно же решил положить в мою копилку шпаргалок. Всё дело в использовании функции DB::expr. Вот например так:

$searchresult=ORM::factory(«user»)->
where( DB::expr(‘concat(first_name,» «,last_name)’), «like»,»%$searchstring%»)->
order_by(«id»,»desc»)->
limit($data[‘per_page’])->
offset($data[‘offset’])->
find_all();

Воистину, ORM может всё, только нужно знать все его трещинки.

Kohana 3.2. Валидация

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

Прежде чем буду описывать — оговорюсь. Я сторонник того, чтобы описывать всю валидацию в модели ORM. Религия у меня такая. Поэтому …

Делаем раз
============================
Описываем правила. Просто добавляем в модель два метода rules и labels.

Вот простой пример:
public function rules() { return array( ‘title’ => array( array(‘not_empty’), ), ); }
public function labels() { return array( ‘title’ => «Заголовок», ); }

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

В общем-то дело почти сделано. При сохранении объекта теперь всегда будет выполняться проверка.

Делаем два
=======================
Проверка выполняется всегда при сохранении объекта. Если нужно просто проверить без сохранения, можно использовать метод check. К сожалению ошибки валидации будут вылетать как ошибки, которые нужно будет отлавливать.

Вот пример кода из контроллера:
try{ // $page->save(); $page->check(); } catch(Exception $e) { $errors = $e->errors(‘validation’); foreach ($errors as $error){ echo «Ошибка: «. $error; } }

Никогда не любил использовать try , но куда деваться, очень уж хочу использовать именно штатную валидацию из ORM.

Какие можно делать правила
========================
Все правила — это суть методы объекта Kohana_Valid и вы сможете их найти в файле /system/classes/kohana/valid.php. Смысл большинства из них очевиден из названий для каждого, кто дружит с великим и могучим английским языком.

Некоторые правила просты и не требуют использования аргументов. Например правило not_empty и email
public function rules() { return array( ’email’ => array( array(‘not_empty’), array(’email’), ), ); }

Некоторые требуют одного или более аргументов. Например exact_length требует 2, собственно значение поля и желаемая длина (строки).
public function rules() { return array( ‘some_field’ => array( array(‘exact_length’ , array(‘:value’, 5)), ), ); }

Если не хватает стандартных, то можно написать своё правило. Только лучше оформить его в виде функции и хранить в этой же модели.
public function rules() { return array( ‘some_field’ => array( array( array($this,’check_something’) , array(‘:value’)), ), ); } public function check_something($value) { // тут может быть какая угодно сложная логика ……………….. return (bool) $blablabla; }

Однако не торопитесь сразу создавать функцию. Пробегитесь по базовому классу ORM. Он имеет довольно большие возможности. Например, для проверки уникальности поля можно использовать уже готовый метод unique. Вот пример проверки email на валидность, непустоту и уникальность:
public function rules() { return array( ’email’ => array( array(‘not_empty’), array(’email’), array(array($this, ‘unique’), array(’email’, ‘:value’)), ), }

Делаем три
============================
Если вы добавляли свои правила — не забудьте добавить какие-нибудь соответствующее описание в /application/messages/validation.php

Ссылки по теме
============================
Kohana 101 от Броткина Ивана — тут замечательно расписана валидация, каждая функция разобрана по косточкам. Заходите и читайте.

WinXP, MTU и прочее другое

Я хочу извиниться перед читателями за дикий оффтопик. Но каждый сезон ручьёв и дождей, когда ливнёвки и колодцы связи заливает, у меня начинает глючить интернет. И некоторое облегчение приносит программное изменение MTU (WinXP).

А поскольку я это делаю уже не первый год, меня реально достало каждый раз гуглить эту тему, и поэтому размещаю шпаргалку тут.

1. Сначала подобрать параметр MTU командой
PING -f -l 1450 xxx.xxx.xxx.xxx
Нужно выбрать максимальный, при котором передача пакета происходит удачно

2. Установить нужный параметр в регистре Windows
HKEY_LOCAL_MACHINE\ SYSTEM\ CurrentControlSet\ Services\ Tcpip\ Parameters\ Interfaces\код_интерфейса\MTU

3. Перегрузить Windows

PS: А может, это провайдер в сезон дождей балуется со своим MTU? И дожди тут не при чём?

Kohana ORM. COUNT_ALL() и RESET(false)


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

$count= ORM::factory(«post») -> where(«published»,»=»,1) -> count_all(); $posts= ORM::factory(«post») -> where(«published»,»=»,1) -> limit(10)->offset(30)-> found_all();

Обратите внимание, в этом примере у нас был фильтр published=1 . Пока всё просто и понятно. Мы просто дважды выполнили запрос со схожими фильтрами.

Но иногда фильтры бывают довольно сложными и генерироваться несколькими страницами кода. В таких случаях возникает соблазн один раз накопить фильтры, чтобы дважды потом использовать. Однако есть проблема. Функция count_all() сбрасывает ORM в ноль в том числе и все фильтры.

Что же делать? Чтобы ORM не сбрасывалась, нужно один раз запустить функцию reset(false). Пример:

$posts = ORM::factory(«post») -> reset(false); /// Вот оно! $posts = $posts -> where(«published»,»=»,1); // Дальше накручиваем фильтров if(……){ $posts = $posts->where( ……….); } …………………….
$count = $posts — >count_all();
// Теперь ничего не теряется $posts = $posts -> limit(10)->offset(30)-> found_all();

Вот такая зарубочка на память.

GIT игнорируем файлы


Ещё одна шпаргалка по GIT.

Если у вас есть файлы, который должны игнорироваться — можно добавить их в .gitignore. В этом случае файл не будет включён в git репозиторий.

Но если нужно включить файл в репозиторий, и при этом игнорировать изменения — используйте git update-index —assume-unchanged .

Пример:

git update-index —assume-unchanged application/config/database.php

Чтобы перестать игнорировать изменения нужно использовать параметр —no-assume-unchanged .

Пример:

git update-index —no-assume-unchanged application/config/database.php

S2 — лёгкая CMS


Хочу предоставить вашему вниманию S2 CMS. S2 довольно лёгкая иминималистичная система. Она прекрасно подойдёт для тех кому быстро-быстро нужен блог или сайт визитка.

CMS имеет довольно дружественную админку. Краткий перечень базовых возможностей впечатляет:

  • Система позволяет организовать набор страниц. Возможна иерархическая структура.
  • Подсистема контроля комментариев.
  • Управление пользователями с довольно сложной системой доступов.
  • Файловый менеджер загруженный файлов.
  • Поддержка различных языков.
  • Подключение модулей.

K S2 есть несколько очень полезных авторскими дополнений. На официальном сайте есть возможность скачать два варианта — с дополнениями и без. Я считаю что нет даже смысла качать вариант без дополнений.

Вот список имеющихся на данный момент дополнений:

  • Blog — Блог. Без этого дополнения сайт содержит лишь статичные страницы
  • Counter — Система внутренней статистики посещений. Строит красивые графики.
  • Editor Highlighting — Подсветка HTML-кода в редакторе.
  • Russian typography — Заменяет кавычки на правильные, ну и прочая русская типографика.
  • Search — Система полнотекстового поиска. По утверждению разработчика учитывает русскую морфологию! Периодически требует переиндексации.
  • Template editor — встроенный редактор шаблонов. Позволяет редактировать файлы шаблона
  • WYSIWYG — просто незаменимая вещь TinyMCE. Без этого дополнения все тексты придётся писать в сыром HTML.

Кто-то скажет, что у WordPress плагинов больше, но не забудьте, что половина плагинов в WP откровенное сырьё без гарантии нормальной работы, а тут заботливо отлаженный код, написанный самим автором CMS.

На самом деле CMS просто впечатляющая, если спомнить, что её написал один человек.

CMS отлично подойдёт для чайников, или почти чайников. Естественно при условии, что не захочется чего-то большего

Но вот разработчикам наверное будет неуютно что-то допиливать в этом коде. Так что для своих поделок я люто и бешенно хочу сваять что-то своё. Тем более, что перед глазами такие образцы. =)

UPD: при установке мне пришлось закомментировать в .htaccess строчку связанную с MultiViews. Зачем она была нужна, не знаю. Без неё всё работает.

Kohana ORM. Прикол при добавлении связи


Мы все знаем, что для добавления связи много-ко-многим используется функция ORM add().

Но что делать, если объект только что создан? Тогда есть проблемка.

Вот практический пример:

// Создаём пользователя $user = ORM::factory(«user»); $user->id = 123123; $user->name = «Username»; $user->email = «asd@asdasd.asd»; $user->password = «PaSsWoRd»; $user->save();
// Даём роль $user->add(«roles»,ORM::factory(«role»,1));

Вроде всё делаем правильно, однако мы получим ошибку:

Database_Exception [ 1048 ]: Column ‘user_id’ cannot be null [ INSERT INTO `roles_users` (`user_id`, `role_id`) VALUES (NULL, ‘1’) ] ~ MODPATH/database/classes/kohana/database/mysql.php [ 194 ]

Забавная ошибка. Объект создан и сохранён. Но тем не менее ORM не может найти id пользователя! Попробуйте запросить $user->id сразу после создания объекта, и вы его получите. И более того, я явно присваиваю id, до сохранения. Но ORM не находит. Мистика, однако!

Построенная таким образом модель, какая-то не полная и чего-то ей не хватает. Совсем другое дело, если ещё раз запросить объект.

Вот пример:

// Создаём пользователя $user = ORM::factory(«user»); $user->id = 123123; $user->name = «Username»; $user->email = «asd@asdasd.asd»; $user->password = «PaSsWoRd»; $user->save();
// Сначала переопределяем объект $user = ORM::factory(«user»,$cms_user->id);
// А вот теперь уже даём роль $user->add(«roles»,ORM::factory(«role»,1));

И так — всё работает.

Проблема решена, всё работает, но как-то по-дурацки. Кто знает, как можно сделать это красивее?

UPD: Речь про Kohana 3.2
UPD2: Глюк и правда странный, тем более что модель и правда немного модифицировалась, возможно автор сам дурак.

Самодельный аккордеон на jQuery


Недавно пришлось написать свой аккордеон. Пришлось, потому что штатный, включённый в Twitter Bootstrap, глючит в MSIE. Например на момент написания поста аккордеон глючил в IE9.

Впрочем, нет ничего сложного в написании такого аккордеона самостоятельно.

HTML
===========================

Тут делаем всё как для обычного аккордеона

Kohana ORM: Удаляем записи с корнем. Целостность БД


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

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

Для этого надо у каждой модели прописать свою процедуру delete(), в которой и прописать алгоритм удаления. Но если база данных построена правильно, если все подчинённые записи подключены именно как «много-к-одному», а не «многие-ко-многим» и т.д., то можно автоматизировать этот процесс и написать одну функцию на все случаи жизни.

public function delete() { if ($this -> loaded()){ foreach($this->_has_many as $key => $value){ foreach( $this -> {$key}-> find_all() as $element){ if(isset($value[‘through’])){ $this->remove($key, $element); }else{ $element -> delete(); } } } } return parent::delete(); }

Вот так.

Ну и естественно, БД должна быть сделана по уму и модели прописаны правильно. А иначе, можно ведь нечаянно удалить что-то нужное