PHP Framework Bluz

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

Почему рождается новый «велосипед» — да старый уже ж не в пору и скрипит

Чтобы не листать весь пост, вот вам ссылка на GitHub — https://github.com/bluzphp

В чем его удобство

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

Особенности

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

Так же упомяну, что данный фреймвёрк начал проклёвываться ещё год назад в одном высокогонагруженном проекте, и о нём я еще расскажу на ThinkPHP ;)

Так что же внутри? А внутри всё пляшет от Application, который отвечает чуть меньше, чем за всё и с десяток пакетов, которые обеспечивают комфортную и быструю разработку приложений

MVC

Куда уж без него, но в нашей реализации есть военная хитрость, вот к примеру контроллер:

<?php
return
/**
 * @privelege View User Profile
 * @cache 5 minutes
 * @param integer $id
 * @return closure
 */
function($id) use ($view) {
    /**
     * @var View $view
     */
     $view->user = $app->getDb()->fetchObject(
          "SELECT * FROM users WHERE id = ?", 
          array($id), 
          'Users\Row');
};

Без паники, да action не предусмотрены, лишь модули и контроллеры-замыкания, и да — это упрощает разработку. Внимательный читатель уже заметит как контроллер «ловит» входные параметры, и что у него оказывается уже есть кеширование, и описана какая-то привилегия — да, всё это работает, как и задумывалось ;)

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

return
/**
 * @var Bluz\View $view
 * @return closure
 */
function() use ($view) {
    $view->title = "Hello world"
};

Собственно код шаблона:

<h2><?=$title?></h2>
<!-- так тоже работает -->
<h2><?=$this->title?></h2>

Всякие мелкие фишки по работе с шаблонизатором описаны в соответствующем разделе wiki

База данных

Для работы с базой данных предусмотрен пакет Db (оригинально то как), он включает в себя Db\Db, Db\Table и Db\Row. Класс Db представляет из себя лишь обёртку над PDO, и слегка упрощает нам жизнь:

<?php
// init settings
$db->setConnect(array(
    'type' => 'mysql',
    'host' => 'localhost',
    'name' => 'db name',
    'user' => 'root',
    'pass' => ''
));
 
// quote variable
$db->quote($id)
 
// query
$db->query("SET NAMES 'utf8'");
 
// get one
$db->fetchOne("SELECT COUNT(*) FROM users");
 
// get row
$db->fetchRow("SELECT * FROM users WHERE id = :id", array(':id'=>$id));
 
// get array
$db->fetchAll("SELECT * FROM users WHERE ip = ?", array($ip));
 
// get pairs
$pairs = $db->fetchPairs("SELECT ip, COUNT(id) FROM users GROUP BY ip", array());
 
// get object
// .. to stdClass
$stdClass = $db->fetchObject('SELECT * FROM some_table WHERE id = ?', array($id));
// .. to new Some object
$someClass = $db->fetchObject('SELECT  * FROM some_table WHERE id = ?', array($id), 'Some');
// .. to exists instance of Some object
$someClass = $db->fetchObject('SELECT * FROM some_table WHERE id = ?', array($id), $someClass);

// plain insert/update/delete
$db->insert('some_table', array('col1'=>'foo', 'col2'=>'bar'));
$db->update('some_table', array('col1'=>'bar', 'col2'=>'foo'), array('id'=>1));
$db->delete('some_table', array('id'=>1));

О транзакциях тоже не забыл, вот пример контроллера:

if ($this->getDb()->transaction(function() {
    /**
     * @var \Bluz\Application $this
     */
    $this->getDb()->delete('acl_privileges');
})) {
    $this->getMessages()->addSuccess('All data was saved');
} else {
    $this->getMessages()->addError('Internal server error');
}

Классы Table и Row это некое подобие active record:

<?php
namespace Application\Users;
class Row extends \Bluz\Db\Row
{
   public function preInsert()
   {
       $this->created = gmdate('Y-m-d H:i:s');
   }
   public function preUpdate()
   {
       $this->updated = gmdate('Y-m-d H:i:s');
   }
}
 
$userRow = new \Application\Users\Row();
$userRow -> login = 'username';
$userRow -> save();

Роутеры

Просты до безобразия, указываются непосредственно в комментариях контроллера:

/**
 * @route /users/{$id}
 * @param integer $id
 */

При использование не требуют явного указания имени (привет ZF):

<?php
$this->url('users', 'login');
$this->url('users', 'profile', array('id' => $id));
$this->url('pages', 'show', array('name' => $name));
?>

Конечно, подобная реализация не без недостатков, но таки вполне юзабельно, и под стать фремвёрку.

Ещё

Есть еще пачка пакетов, пожалуй стоит привести их список:

  • Acl — позволяет быстро и гибко организовать раздачу прав
  • Cache — очень простая обёртка над memcached
  • EventManager — события и их обработчики
  • Registry — тут без комментариев
  • Request — объект запроса, сам по себе используется редко
  • Session — лишь обёртка

Выводы

Я конечно не надеюсь, что вы присоединитесь к разработке, но я искренне верю, что вам пригодится сам фреймвёрк, возможно его код или идеи из него :)

Если интересно — присоединяйтесь к Skype чату ;)

20 thoughts on “PHP Framework Bluz”

  1. Я тоже сторонник идеи фреймворка, продиктованного конкретными задачами. без лишних монструозностей, которые могут и не понадобиться. И не имеет значения, откуда заимствованы идеи или куски кода – важен результат и полезность для автора. В коде с интересом покопаюсь :)

  2. php 5.4 старье давай досвидания… я понимаю, что он вроде как легковесный, но pdo…. имхо объектную вещь надо, а не только нативные sql, плюс вопрос по поводу preInsert и preUpdate, не логичней бы было обозвать before? и объединить в beforeSave, да да, сперто с yii, но идея хороша, а внутри уже делать проверку на то новая запись или же идет апдейт. а то так можно и запутаться + дублирование кода, к примеру логгирование чего либо, придется писать метод, который в обеих pre вызывать, а вообще очень даже радует, namespace, простота, есть куда развиваться.

    P.S. насчет контроллеров непривычно, но идея в целом понравилась, осталось привыкнуть. а непривычно потому что всегда мысль что контроллер это класс, а не функция в файле)
    P.P.S. валидация планируется в моделях?

    1. Да, планируется, уже сейчас Row класс требует декларации полей, добавить туда параметры валидации, и будет уже что-то похожее на Symfony/ZF2 Forms

    2. … имхо объектную вещь надо, а не только нативные sql

      Нет, нет, нет и ещё раз нет. Вы только представьте: такой легковесный и гибкий фреймворк, а Вы предлагаете встроить туда танк-паровоз из объектной прослойки на реляционную БД.

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

  3. Получилось весьма интересно, обязательно попробую.
    Ещё бы посмотреть насколько он быстр относительно других микрофреймворков – silex, slim и прочих.

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

      Надеюсь нагруженный Сайт уже запущен и работает в данный момент, а этот фрэймворк не просто сделан на будущее или выкинут за ненужностью в паблик.

    1. Прикольный фрейм, жду новую версию, хочу пощупать, пока он вызывает лишь любопытство, но не более.
      P.S. ЯросТь

  4. Советую посмотреть на фреймворк http://laravel.com/, особенно на его идею бандлов. Сам недавно наткнулся на него в поисках идей для микрофреймворка и нашёл в нём практически всё что хотел писать :(

  5. Подскажите, почему требования PHP 5.4?
    Для анонимных функций достаточно 5.3, или есть какая-то еще особенность?
    А так спасибо, выглядит занятно.
    Поставил себе в планах разобраться в нем.

  6. При попытке установить skeleton как написано в README, получил вот это:
    Script sh ./bin/install.sh handling the post-install-cmd event returned with an error: ./bin/install.sh: 9: ./bin/install.sh: Bad substitution
    ./bin/install.sh: 9: ./bin/install.sh: realpath: not found
    chmod: невозможно получить доступ к «/data/cache/»: Нет такого файла или каталога
    chmod: невозможно получить доступ к «/data/logs/»: Нет такого файла или каталога
    chmod: невозможно получить доступ к «/data/sessions/»: Нет такого файла или каталога
    chmod: невозможно получить доступ к «/data/uploads/»: Нет такого файла или каталога
    cp: не удалось выполнить stat для «/application/configs/app.dev.sample.php»: Нет такого файла или каталога
    cp: не удалось выполнить stat для «/public/.htaccess.dev.sample»: Нет такого файла или каталога

  7. Наверное сюда писать не нужно об этом, скажите куда писать.
    Я тут пытаюсь запустить у себя всё это дело, но пока вот сталкиваюсь с ошибками. Первую просто вручную исправил, теперь вот:
    Call to a member function getIdentity() on a non-object

    /home/sid/www/bluz/library/bluzphp/framework/src/Bluz/View/Helper/User.php#39

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

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.