Open Source PHP Framework
Best Practices Inside

Руководство

Предисловие

Введение

Это руководство содержит все основные компоненты фрейворка. В настоящее время находится в постоянном обновлении. Терпение, скоро все будет.

Быстрый старт

подробное руководство по установке

1. Создайте composer.json в директории workspace/MyProject

$ mkdir -p workspace/MyProject && cd workspace/MyProject

workspace - ваш рабочая дииректория (logs, caches etc.);
MyProject - исходные коды вашего проекта

{
    "name": "vendor/my-project",
    "description": "My project with Ice",
    "type": "project",
    "require": {
        "ifacesoft/ice": "1.0.*"
    },
    "license": "proprietary",
    "authors": [
        {
            "name": "dp",
            "email": "denis.a.shestakov@gmail.com"
        }
    ],
    "minimum-stability": "stable",
    "config": {
        "vendor-dir": "../_vendor"
    },
    "scripts": {
        "post-install-cmd": [
            "Ice\\App::update"
        ],
        "post-update-cmd": [
            "Ice\\App::update"
        ]
    }
}

2. Инсталлируйте проект с помощью composer

$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar install --prefer-source

3. Настройте веб-сервер и /etc/hosts

После успешной инсталяции, используй сгенерированные конфигурации.

Готово! Ваш проект должен быть доступен по адресу http://myproject.local

4. Генерация моделей

Каждый раз, когда вы вызываете './cli Ice:Deploy' или напрямую './cli Ice:Orm_Migrate' создаются, обновляются и удаляются все модели в соответствии с состоянием текущей схемы базы данных.

Полезные ресурсы

Исходный код (начиния с версии 0.6 основой репозиторий нахолится на Bitbacket)

Исходный код на Bitbucket

Исходный код на GitHub

Api документация к коду

Поддержка проекта

Ice - это проект с открытым кодом и каждый желающий может внемти свою лепту в его развитие. Проект очень молод и нуждается в серьезной поддержке. На этом этапе требется помощь в написании документации и его перевода на все доступные языки. Также любая ваша критика и пожелания пойдут на пользу проекту.

Ваши комментарии и предложения можете оставлять в наших группах в социальных сетях: Vkontakte или Facebook

Ваши сообщения об ошибках можно оставлять на странице официального репозитория Ice on GitHub

Спасибо за любую оказанную поддержку.

Начало работы

Установка

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

Шаг первый: выполнить bash-команды

$ mkdir -p workspace/MyProject && cd workspace/MyProject
$ curl -sS https://getcomposer.org/installer | php
$ php composer.phar init

Следующий шаг: инициализировать composer - создать composer.json

Welcome to the Composer config generator

This command will guide you through creating your composer.json config.

Package name (<vendor>/<name>) [dp/my-project]: vendor/my-project
Description []: My project with Ice
Author [dp <denis.a.shestakov@gmail.com>]:
Minimum Stability []: stable
Package Type []: project
License []: proprietary

Define your dependencies.

Would you like to define your dependencies (require) interactively [yes]?
Search for a package []: ifacesoft/ice
Enter the version constraint to require (or leave blank to use the latest version) []:
Using version 1.0.* for ifacesoft/ice
Search for a package []:
Would you like to define your dev dependencies (require-dev) interactively [yes]? no

{
    "name": "vendor/my-project",
    "description": "My project with Ice",
    "type": "project",
    "require": {
        "ifacesoft/ice": "1.0.*"
    },
    "license": "proprietary",
    "authors": [
        {
            "name": "dp",
            "email": "denis.a.shestakov@gmail.com"
        }
    ],
    "minimum-stability": "stable"
}
Do you confirm generation [yes]? yes

Внести правки в composer.json (последние строчки выделены жирным)

{
    "name": "vendor/my-project",
    "description": "My project with Ice",
    "type": "project",
    "require": {
        "ifacesoft/ice": "1.0.*"
    },
    "license": "proprietary",
    "authors": [
        {
            "name": "dp",
            "email": "denis.a.shestakov@gmail.com"
        }
    ],
    "minimum-stability": "stable",
    "config": {
        "vendor-dir": "../_vendor"
    },
    "scripts": {
        "post-install-cmd": [
            "Ice\\App::update"
        ],
        "post-update-cmd": [
            "Ice\\App::update"
        ]
    }
}

Выполнить установку зависимостей с помощью composer

$ php composer.phar install --prefer-source

Могут оказаться проблемы с установкой вендора bootstrap (Failed to download twbs/bootstrap from source: The process "git clone --no-checkout 'git://github.com/twbs/bootstrap.git' '/usr/home/dp/PhpstormProjects/workspace/_vendor/twbs/bootstrap' && cd '/usr/home/dp/PhpstormProjects/workspace/_vendor/twbs/bootstrap' && git remote add composer 'git://github.com/twbs/bootstrap.git' && git fetch composer" exceeded the timeout of 300 seconds. Now trying to download from dist). Следует последовать инструкции и выполнить установку вручную.

Конфигурирование

/etc/hosts

127.0.0.1       myproject.global myproject.test myproject.local

Веб-сервер

Nginx + php-fpm
upstream myproject_phpfcgi {
    #    server 127.0.0.1:9000;
    server unix:/var/run/php5-fpm.sock;
}

server {
    listen 80;

    server_name myproject.global myproject.test myproject.local;
    root /usr/home/dp/PhpstormProjects/workspace/MyProject/Web;

    error_log /usr/home/dp/PhpstormProjects/workspace/_log/error.log;
    access_log /usr/home/dp/PhpstormProjects/workspace/_log/access.log combined;

    client_max_body_size 8m;

    rewrite ^/index\.php/?(.*)$ /$1 permanent;

    location / {
        index index.php;
        try_files $uri @rewriteapp;
    }

    location ~ ^/resource($|/.*) {
        alias /usr/home/dp/PhpstormProjects/workspace/_resource$1;
        index index.html;
    }

    location @rewriteapp {
        rewrite ^(.*)$ /index.php/$1 last;
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass myproject_phpfcgi;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;

        include fastcgi_params;

        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  HTTPS off;

        fastcgi_buffers 32 32k;
        fastcgi_buffer_size 32k;
    }
}
Apache + mod_php
<VirtualHost *:80>
    ServerName myproject.local    ServerAlias myproject.global myproject.test
    DocumentRoot /usr/home/dp/PhpstormProjects/workspace/MyProject/Web
    DirectoryIndex index.php

    Alias /resource/ /usr/home/dp/PhpstormProjects/workspace/_resource/

    CustomLog /usr/home/dp/PhpstormProjects/workspace/_log/access.log combined
    ErrorLog /usr/home/dp/PhpstormProjects/workspace/_log/error.log

        <Directory /usr/home/dp/PhpstormProjects/workspace>
        AllowOverride All
        Order allow,deny
        Allow from All
        </Directory>
</VirtualHost>

Фреймворк

Настройка фреймворка будет произведена автоматически

Структура проекта

Директория workspace:
_cache/          Cache files for separate projects
    _log/                   Log files for separate projects
    _resource/              Resource files (javascript, css, images etc.) for separate projects
    _storage/               File storage
    _vendor/                Vendors (loaded via composer)

    MyProject/        Your module
        Config /          Configuration files (php format)
            Ice/              Overridden configuration files for Ice module
            Mp/               Configuration files for your module (MyProject)
        Resource/         Resource files
            Ice/              Overridden resource files for Ice module
            Mp/               Resource for your module (MyProject) (views, localization files etc.)
        Source/           Source files
            Ice/              Overridden source files for Ice module (not recommended)
            Mp/               Source files for your module (MyProject)
                Action/           Action classes for your module (MyProject)
                Model/            Model classes for your module (MyProject)
                ...               Other implementations of core ice classes and interfaces
        Web/              Web root directory
            index.php         Directory index file
        bootstrap.php     Bootstrap script
        app.php           Application run script
        cli               Console application run script

Основы

Маршруты

/Config/Ice/Core/Route.php

return [
    'mp_page' => [
        'route' => '/page/{$page}',
        'params' => [
            'page' => '(\d)'
        ],
        'weight' => 10000,
        'request' => [
            'GET' => [
                'Www:Layout_Main' => [
                    'actions' => [
                        ['Ice:Title' => 'title', ['title' => 'Ice - Open Source PHP Framework ']],
                        'Www:Index' => 'main'
                    ]
                ]
            ]
        ]
    ]
]
Important parts:
  • 'mp_page' - Route name, (Uses: Route::getInstance('mp_page')->getUrl(20)) returned '/page/20' etc.)
  • 'weight' - Priority of matched routes. Greater weight - greater priority.
  • 'request' section - Array of available requuest methods (GET, POST etc.)
  • 'request/GET' - Only one item (first) contained layout action class as key and params as value

Деиствия

namespace Mp\Action;
use Ice\Core\Action;
class Page extends Action
{
    protected static function config()
    {
        return [
            'view' => ['viewRenderClass' => 'Ice:Smarty', 'template' => null, 'layout' => null],
            'actions' => [],
            'input' => [],
            'output' => [],
            'ttl' => -1,
            'access' => [
                'roles' => [],
                'request' => null,
                'env' => null
            ]
        ];
    }
    public function run(array $input)
    {
        return ['var' => 'inTemplate'];
    }
}
2 main methods - config and run

method config - return array:

  • 'view' - Define way of render output data ('viewRenderClass' - render class, 'template' - template for render, layout - template-wrapper of rendered content in emmet style)
  • 'actions' - Child actions
  • 'input' - Array of input params with their data providers. Also information of validators, defaults end other.
  • 'output' - Фdditional sources of output (params and their data providers as well as 'input' section)
  • 'ttl' - time stored in cache (now supported only 3600 :) )
  • 'access' - Information to checks permissions to run action (support environment - one of 'production', 'test' or 'development' and request - one of 'cli' or 'ajax')

method run - return output array

Содержит бизнес-логику

Шаблоны

Рендер шаблона

Smarty::getInstance()->fetch('Mp\Action\Page', ['var' => 'inTemplate'])

Работа с базами данных

Модели

Select examples:

$page = Page::getModel(20, ['title', 'desc']); // or Page::getModel(20, '*')
// or
$page = Page::create(['title' => 'page 20')->find([id, 'desc']);

Insert examples:

Page::create(['title' => 'page 20', 'desc' => '20th page'])->save();

Update examples:

Page::getModel(20, ['title', 'desc'])->set(['title' => 'another title'])->save();

Update examples:

Page::getModel(20, '/pk')->remove();

Построение запросов

Select examples:

$page = Page::createQueryBuilder()->eq(['desc' => '20th page'])->getSelectQuery()->getModel();

Insert examples:

Page::createQueryBuilder()->getInsertQuery(['title' => 'page 20', 'desc' => '20th page'])->getQueryResult();

Update examples:

Page::createQueryBuilder()->eq(['id' => 20])->getUpdateQuery(['title' => 'another title'])->getQueryResult();

Update examples:

Page::createQueryBuilder()->getDeleteQuery(20)->getQueryResult();

Виджеты

Формы

Простая форма

$form = Simple::create(Request::uri(), __CLASS__)
    ->setLayout(Emmet::PANEL_BODY)
    ->text('textField', 'First text field', ['placeholder' => 'Enter text value'])
    ->date('date', 'Example date field', ['default' => Date::get()])
    ->password('password', 'Password');
Результат:

Простое меню

$navMenu = Nav::create(Request::uri(), __CLASS__)
    ->setClasses('nav-pills')
    ->link(
        'guide',
        'Руководство',
        [
            'href' => 'http://iceframework.net/guide', 'target' => '_blank',
            'active' => String::startsWith(Request::uri(), Route::getInstance('www_guide')->getUrl())
        ]
    )
    ->link('github', 'GitHub', ['href' => 'https://github.com/ifacesoft/Ice/tree/master', 'target' => '_blank'])
    ->link('bitbucket', 'Bitbucket', ['href' => 'https://bitbucket.org/dp_ifacesoft/ice', 'target' => '_blank'])
    ->link('api', 'Api', ['href' => 'http://iceframework.net/resource/api/Ice/1.0', 'target' => '_blank']);
Результат:

Навигационное меню

$navbarMenu = Navbar::create(Route::getInstance('ice_admin')->getUrl(), __CLASS__)
    ->setBrand(Module::getInstance()->get('name'))
    ->setClasses('navbar-inverse')
    ->link(
        Route::getInstance('www_guide')->getUrl(),
        'Руководство',
        ['active' => String::startsWith(Request::uri(), Route::getInstance('www_guide')->getUrl())]
    )
    ->link('/resource/api/Ice/1.0', 'Api', ['active' => false])
    ->dropdown(
        '#widgets',
        'Dropdown menu - Widgets',
        [
            'Widget Form' => '#forms',
            'Widget Menu' => '#menu',
            'Widget Data' => '#data',
        ]
    );
Результат:

Пагинация

$paginationMenu = Pagination::create(Request::uri(), __CLASS__)
    ->setFoundRows(1234)
    ->setClasses('pagination-sm')
    ->setStyle('margin: 0;')
    ->setPage(25)
    ->setLimit(30);
Результат:

Данные

Таблица

$tableData = Table::create(Request::uri(), __CLASS__)
    ->setClasses('table-striped table-bordered table-hover table-condensed')
    ->setStyle('background-color: #ffffff;')
    ->setHeaderStyle('background-color: #e7e7e7')
    ->setColumnCount(3)
    ->text('period', 'Период', ['rowspan' => 2])
    ->text('count', 'Просмотров', ['colspan' => 2])
    ->text('count1', 'люди')
    ->text('count2', 'роботы')
    ->setRows([
        [
            'period' => 'вчера',
            'count' => 5,
            'count1' => 3,
            'count2' => 2
        ],
        [
            'period' => 'сегодня',
            'count' => 8,
            'count1' => 5,
            'count2' => 3
        ]
    ]);
Результат:
# Период Просмотров
люди роботы
1 вчера 5
3 2
2 сегодня 8
5 3

Работа с данными

Валидаторы

Фильтры

Конвертеры

Обработка ошибок

Логгер

Warning

Logger::getInstance(Page::getClass())->warning('Ooou! warning', __FILE__, __LINE__);

Error

Logger::getInstance(Page::getClass())->error('Ooou! error', __FILE__, __LINE__);

Fatal - throw exception

Logger::getInstance(Page::getClass())->exception('Ooou! Something went wrong. Fix it.', __FILE__, __LINE__);

Debug in browser console

Logger::fb($debugVar);

Дебаггер

Debuger::dump($debugVar);
// or
Debuger::dumpDie($debugVar);

Профайлер

1. Создаем метку

$startTime = Profiler::getMicrotime();
$startMemory = Profiler::getMemoryGetUsage();

2. После проблемного кода фиксируем состояние

Profiler::setPoint('profilerPointName', $startTime, $startMemory);

3. Показываем результат

echo Profiler::getReport('profilerPointName');