→

Фреймворки →  Yii — php-фреймворк

Вышла стабильная версия PHP фреймворка Yii 1.1.

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

Тестирование на основе PHPUnit.
Построитель форм.
— Возможность создания шкурок для виджетов.
— Улучшен API реляционных запросов ActiveRecord.
— В комплекте теперь поставляется набор расширений Zii, включающий виджеты для jQuery UI и другие полезные компоненты.

Полное руководство по версии 1.1 на русском языке на yiiframework.ru уже находится в актуальном состоянии.

Перевод обновлённого руководства по созданию блога будет завершён немного позже.
Скачать новые версии можно здесь: http://www.yiiframework.com/download/
2

Фреймворки →  Кеширование в Codeigniter при помощи Zend Cache

Codeigniter на столько мощный фреймворк, что приходится пользоваться недофреймфорком Zend Framework, слышал аргумент против Зенд Фреймворка: «это тупо набор классов», скажу, что это нихера не набор классов, а классы в ZF хороши. Поэтому будем пользовать Zend Cache для еширования в Codeigniter.

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

Использование компонента Zend Cache в CodeIgniter неудобно, поэтому решил написать свою библиотеку, которя будет использовать этот механизм кэширования и будет проста в применении с CodeIgniter. Теперь немного опишу своё творение, и расскажу как его применить.

Пример применения библиотеки


Для начала нужно сконфигурировать библиотеку, для этого нужно создать файл cache.php в /aplication/config/ примерно так:

//Путь до библиотеки Zend
$config['path_to_zend']  = '';

//Название фронтэнда
$config['frontend'] = 'Core';
//Название бэкэнда
$config['backend']  = 'File';

//Опции фронтэнда
$config['frontendOption']  = array(
       'lifetime'                  => null,
       'automatic_cleaning_factor' => 0,
       'automatic_serialization'    => true
);

//Опции бэкэнда
$config['backendOption']  = array(
    'cache_dir'              => APPPATH.'cache/',
    'read_control_type'      => 'strlen',
    'file_locking'           => false,
    'hashed_directory_level' => 0,
    'file_name_prefix'         => 'cache'
);


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

$this->load->library('Cache');

Пример 1:


if ( ! $end = $this->cache->load('name_ceche') ) {

    $blog = $this->db->get("blog");
    $category = $this->db->get("category");

    $end['content'] = $blog->result();
    $end['category'] = $category->result();

    $this->cache->save($end, 'name_ceche', array('page1', 'blog'));
}


В первом примере, мы кэшируем целый массив, это возможно если в настройках фронтенда параметр 'automatic_serialization' учтановлен в true.
В таком случае мы можем сохранить в кэш данные примо из базы данных или сразу из нескольких баз данных, либо перед их кэшированием можно как то их обработать что бы не тратить ресурсы сервера потом. Таким образом мы избавляемся от запросов к базе данных (в данном случае двух) и вместо этого подгружаем файл, что выполняется быстрее.

Пример 2:


if ( ! $end = $this->cache->load('name_ceche') ) {

    $blog = $this->db->get("blog");

    $data['content'] = $blog->result();

    $end = $this->load->view('myfile', $data, true);
   
    $this->cache->save($end, 'name_ceche', array('page1', 'blog'));
}


Во втором примере мы видим что кэшируется уже не массив с данными а целая часть страницы. Такой метод позволяет кэшировать данные которые не требуют частого обновления (например список категорий на странице, облако тэгов и т.д.) либо генерация этих данных очень ресурсоёмка и имеет смысл сохранить их на небольшой промежуток времени. И в данном случае опцию 'automatic_serialization' не обязательно устанавливать в true.

Пример 3:


$this->cache->remove('name_ceche');
$this->cache->clean('page1');
$this->cache->clean('blog');


В примере №3 показаны способы удаления кэша который мы создали ранее, в примерах 1 и 2. Но заметьте сделать что это можно сделать разными способами.
С помощью первого метода можно удалить кэш по его уникальному имени, с помощью второго и третьего метода мы сделаем тоже самое но используя ни его имя, а тэги которые были присвоены кэшу. Это позволяет удобно управлять кэшем, например можно удалить кэш категорий только с определённой страницы, задав при сохранении определённые тэги.

Подробную информацию о том для чего определённые настройки и описание бэкендов и фронтэндов не приводил т.к. эта информация есть на русском языке в документации к Zend Cache.

Скачать:
CI-ZendCache.zip
1
1

PHP программирование →  Юнит-тестирование контроллеров Zend Framework

Тестирование Веб-приложений — это комплексная задача, потому что веб-приложение создается из нескольких логических слоев. Модульное тестирование контроллера Zend Framework может быть весьма трудной задачей, особенно для тех, кто слабо знаком с Zend Framework.

Вы можете тестировать свои контроллеры действий используя Zend_Test и/или PHPUnit. Zend_Test позволяет вам имитировать запросы, передавать тестовые данные, контролировать вывод вашего приложения и в целом убедиться в том, что ваш код делает именно то, что должен делать. Вам решать, какой из них использовать. Если вы не можете выбрать один из них, то можете использовать оба. Если вы только знакомитесь с тестированием с помощью Zend_Test, то эта статья будет лучшей точкой старта.

Фреймворк PHPUnit может показаться очень знакомым тем разработчикам, которые пришли из Java. Разработчики PHPUnit черпали вдохновение из JUnit — тестовом фреймворке для платформы Java, поэтому вы будете чувствовать себя как дома при использовании PHPUnit если вам уже приходилось сталкиваться с JUnit или одним из его клонов.

Конечно, никто не запрещает вам использовать системы бок о бок (даже в одном и том же приложении). В конце концов, большинство проектов так и будет использовать.

Использование PHPUnit


app/
    config/
    controllers/
        ExampleController.php
    models/
    views/
lib/
    Zend/
public/
tests/
    controllers/
        AllTests.php
        ExampleControllerTest.php
    lib/
    AllTests.php
    bootstrap.php


Тестовый набор нуждается в некоторой информации об окружении, и обычно эта информация находится в файле bootstrap.php. Самым большим отличием этого файла от одного из из используемых в вашем приложении является то, что Фронт-контроллер не выполняет диспетчеризацию объекта запроса:

tests/bootstrap.php
<?php
/* Start output buffering */
ob_start();

/* Report all errors directly to the screen for simple diagnostics in the dev environment */
error_reporting( E_ALL | E_STRICT );
ini_set('display_startup_errors', 1);
ini_set('display_errors', 1);
date_default_timezone_set('Europe/London');

/* Determine the root and library directories of the application */
$appRoot = dirname(__FILE__) . '/..';
$libDir = "$appRoot/lib";
$path = array($libDir, get_include_path());
set_include_path(implode(PATH_SEPARATOR, $path));

define('APPLICATION_PATH', $appRoot . '/app');
define('APPLICATION_ENVIRONMENT', 'dev');

require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();

$front = Zend_Controller_Front::getInstance();
$front->throwExceptions(true);
$front->setParam('noViewRenderer', true);
$front->setParam('env', APPLICATION_ENVIRONMENT);
$front->setRequest(new Zend_Controller_Request_Http());
$front->returnResponse(true);

$router = $front->getRouter();
include APPLICATION_PATH . '/config/routes.php';
$router->addRoutes($routes);
$router->setParams($front->getParams());

$dispatcher = $front->getDispatcher();
$dispatcher->setParams($front->getParams());
$dispatcher->setResponse($front->getResponse());
$router->route($front->getRequest());


Обратите внимание! Отключение помощника ViewRenderer является не обязательным. Однако, вам должно быть известно, что использование класса Zend_Controller_Action_Helper_ViewRenderer может привести к снижению производительности. Подробнее об этом можно прочесть здесь.

Класс PHPUnit_Framework_TestSuite фреймворка PHPUnit позволяет вам организовать тесты в иерархические наборы тестов:

tests/AllTests.php
<?php
require_once dirname(__FILE__) . '/bootstrap.php';
require_once dirname(__FILE__) . '/controllers/AllTests.php';

class AllTests
{
    public static function main()
    {
        $parameters = array();
        PHPUnit_TextUI_TestRunner::run(self::suite(), $parameters);
    }

    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('My Application');
        $suite->addTest(ControllersAllTests::suite());
        return $suite;
    }
}
AllTests::main();


tests/controllers/AllTests.php
<?php
require_once dirname(__FILE__) . '/ExampleControllerTest.php';

class ControllersAllTests
{
    public static function main()
    {
        PHPUnit_TextUI_TestRunner::run(self::suite());
    }
    public static function suite()
    {
        $suite = new PHPUnit_Framework_TestSuite('My Application - Controllers');
        $suite->addTestSuite('ExampleControllerTestCase');
        return $suite;
    }
}


Написание модульных тестов


Из-за довольно странных причин эта часть не описана в документации. Вот что вам нужно сделать до написания теста:

1. Подключить контроллер, который вы собираетесь тестировать.
2. Расширить контроллер действий (унаследовавшись от него).
3. Сбросить состояние экземпляра фронт-контроллера.
4. Указать путь к тестируемому контроллеру действий.
5. Установить объекты Запроса и Ответа.
6. Создать экземпляр тестируемого объекта.

Пример:
tests/controllers/ExampleControllerTest.php
<?php
require_once APPLICATION_PATH . '/controllers/ExampleController.php';

class ExampleControllerTest extends ExampleController
{
    public function __construct($url = null)
    {
        $front = Zend_Controller_Front::getInstance();
        $front->resetInstance();
        $front->setControllerDirectory(APPLICATION_PATH . '/controllers');
        $front->setRequest(new Zend_Controller_Request_Http($url));
        $front->setResponse(new Zend_Controller_Response_Http());
        parent::__construct($front->getRequest(), $front->getResponse());
    }
}


Вся магия происходит внутри класса ExampleControllerTest. Он делает так, что контроллер действий думает, что был вызван фронт-контроллером в цикле диспетчеризации. Единственный путь сделать это — создание экземпляра контроллера действий без диспетчеризации запроса. Получение экземпляра контроллера действий дает вам больше контроля и гибкости, особенно при тестировании веб-сервисов.

А теперь пришло время создать наш первый тестовый набор. Тестовый набор это класс, наследуемый от PHPUnit_Framework_TestCase, содержащий тестовые методы, определяемые по префиксу «test» в названии метода.

require_once APPLICATION_PATH . '/controllers/ExampleController.php';

class ExampleControllerTest extends ExampleController
{
    ...
}

class ExampleControllerTestCase extends PHPUnit_Framework_TestCase
{
    public function testDefaultAction()
    {
        $controller = new ExampleControllerTest();
        $isDispatched = $controller->indexAction();

        $this->assertTrue($isDispatched);
    }

    public function testFirstAction()
    {
        $url = 'http://localhost/example/first';
        $controller = new ExampleControllerTest($url);
        $controller->firstAction();
        $errorMsg = $controller->getRequest()->getParam('error_message', null);

        $this->assertEquals(null, $errorMsg);
    }

    public function testGetParameterName()
    {
        $url = 'http://localhost/example/first/fed';
        $controller = new ExampleControllerTest($url);
        $name = $controller->getRequest()->getParam('name', null);

        $this->assertEquals('fed', $name);
    }

    public function testGetNameMethod()
    {
        $url = 'http://localhost/example/first/fed';
        $controller = new ExampleControllerTest($url);
        $name = $controller->getName();
        $this->assertEquals('fed', $name);
    }
}

Запуск тестов



federico@tests$ phpunit AllTests
PHPUnit 3.3.8 by Sebastian Bergmann.
.....
Time: 0 seconds
OK (4 tests, 4 assertions)


Если тестирование завершится неудачно, то вы увидите подробную информацию о проваленном тесте. По желанию, вы можете подключить Phing в Hudson и автоматизировать выполнение этой задачи. Если есть вопросы — обращайтесь.
0

Фреймворки →  Проблемы отображения Datepicker в Dialog (JQuery фреймворк)

Наверно, это баг:) Когда вызываешь диалоговое окно (в моем случае оно было модальным) и в нем пытаешься вызвать Datepicker(календарик для выбора даты), то календарик оказывается под диалоговым окном. Естественно, пользоваться таким календариком не очень удобно:)

Первое, что пришло в голову — z-index. Оно и естественно, как фиксить?

Из того, что нашел — все сводилось к допиливанию кода именно JQuery, я противник такого варварства, т.к. не известно, где это может всплыть (это же говно:)).

Сделал так:

$(function() {
        $("#date_publish").datepicker();//собственно вызов нашего календаря
        $("#ui-datepicker-div").css("z-index", 1000000); //задаем z-index
});
0

Фреймворки →  Роуты в Zend Framework и официальная документация

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

Столкнулся с такой проблемой, что пример кода из документации не хотел работать


// Создание маршрутизатора

$router = $ctrl->getRouter(); // по умолчанию возвращает rewrite router
$router->addRoute(
    'user',
    new Zend_Controller_Router_Route('user/:username',
                                     array('controller' => 'user',
                                           'action' => 'info'))
);
 


Начал рыть, не давала покоя переменная $ctrl. Я думал, что она где-то объявлена в фреймворке, потом выше кода в документации прочитал

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

В общем нужно инстанцировать:)

В начале кода добавляем:

$ctrl  = Zend_Controller_Front::getInstance();


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


set_include_path('../library' . PATH_SEPARATOR . get_include_path());

require_once 'Zend/Controller/Front.php';    
require_once 'Zend/Controller/Router/Route.php';    

$ctrl  = Zend_Controller_Front::getInstance();

// Создание маршрутизатора

$router = $ctrl->getRouter(); // по умолчанию возвращает rewrite router
$router->addRoute(
    'user',
    new Zend_Controller_Router_Route('user/:username',
                                     array('controller' => 'user',
                                           'action' => 'info'))
);
 


Удачи в изучении документации:)
0

Фреймворки →  Akismet библиотека для фреймворка CodeIgniter

Akismet это удаленный антиспам веб-сервис.

Если для построения своих приложений вы используете фреймворк CodeIgniter и у вас есть комментарии к статьям, то рассмотренная ниже библиотека защитит вас от спамеров при помощи сервиса Akismet.

Для пользования сервисом Akismet необходимо получить API ключик у них на сайте.

Скачайте библиотеку и положите у себя по адресу application/libraries/.

Как использовать в контроллере:


( Читать дальше )
0
4