Live News for Yii Framework News, fresh extensions and wiki articles about Yii framework. Fri, 23 Aug 2019 17:37:05 +0000 Zend_Feed_Writer 2 (http://framework.zend.com) https://www.yiiframework.com/ [extension] razonyang/yii2-rate-limiter Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/razonyang/yii2-rate-limiter https://www.yiiframework.com/extension/razonyang/yii2-rate-limiter razonyang razonyang

Yii2 Rate Limiter

  1. Backends
  2. Installation
  3. Usage

Build Status Scrutinizer Code Quality Code Coverage Latest Stable Version Total Downloads LICENSE

Backends

Installation

composer require razonyang/yii2-rate-limiter

Usage

Let's take 5000 requests every hours as example:

return [
    public function behaviors()
    {
        return [
            // redis via redis extension
            'rateLimiter' => [
                'class' => \RazonYang\Yii2\RateLimiter\RedisRateLimiter::class,
                'password' => '',
                'hostname' => 'localhost',
                'port' => 6379,
                'capacity' => 5000,
                'rate' => 0.72,
                'limitPeriod' => 3600,
                'prefix' => 'rate_limiter:',
                'ttl' => 3600,
                // 'nameCallback' => $callback,
            ],
            // redis via yii2-redis
            'rateLimiter' => [
                'class' => \RazonYang\Yii2\RateLimiter\Redis\RateLimiter::class,
                'redis' => 'redis', // redis component name or definition
                'capacity' => 5000,
                'rate' => 0.72,
                'limitPeriod' => 3600,
                'prefix' => 'rate_limiter:',
                'ttl' => 3600,
                // 'nameCallback' => $callback,
            ],

            // memcached
            'rateLimiter' => [
                'class' => \RazonYang\Yii2\RateLimiter\MemcachedRateLimiter::class,
                'hostname' => 'localhost',
                'port' => 11211,
                'capacity' => 5000,
                'rate' => 0.72,
                'limitPeriod' => 3600,
                'prefix' => 'rate_limiter:',
                'ttl' => 3600,
                // 'nameCallback' => $callback,
            ],
        ];
    }
];

RateLimiter takes uid:route(authorized) or ip:route(guest) as bucket name, you can also change this behavior via nameCallback:

$nameCallback = function (
    \yii\web\User $user,
    \yii\web\Request $request,
    \yii\base\Action $action
): string {
    return 'bucket name';
}
]]>
0
[extension] razonyang/yii2-app-template Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/razonyang/yii2-app-template https://www.yiiframework.com/extension/razonyang/yii2-app-template razonyang razonyang
  1. Yii2 App Template
  2. DEMO
  3. DOCUMENTATION
  4. DIRECTORY STRUCTURE
  5. Credit

Yii2 App Template

Build Status Scrutinizer Code Quality Code Coverage Latest Stable Version Total Downloads LICENSE

Yii2 App Project Template is a skeleton Yii 2 application best for developing complex web applications with multiple tiers.

There is a Yii2 Vue Admin for building a back end application.

DEMO

DOCUMENTATION

DIRECTORY STRUCTURE

app
    Console/             
        Controller/              contains console controller classes
        Model/                   contains console model classes
        Job/                     contains console job classes
    Exception/                   contains exception classes
    Form/                        contains form classes
    Http/
       Api/
           Backend/              contains back end API classes
           Frontend/             contains front end API classes
       Asset/                    contains web assets such as JavaScript and CSS
       Controller/               contains web controller classes
       Filter/                   contains web filters
       Form/                     contains web form classes
       Model/                    contains web model classes
       Module/                   contains web modules
       Widget/                   contains web widgets
    Job/                         contains web job classes
    Model/                       contains model classes
    Rbac/
        Rule/
    Validator/                   contains validators
bin/                             contains scripts
conf/                            contains conf files, such as crond job, systemd service unit etc
config/                          contains all of app configurations
public/                          contains the entry script and web resources
resources
    environments/                contains environment-based overrides
    mail/                        contains view files for e-mails
    messages/                    contains I18N emssages
    migrations/                  contains database migrations
    views/                       contains view files for the Web application
tests/                           contains tests    
vendor/                          contains dependent 3rd-party packages

Credit

It is a fork of Yii2 Advanced Template

]]>
0
[extension] razonyang/yii2-uploader Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/razonyang/yii2-uploader https://www.yiiframework.com/extension/razonyang/yii2-uploader razonyang razonyang

Yii2 Uploader

  1. Installation
  2. Usage

Build Status Scrutinizer Code Quality Code Coverage Latest Stable Version Total Downloads LICENSE

Installation

composer require razonyang/yii2-uploader

Usage

Configuration:

return [
    'components' => [
        'uploader' => [
            'class' => \RazonYang\Yii2\Uploader\Uploader::class,
            'host' => 'http://localhost/resources', // the hostname relative to your uploaded files
            'filesystem' => [
                // filesystem 
                'class' => \creocoder\flysystem\LocalFilesystem::class,
                'path' => '@webroot/resources',
            ],
        ],
    ],
];

And then defines a form, UploadForm

class UploadForm extends \yii\base\Model
{
    use \RazonYang\Yii2\Uploader\UploadModelTrait;

    public function handle()
    {
        if (!$this->validate()) {
            // handles error
            throw new \Exception('invalid file');
        }

        $url = $this->upload();
        return [
            'url' => $url,
            // ... other information
        ];
    }
}

class UploadController extends \yii\web\Controller
{
    public function actionUpload()
    {
        $form = new UploadForm([
            'file' => \yii\web\UploadedFile::getInstanceByName('file')
        ]);
        return $form->handle();
    }
}
]]>
0
[news] ApiDoc extension version 2.1.2 released Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/246/apidoc-extension-version-2-1-2-released https://www.yiiframework.com/news/246/apidoc-extension-version-2-1-2-released samdark samdark

We are very pleased to announce the release of the ApiDoc extension version 2.1.2.

This release upgrades highlight.js dependency to 9.13.1 and fixes multiple TOC rendering in ApiMarkdown.

See the CHANGELOG for a full list of changes.

]]>
0
[extension] owk/yii2-circular-navigation Tue, 20 Aug 2019 23:11:05 +0000 https://www.yiiframework.com/extension/owk/yii2-circular-navigation https://www.yiiframework.com/extension/owk/yii2-circular-navigation owk owk

Yii2 Circular navigation

  1. Installation
  2. Usage

Created by Codrops

http://www.codrops.com

>Integrate or build upon it for free in your personal or commercial projects. Don't republish, redistribute or sell "as-is".

Read more here: licensing

edited by owk

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist owk/yii2-circular-navigation

or add

"owk/yii2-circular-navigation": "^1.0.0"

to the require section of your composer.json file.

Usage

Once the extension is installed, simply use it in your view by : `php <?php echo owk\circularnavigation\CircularNavigation::widget([

            'cnoptions'=>[
                'menu' =>[
                    'background_color' => '#0088cd',
                    'background_color_hover' => 'rgb(12, 135, 212)',
                    // 'openLabel' => 'Menú',
                    // 'closeLabel' => 'Cerrar',
                    // 'color' => 'white'
                ],
                'item' => [
                    'background_color' => '-webkit-linear-gradient(90deg, #666666 0%,#319ed8 50%,#666666 100%)',
                    // 'background_color' => '#000',
                    // 'background_color_hover' => '#0088cd'
                ]
            ],
            'items' => [
                
                [
                    'url' =>'#',
                    'icon' =>'glyphicon-list-alt'
                ],
                [
                    'url' =>'/',
                    'icon' =>'glyphicon-home'
                ],
                [
                    'url' =>'#editar',
                    'icon' =>'glyphicon-pencil'
                ],
                // [
                //     'url' =>'#enviar',
                //     'icon' =>'glyphicon-send'
                // ],
                [
                    'url' =>'#table',
                    'icon' =>'glyphicon-duplicate'
                ]
                ,
                [
                    'url' =>'#aceptar',
                    'icon' =>'glyphicon-phone'
                ]
            ]
            ]);?>

]]>
0
[news] Debug extension 2.1.8 released Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/245/debug-extension-2-1-8-released https://www.yiiframework.com/news/245/debug-extension-2-1-8-released samdark samdark

Debug extension version 2.1.8 was released.

This version fixes two bugs:

  • Infinite redirect when URL normalizer is turned on
  • Broken user switching from the toolbar

See the CHANGELOG for details.

]]>
0
[wiki] Move sources to src Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/wiki/2550/move-sources-to-src https://www.yiiframework.com/wiki/2550/move-sources-to-src samdark samdark

Yii 3 and many Yii 2 package sources are contained within src directory which is convenient since you have less directories to check.

/config
/runtime
/src
  /assets
  /commands
  /controllers
  /mail
  /models
  /views
  /widgets
/tests
/vendor
/web
yii

Let's start with the basic applicaiton template.

  1. Create src directory.
  2. Move source directories there.
  3. Adjust config/web.php:
$config = [
    // ...
    'basePath' => dirname(__DIR__) . '/src',
    // ...
    'aliases' => [
        '@vendor' => dirname(__DIR__) . '/vendor',
        '@runtime' => dirname(__DIR__) . '/runtime',
        // ...
    ],
    // ...
];

And config/console.php:

$config = [
    // ...
    'basePath' => dirname(__DIR__) . '/src',
    // ...
    'aliases' => [
        '@vendor' => dirname(__DIR__) . '/vendor',
        '@runtime' => dirname(__DIR__) . '/runtime',
        // ...
    ],
    // ...
];

That's it now you have both console and web application source code in src.

]]>
0
[news] Yii 2.0.25 Tue, 13 Aug 2019 20:09:34 +0000 https://www.yiiframework.com/news/244/yii-2-0-25 https://www.yiiframework.com/news/244/yii-2-0-25 samdark samdark

We are very pleased to announce the release of Yii Framework version 2.0.25. Please refer to the instructions at https://www.yiiframework.com/download/ to install or upgrade to this version.

Version 2.0.25 is a minor release of Yii 2.0. This release includes bug fixes accumulated since last release.

Thanks to all Yii community members who contribute to the framework, translators who keep documentation translations up to date and community members who answer questions at forums.

There are many active Yii communities so if you need help or want to share your experience, feel free to join them.

A complete list of changes can be found in the CHANGELOG.

]]>
0
[news] Gii extension 2.1.1 released Tue, 13 Aug 2019 14:37:18 +0000 https://www.yiiframework.com/news/243/gii-extension-2-1-1-released https://www.yiiframework.com/news/243/gii-extension-2-1-1-released samdark samdark

We are very pleased to announce the release of Gii extension version 2.1.1 fixing a bug not highlighting part of the diff preview.

See the CHANGELOG for details.

]]>
0
[news] Bootstrap 4 extension version 2.0.7 released Tue, 13 Aug 2019 11:53:10 +0000 https://www.yiiframework.com/news/242/bootstrap-4-extension-version-2-0-7-released https://www.yiiframework.com/news/242/bootstrap-4-extension-version-2-0-7-released samdark samdark

Bootstrap 4 extension version 2.0.7 was released. This version fixes a bug in displaying error message for checkbox and radio lists and allowing to override all CSS classes via widget factory.

Thanks to @simialbi for taking care of the extension!

See CHANGELOG for details.

]]>
0
[extension] diecoding/yii2-core Mon, 12 Aug 2019 16:01:55 +0000 https://www.yiiframework.com/extension/diecoding/yii2-core https://www.yiiframework.com/extension/diecoding/yii2-core die-coding die-coding

Yii2 Core

  1. Cara Memasang
  2. List Class

Tidak ada dokumentasi, karena hanya untuk tambahan internal Die Coding saja ^_^

Latest Version Software License Quality Score Total Downloads

Cara Memasang

  • Melalui console
composer require --prefer-dist diecoding/yii2-core "dev-master"
  • Melalui composer.json
  1. Tambahkan pada baris require
"diecoding/yii2-core": "dev-master"
  1. Kemudian jalankan
composer update

List Class

\diecoding\behaviors\TouchDbBehavior();

\diecoding\behaviors\TouchDbBehavior();


\diecoding\helpers\Date();
]]>
0
[extension] razonyang/yii2-jsend Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/razonyang/yii2-jsend https://www.yiiframework.com/extension/razonyang/yii2-jsend razonyang razonyang

JSend port for Yii2

  1. Installation
  2. Usage
  3. Error Handler

Build Status Scrutinizer Code Quality Code Coverage Latest Stable Version Total Downloads LICENSE

The package is a Yii2's implementation of JSend specification.

Installation

composer require razonyang/yii2-jsend

Usage

Update resposne formater and error handler:

return [
    'components' => [
        'response' => [
            'formatters' => [
                \yii\web\Response::JSON => [
                    'class' => \RazonYang\Yii2\JSend\Formatter::class,
                ],
            ],
        ],
        'errorHandler' => [
            'class' => \RazonYang\Yii2\JSend\ErrorHandler::class,
        ],
    ],
];

Change you rest controller serializer:

public $serializer = \RazonYang\Yii2\JSend\Serializer::class;

Error Handler

ErrorHandler converts exception to error payload:

{
    "status": "error",
    "code": "exception code",
    "message": "exception message"
}

It can also returns the optional data field by throwing a JSend's Exception:

throws new RazonYang\Jsend\Exception($message, $code, $data, $previous);

// you can also define your own exception:
class MyException extends RazonYang\Jsend\Exception
{
}

throws new MyException();
{
    "status": "error",
    "code": "exception code",
    "message": "exception message",
    "data": "exception data"
}
]]>
0
[extension] instafeed Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/instafeed https://www.yiiframework.com/extension/instafeed IlliaBasharov IlliaBasharov
  1. Requirements
  2. Installation
  3. Usage
  4. Resources

...overview of the extension...

Requirements

...requirements of using this extension (e.g. Yii 2.0 or above)...

Installation

...how to install the extension (e.g. composer install extensionname)...

Usage

...how to use this extension...

...can use code blocks like the following...

$model=new User;
$model->save();

Resources

DELETE THIS SECTION IF YOU DO NOT HAVE IT

...external resources for this extension...

  • [Project page](URL to your project page)
  • [Try out a demo](URL to your project demo page)
]]>
0
[news] Yii 2.0.24 Tue, 30 Jul 2019 15:57:22 +0000 https://www.yiiframework.com/news/241/yii-2-0-24 https://www.yiiframework.com/news/241/yii-2-0-24 samdark samdark

We are very pleased to announce the release of Yii Framework version 2.0.24. Please refer to the instructions at https://www.yiiframework.com/download/ to install or upgrade to this version.

Version 2.0.24 is a minor release of Yii 2.0. In this release 8 bugs were fixed.

It includes further work on MSSQL, migration fixes, subdomain support for User::loginRequired() and a fix for logger replacement.

Thanks to all Yii community members who contribute to the framework, translators who keep documentation translations up to date and community members who answer questions at forums.

There are many active Yii communities so if you need help or want to share your experience, feel free to join them.

A complete list of changes can be found in the CHANGELOG.

]]>
0
[news] Debug extension 2.1.7 released Tue, 30 Jul 2019 12:50:23 +0000 https://www.yiiframework.com/news/240/debug-extension-2-1-7-released https://www.yiiframework.com/news/240/debug-extension-2-1-7-released samdark samdark

Debug extension version 2.1.7 was released.

This version fixes regression in previous release regarding edge cases of closure serialization, fixes insufficient ouput escaping that may lead to XSS and adds "since previous" and sequential number to "logs" panel detail view:

aop7x-ywototms6dffcoa0_5jmo.png

See the CHANGELOG for details.

]]>
0
[extension] wxxiong6/yii-seaslog Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/wxxiong6/yii-seaslog https://www.yiiframework.com/extension/wxxiong6/yii-seaslog wxxiong6 wxxiong6

yii2-seasLog extension

  1. Requirements
  2. Installation
  3. Usage
  4. Changelog

使用SeasLog高效日志扩展替换Yii2框架的日志模块,使其提高写日志效率。只需配置就可以实现。

SeasLog扩展https://github.com/SeasX/SeasLog/

Requirements

  • Yii2
  • PHP >=5.4
  • ext-seaslog installed

Installation

composer require wxxiong6/yii-seaslog:"1.0.0"

Usage

main.php

    'log' => [
            'traceLevel' => YII_DEBUG ? 3 : 0,
            'targets' => [
                'default' => [
                    'class' => 'wxxiong6\yii\seaslog\Yii2SeasLog',
                    'levels' => ['trace', 'info', 'error', 'warning'],
                    'logFile' => 'backend/runtime/',
                    'logVars' => [],
                ],
            ],
        ],

为了跟yii2日志格式一致,修改php.ini seaslog日志格式

seaslog.default_template = %T %M

Changelog

Release 1.0 - Changelog
  • Official stable release
]]>
0
[extension] practically/yii2-chartjs Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/practically/yii2-chartjs https://www.yiiframework.com/extension/practically/yii2-chartjs AdeAttwood AdeAttwood

Yii2 Chart JS

  1. Installation
  2. Usage
  3. Contributing
  4. Credits

Wrapper for chart js in Yii2. Easily turn Yii2 querys into beautiful charts.

Installation

The preferred way is with composer.

composer require practically/yii2-chartjs

Note: This package does not handle the installation of chart js library. For that you can visit the chart js website

You can also install with the asset packagist

composer require bower-asset/chart-js

Usage

Basic usage
use practically\chartjs\Chart;

echo Chart::widget([
    'type' => Chart::TYPE_BAR,
    'datasets' => [
        [
            'data' => [
                'Label 1' => 10,
                'Label 2' => 20,
                'Label 3' => 30
            ]
        ]
    ]
]);
Using a db query to define the data
echo Chart::widget([
    'type' => Chart::TYPE_BAR,
    'datasets' => [
        [
            'query' => Model::find()
                ->select('type')
                ->addSelect('count(*) as data')
                ->groupBy('type')
                ->createCommand(),
            'labelAttribute' => 'type'
        ]
    ]
]);
Adding dom options
echo Chart::widget([
    ...

    'options' => [
        'class' => 'chart',
        'data-attribute' => 'my-value'
    ],

    ...
]);
Adding client options

In the client options array you can define any property to be json encoded and passed to the chart js constructor.

echo Chart::widget([
    ...

    'clientOptions' => [
        'title' => [
            'display' => true,
            'text' => 'My New Title',
        ],
        'legend' => ['display' => false],
    ]

    ...
]);
Formatting the y axes
echo Chart::widget([
    ...

     'clientOptions' => [
        'scales' => [
            'yAxes' => [
                [
                    'ticks' => [
                        'callback' => new JsExpression('function(value, index, values) {
                             return \'£\'+value;
                        }')
                    ]
                ]
            ]
        ],
        'tooltips' => [
            'callbacks' => [
                'label' => new JsExpression('function(tooltipItem, chart) {
                    var datasetLabel = chart.datasets[tooltipItem.datasetIndex].label || \'\';
                    return datasetLabel + \' £\'+tooltipItem.yLabel;
                }')
            ]
        ]
    ]

    ...
]);
Adding chart js events
Chart::widget([
    'type' => Chart::TYPE_DOUGHNUT,
    'jsVar' => 'DoughnutChart',
    'jsEvents' => [
        'onclick' => new JsExpression('function(e) {
            var el = DoughnutChart.getElementAtEvent(e);
            window.location.href = "/search/ + el[0]._model.label;
        }')
    ]
]);

Contributing

Getting set up

Clone the repo and run composer install. Then start hacking!

Testing

All new features of bug fixes must be tested. Testing is with phpunit and can be run with the following command

composer run-script test
Coding Standards

This library uses psr2 coding standards and squizlabs/php_codesniffer for linting. There is a composer script for this:

composer run-script lint
Pull Requests

Before you create a pull request with you changes, the pre-commit script must pass. That can be run as follows:

composer run-script pre-commit

Credits

This package is created and maintained by Practically.io

]]>
0
[news] Debug extension 2.1.6 released Tue, 23 Jul 2019 20:30:20 +0000 https://www.yiiframework.com/news/239/debug-extension-2-1-6-released https://www.yiiframework.com/news/239/debug-extension-2-1-6-released samdark samdark

Debug extension version 2.1.6 was released containing five enhancements:

  • Total request processing time and peak memory consumption were added on index page for each request
  • Improved error when no debug data present
  • Browser compatibility was improved so toolbar now works with IE and older browsers
  • Closures are now serialized with the help of opis/closure eliminating related issues
  • Module got tracePathMappings option that allows you to fine tune stacktrace links to work for Docker image with file system mapped to host machine

See the CHANGELOG for details.

]]>
0
[news] Bootstrap 4 extension version 2.0.6 released Tue, 23 Jul 2019 16:32:56 +0000 https://www.yiiframework.com/news/238/bootstrap-4-extension-version-2-0-6-released https://www.yiiframework.com/news/238/bootstrap-4-extension-version-2-0-6-released samdark samdark

Bootstrap 4 extension version 2.0.6 was released. In this version there are two changes.

First, documentation on how to migrate from Bootstrap 3 was added.

Second, simplified syntax for progress bars that was present in Bootstrap 3 was brought back:

echo Progress::widget([
     'percent' => 65,
     'barOptions' => ['class' => 'progress-bar-danger']
]);

Thanks to @simialbi for both changes.

See CHANGELOG for details.

]]>
0
[extension] yii-ui/yii2-flag-icon-css-widget Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/yii-ui/yii2-flag-icon-css-widget https://www.yiiframework.com/extension/yii-ui/yii2-flag-icon-css-widget cmoeke cmoeke

Yii UI Yii UI - Yii2 Flag icon css - Widget

  1. Installation
  2. Usage
  3. Documentation
  4. License

Latest Stable Version Total Downloads Yii2 License

This is an Yii framework 2.0 widget of the Lipis flag-icon-css package.

If you are looking for the asset bundle, please install yii-ui/yii2-flag-icon-css-asset-bundle.

Installation

The preferred way to install this extension is through composer.

Either run php composer.phar require yii-ui/yii2-flag-icon-css-widget or add "yii-ui/yii2-flag-icon-css-widget": "^1.0" to the require section of your composer.json file.

Usage

use yiiui\yii2flagiconcss\widget\FlagIcon;

echo FlagIcon::widget([
    'countryCode' => 'de',
    'options' => [
        'class' => 'example-flag'
    ],
    'squared' => true,
]);

See https://www.yii-ui.com/packages/yii2-flag-icon-css-widget for more infos. For plugin configuration see Lipis flag-icon-css Documentation.

Documentation

Documentation can be found at https://www.yii-ui.com/packages/yii2-flag-icon-css-widget/docs.

License

yii2-flag-icon-css-widget is released under the MIT License. See the LICENSE for details.

]]>
0
[extension] yii-ui/yii2-flag-icon-css-asset-bundle Tue, 06 Aug 2019 10:00:34 +0000 https://www.yiiframework.com/extension/yii-ui/yii2-flag-icon-css-asset-bundle https://www.yiiframework.com/extension/yii-ui/yii2-flag-icon-css-asset-bundle cmoeke cmoeke ]]> 0 [extension] execut/yii2-import Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/execut/yii2-import https://www.yiiframework.com/extension/execut/yii2-import eXeCUT eXeCUT

Latest Version Build Status Coverage Status Scrutinizer Code Quality SensioLabsInsight Packagist Downloads

yii2-import

Fast and flexible Yii2 module for importing and synchronizing anything into the database through activeRecord

Installation

The preferred way to install this extension is through composer.

Install

Either run

$ php composer.phar require execut/yii2-import "dev-master"

or add

"execut/yii2-import": "dev-master"

to the `require` section of your composer.json file.

Configuration

Add module bootstrap and application language in target web application config: `php

...
'language' => 'ru',
'bootstrap' => [
...
    'import' => [
        'class' => \execut\import\bootstrap\Backend::class,
    ]
...
],

Add module bootstrap in console application config:
```php
    'bootstrap' => [
    ...
        'import' => [
            'class' => \execut\import\bootstrap\Console::class,
        ]
    ...
    ],

For activate i18n translation set you application language in config: `php


Apply migrations via yii command:

./yii migrate/up --migrationPath=vendor/kartik-v/yii2-dynagrid/src/migrations `

After configuration, the module should open by paths: import/files import/settings

Module navigation

You may output navigation of module inside your layout via execut/yii2-navigation: `php

echo Nav::widget([
    ...
    'items' => \yii\helpers\ArrayHelper::merge($menuItems, \yii::$app->navigation->getMenuItems()),
    ...
]);
NavBar::end();

// Before standard breadcrumbs render breadcrumbs and header widget:
echo \execut\navigation\widgets\Breadcrumbs::widget();
echo \execut\navigation\widgets\Header::widget();
For more information about execut/yii2-navigation module, please read it [documentation](https://github.com/execut/yii2-navigation)

Further instructions will be in Russian, because there is no time to translate, your help is welcome.

### Описание разделов
#### Файлы

По адресу import/files происходит управление файлами, которые импортируются. Здесь можно вручную загружать новые
и управлять загрузками. Каждому файлу можно выставить статусы и консольная команда для импорта подхватит его:
* New - загрузить файл
* Reload - перезагрузиь файл
* Delete - удалить файл
* Loaded - файл загружен
* Stop - остановить загрузку
* Error - ошибка загрузки файла

Остальные статусы используются консольной командой для отображения процесса импорта и если их выставить вручную,
поведение импорта непредсказуемо:
* Loading - файл в процессе импорта
* Stopped - импорт файла остановлен
* Deleting - файл в процессе удаления

#### Настройки

По адресу import/settings можно управлять настройками, через которые происходит захват файлов их внешних источников,
разбор файлов на данные и их запись в базу данных.

Чтобы начать производить настройки импорта, модулю необходимо указнать про ваше окружение базы данных через реализацию
плагина execut\import\Plugin. Подробнее о том как реализовать этот плагин, смотрите раздел
[создание плагинов](#создание-плагинов)

#### Консоль

В консоли есть 3 команды:
##### import
Команда ./yii import запускает процесс импорта и удаления файлов. Этот процесс пошагово выглядит так:
1. Отбирается самый старый по дате создания файл со статусом New и Reload
2. Удаляется старый файл с такой-же настройкой как и новый
3. Происходит его парсинг и запись в БД
4. Шаг 1 повторяется

Эта команда поддерживает её параллельный запуск для большей скорости импорта.
У команды есть единственный необязательный аргумент: идентификатор файла, который необходимо импортировать. Если его
передать, то указанный файл начнёт импортироваться через шаги 1-3. После выполнения шага 3 процесс выполнения команды
обрывается

##### import/check-source
./yii import/check-source выполняет процесс захвата файлов из внешних источников через настройки и их запись в базу для
последующего запуска.
Аргументы команды:
* type - тип источника. Может быть email, ftp или site.
* id - идентификатор настройки. Если указать его, то произойдёт захват только указанной настройки.

Команда поддерживает параллельный запуск.

##### import/release-trigger
./yii import/release-trigger очищает все mutex-триггеры. Применяется для случаев, если произошёл сбой при выполнении
команд для разблокировки их дальнейшего выполнения.

##### Автоматический захват файлов
Для системы Linux есть два способа настройки автоматического захвата файлов. Через cron или с помощью службы systemd.
###### Systemd
Через службу systemd желательней, поскольку ею пользоваться удобнее и не нужно заботиться об отказоустойчивости демона.
Служба сама будет перезапускаться в случае его отказа. Для настройки службы нужно создать unit нового сервиса. В случае
ubuntu для этого нужно создать файл yii2-import.service в папке /etc/systemd/system/ со следующим содержимым:

[Unit] Description=eXeCUT Yii2 import service

[Service] Type=simple User={Пользователь, из под которого происходит запуск приложения} ExecStart={Путь до приложения}/yii import/check-source-daemon email Restart=always

[Install] WantedBy=multi-user.target `

После этого можно запустить службу командой service yii2-import start и следить за ней через лог /var/log/syslog

Cron

Чтобы запускать по крону необходимо добавить новый файл в папке /etc/cron.d/ или новые строчки в файл /etc/crontab со следующим содержимым: */5 * * * * {Пользователь} {Путь до приложения}/yii import/check-source 0 8 * * * {Пользователь} {Путь до приложения}/yii import/check-source ftp; 0 8 * * * {Пользователь} {Путь до приложения}/yii import/check-source site; Этот пример запускает раз в 5 минут захват почты и в 8 утра захват с фтп и сайтов.

Создание плагинов
Создание простых записей

Для изучения принципа создания плагина, рассмотрим простой пример. У нас есть товар. У товара есть название и цена. Нам нужно импортировать этот товар в базу данных каталога. Применим миграции примера: `ssh ./yii migrate/up --migrationPath=vendor/execut/yii2-import/example/migrations `

Подключим плагин простого плагина через конфигурационные файлы двух приложений консольного и web, в тех строках, что мы задавали раннее для запуска модуля: `php

            'import' => [

//'class' => \execut\import\bootstrap\Console::class,

                'depends' => [
                    'modules' => [
                        'import' => [
                            'plugins' => [
                                'simple' => [
                                    'class' => \execut\import\example\Plugin::class,
                                ],
                            ],
                        ],
                    ],
                ],
            ],

После этого в админке настроек импорта появляется возможность задавать настройки для ипорта товаров с
двумя полями: названием и ценой.
Перейдём по адресу import/settings и создадим в этой админке настройку со следующими полями:

1. Название: Простой товар
1. Пропустить строк: 1
1. Кодировка файла: UTF-8
1. Источник захвата файла: Вручню
1. Листы
   1. Название: Первый лист
       1. Тип: Product
           1. Тип: Product name, Колонка: 1
           1. Тип: Product price, Колонка: 2

![Sheet example](docs/sheet.jpg)

В результате мы настроили возможность загружать файл, расположенный внутри папки компонента: example/data/products.gnumeric
Попробуем его загрузить через админку файлов импорта import/files, выбрав следующие значения полей:
1. Файл: выбираем файл example/data/products.gnumeric
1. Настройки: выбираем раннее созданную настройку "Простой товар"
1. Источник захвата файла: Вручную

И пробуем этот файл загрузить в базу через консольную команду:
```bash
> ./yii import
Start check failed files
End check failed files
Start parse file #1 products.gnumeric
start extract example_product_id
start construct where example_product_id
end construct where example_product_id after 0.0058150291442871 seconds
start find example_product_id
end find example_product_id after 0.014003992080688 seconds
start keys collect example_product_id
end keys collect example_product_id after 4.0531158447266E-6 seconds
start models collect example_product_id
end models collect example_product_id after 0.24526405334473 seconds
end extract example_product_id after 0.26518106460571 seconds
Row #0: Saving example_products # a:2:{s:4:"name";s:1:"1";s:5:"price";s:9:"Product 1";} because they is created
Row #1: Saving example_products # a:2:{s:4:"name";s:1:"2";s:5:"price";s:9:"Product 2";} because they is created
Row #2: Saving example_products # a:2:{s:4:"name";s:1:"3";s:5:"price";s:9:"Product 3";} because they is created
...

В результате импорта в таблице example_products должны появиться 2500 товаров

Создание записей через связи

Расширим пример выше, но, уже импортируя товар через артикулы. Для этого подключим другой плагин указанным выше образом: execut\import\example\withRelations\Plugin Этот плагин позволит загружать и синхронизировать товары по связке их артикул\производитель. Необходимо скорректировать созданную раннее настройку, указав 3 и 5 столбец как Article и Brand соответственно. После этого указываем статус файла "Перезагрузить" и загружаем его вновь: `bash > ./yii import `

После этого должны появиться 3 производителя, 2499 их артикулов и 2499 товаров с ними. Если попробовать вновь загрузить файл, то ничего не должно измениться в БД, поскольку изменений в файле не было.

Усложненный поиск записей

Есть возможность усложнить поиск записей, если, например, в файлах один и тот-же производитель может называться по разному. Для этого модели производителя необходимо наследовать интерфейс execut\import\ModelInterface и вычислить в нём все возможные варианты названия активного производителя, а в объекте запроса ActiveQuery для этой модели унаследовать execut\import\Query и в нём задать новый способ поиска.

]]>
0
[news] Yii 2.0.23 Tue, 16 Jul 2019 20:37:03 +0000 https://www.yiiframework.com/news/237/yii-2-0-23 https://www.yiiframework.com/news/237/yii-2-0-23 samdark samdark

We are very pleased to announce the release of Yii Framework version 2.0.23. Please refer to the instructions at https://www.yiiframework.com/download/ to install or upgrade to this version.

Version 2.0.23 is a minor release of Yii 2.0. In this release 5 bugs were fixed with the main focus on MSSQL database support. All fixes were made by Alexander Kartavenko. Thank you!

Thanks to all Yii community members who contribute to the framework, translators who keep documentation translations up to date and community members who answer questions at forums.

There are many active Yii communities so if you need help or want to share your experience, feel free to join them.

A complete list of changes can be found in the CHANGELOG.

]]>
0
[extension] rafaeldsb/yii2-rabbitmq-log Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/rafaeldsb/yii2-rabbitmq-log https://www.yiiframework.com/extension/rafaeldsb/yii2-rabbitmq-log rafaeldsb rafaeldsb

yii2-rabbitmq-log

Geração de logs estruturados e envio para o rabbitmq para projetos baseado no yii2

Instalação


## Configuração
Edite o arquivo de configuração e acrescente o componente e adicione ele no bootstrap da aplicação:
```php
return [
    ...
    'components' => [
        ...
        'rabbitmq' => [
            'class' => \rafaeldsb\rabbitmqlog\RabbitMQ::className(),
            'host' => 'localhost',
            'port' => 5672,
            'user' => 'SeuUsuarioRabbitMQ',
            'password' => 'SuaSenhaRabbitMQ',
            'vHost' => 'SeuVHostRabbitmq',
            'queues' => [
                [
                    'queue' => 'NomeDaSuaFila',
                    'passive' => false,
                    'durable' => true,
                    'exclusive' => false,
                    'auto_delete' => false
                ]
            ],
            'defaultRoutingKey' => 'RoutingKey',
            'logClass' => 'SuaClasseCustomizadaDeLogs' // Opcional
        ]
    ],
    'bootstrap' => [
        'rabbitmq'
    ],
    ...
]
```

]]>
0
[extension] execut/yii2-autosize-textarea Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/execut/yii2-autosize-textarea https://www.yiiframework.com/extension/execut/yii2-autosize-textarea eXeCUT eXeCUT

Autosize textarea widget for Yii2 based on jquery.ns-autogrow plugin

  1. Installation
  2. Example
  3. License

Plugin page

Installation

The preferred way to install this extension is through composer.

Install

Either run

$ php composer.phar require execut/yii2-autosize-textarea "dev-master"

or add

"execut/yii2-autosize-textarea": "dev-master"

to the `require` section of your composer.json file.

Example

use execut\autosizeTextarea\TextareaWidget;

class Model extends \yii\base\Model {
    public $text = null;
    public function rules()
    {
        return [['text', 'safe']];
    }
}

$form = \yii\widgets\ActiveForm::begin();
echo $form->field(new \Model(), 'text')->widget(TextareaWidget::class, [
    'options' => [
        'style' => 'height: 30px', // If you want set textarea height
    ],
    'clientOptions' => [
        'vertical' => true, //(true/false) - Enable/Disable vertical autogrow (true by default)
        'horizontal' => true, //(true/false) - Enable/Disable horizontal autogrow (true by default)
        'postGrowCallback' => new JsExpression('function () {console.debug(\'post grow callback\');}'),
        //Post grow callback. Executes after dimensions of textarea have been adjusted.
        'flickering' => true, //(true/false) - Enable/Disable flickering.
        //If flickering is disabled, extra line will be added to textarea.
        //Flickering is enabled by default.
        'debugx' => -10000, // X position of shadow element (-10000 by default)
        'debugy' => -10000, // Y position of shadow element (-10000 by default)
        'debugcolor' => 'yellow', // Color of shadow element (yellow by default)
    ]
]);
\yii\widgets\ActiveForm::end();

Example autosize textarea widget for Yii2

License

yii2-autosize-textarea is released under the Apache License Version 2.0. See the bundled LICENSE.md for details.

]]>
0
[extension] yii2-admin-openadm Fri, 05 Jul 2019 14:57:52 +0000 https://www.yiiframework.com/extension/yii2-admin-openadm https://www.yiiframework.com/extension/yii2-admin-openadm xiongchuan xiongchuan
  1. introduce
  2. Source
  3. Installation
  4. Usage
  5. Migrate DB
  6. screenshots
  • introduce

    openadm/yii2-admin 基于yii2-extension包管理和adminlte2主题构建的admin项目,包括了基础的用户管理,RBAC管理,扩展管理等核心功能。

去OpenADM 查看更多

Either run

php composer.phar require --prefer-dist openadm/yii2-admin "*"

or add

"openadm/yii2-admin": "*"

to the require section of your composer.json file.

  • Usage

    Once the extension is installed, simply use it in your code by :

  • Migrate DB

./yii migrate --migrationPath=@openadm/admin/migrations
./yii migrate all -p=@tecnocen/oauth2server/migrations/tables
  • screenshots

down?path=%2F1%2FeUd4l9IbwawbFN9m4gAzK901bzdXkFdJ.png

down?path=%2F1%2F9EFYYbX1vDHF7d0NMaqFx5VCk-GKNng_.png

]]>
0
[extension] sjaakp/yii2-novelty Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/sjaakp/yii2-novelty https://www.yiiframework.com/extension/sjaakp/yii2-novelty sjaakp sjaakp

yii2-novelty

  1. Property indicating novelty of Yii2 ActiveRecord
  2. Installation
  3. Using NoveltyBehavior
  4. Options

Property indicating novelty of Yii2 ActiveRecord

yii2-novelty is a behavior that adds a property with the name 'novelty' to an ActiveRecord in the Yii2 PHP framework. This property has one of the following three values:

  • 'new' in case the record is created since the user visited the site previously;
  • 'updated' in case the record is updated since the user visited the site previously;
  • null in other cases.

The class NoveltyBehavior extends om Yii's TimestampBehavior. The value of novelty is based on the attribute values of TimestampBehavior, usually called 'created_at' and 'updated_at', and on the time the user visited the site previously. The previous visit time is stored in two cookies.

Installation

Install yii2-novelty in the usual way with Composer. Add the following to the require section of your composer.json file:

"sjaakp/yii2-novelty": "*"

or run:

composer require sjaakp/yii2-novelty

You can manually install yii2-novelty by downloading the source in ZIP-format.

Using NoveltyBehavior

Add NoveltyBehavior to your ActiveRecord like this:

<?php

use sjaakp\novelty\NoveltyBehavior;

class MyRecord extends ActiveRecord
{
    public function behaviors( ) {
	    return [
	        [
	            'class' => NoveltyBehavior::class,
	            // ... options ...
	        ],
	        // ... more behaviors ...
	    ];
	}
	...
}

NoveltyBehavior extends on yii\behaviors\TimestampBehavior, so you shouldn't use them together.

After adding NoveltyBehavior the ActiveRecord has an extra property 'novelty', which can be read like any other property, f.i. with:

$novelty = $record->novelty;

It is a read-only property, so it cannot be written to.

Options

In most cases, NoveltyBehavior will work out of the box. The following options are available for finetuning. All are optional.

  • noveltyAttribute string Name of the read-only attribute. Default: 'novelty'.
  • visitCookie string Name of the cookie storing the previous visit time. Default: 'visit'.
  • visitStamina integer Expiration time of the visit-cookie in seconds. Default: 31536000 (one year).
  • cacheCookie string Name of the cookie caching the previous visit time. Default: 'visit-cache'.
  • cacheStamina integer Expiration time of the cache-cookie in seconds. Default: 1800 (30 minutes).
  • format null|string PHP date() format of the TimestampBehavior attributes. If null, this will be set with the right values for value is null, or for value set to new Expression('NOW()'), i.e. virtually all use cases. Only in really exotic cases might this be set to anything else than null. Default: null.
  • noveltyValues array Possible values assigned to novelty. Default: see source.

NoveltyBehavior also inherits all the options of yii\behaviors\TimestampBehavior.

]]>
0
[extension] yii2generalsetting/yii2generalsetting Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/yii2generalsetting/yii2generalsetting https://www.yiiframework.com/extension/yii2generalsetting/yii2generalsetting agsachdev agsachdev

General Setting - V1

  1. Installation
  2. Migrate First
  3. Usage

General Setting

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist yii2generalsetting/yii2generalsetting "*"

or add

"yii2generalsetting/yii2generalsetting": "*"

to the require section of your composer.json file.

Migrate First

php yii migrate --migrationPath=vendor/groovy/src/migrations

Usage

Once the extension is installed, simply use it in your code by :

'components' => [
    'getsettings' => [
        'class' => 'vendor\yii2generalsetting\yii2generalsetting\src\components\Groovysettings',
        'development'=>false,
        's3UploadFiles'=>false,
    ],
],

'modules' => [
    'allsettings' => [
        'class' => 'vendor\yii2generalsetting\yii2generalsetting\src\modules\allsettings\Module',
    ]
],

open link YOUR_SITE_URL/allsetting


Get Data 
-----

Yii::$app->getsettings->Getallsttings('json'); //get json format
Yii::$app->getsettings->Getallsttings('array'); //get array format

//Single Value By Name
$apiKey = Yii::$app->getsettings->Getcategorysingleconfig('Front Settings','Google Key'); //Front Settings = Setting Name and Google Key = Field Name


Notice
-----
if You old user so please add ENUM (textarea) in s_type (all_setting_fields table )
Other Wise got a error 
Thank you
]]>
0
[extension] groovy/src Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/groovy/src https://www.yiiframework.com/extension/groovy/src agsachdev agsachdev

Groovy Email Template

  1. Installation ---- V1.4
  2. Migrate First
  3. Add Module
  4. Add components
  5. Usage

Groovy Email Template

Installation ---- V1.4

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist groovy/src "*"

or add

"groovy/src": "dev-master"

to the require section of your composer.json file.

Migrate First

php yii migrate --migrationPath=vendor/groovy/src/migrations

Add Module

'email' => [
    'class' => 'vendor\groovy\src\email\Module',
],

Add components

'emailtemplate' => [
    'class' => 'vendor\groovy\src\email\components\EmailsTemplate',
    'allowDelete'=>false,
    'allowInsert'=>true,
    'dummycontent'=> dirname(dirname(__DIR__))."/frontend/web/emailtemplate/dummy.html",
    'icons'=>["update"=>"glyphicon glyphicon-pencil","view"=>"glyphicon glyphicon-eye-open","delete"=>"glyphicon glyphicon-trash"],
    'breadcrumbs'=> dirname(dirname(__DIR__))."/frontend/web/breadcrumbs/breadcrumbs.php",
],

Usage

// Need Email HTML dynamic
$string_array = array(
    '{{Password}}'=>$password,
);
$html = Yii::$app->emailtemplate->replace_string_email($string_array ,"welcome_email"); // $string_array = Array Of String welcome_email = Email Slug

// Need Email HTML Subject
$subject_string_array = array(
     "{{app_name}}"=>Yii::$app->name
);
$subject = Yii::$app->emailtemplate->replace_string_email($subject_string_array ,"welcome_email","subject");// $string_array = Array Of String welcome_mail = Email Slug and subject

]]>
0
[extension] nterms/yii2-mailqueue Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/nterms/yii2-mailqueue https://www.yiiframework.com/extension/nterms/yii2-mailqueue nterms nterms

yii2-mailqueue

  1. Installation
  2. Configuration
  3. Updating database schema
  4. Processing the mail queue
  5. Setting the CRON job
  6. Usage
  7. License

Email queue component for yii2 that works with yii2-swiftmailer

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist nterms/yii2-mailqueue "*"

or add

"nterms/yii2-mailqueue": "*"

to the require section of your composer.json file.

Configuration

Once the extension is installed, add following code to your application configuration :

return [
    //....
    'components' => [
        'mailqueue' => [
            'class' => 'nterms\mailqueue\MailQueue',
			'table' => '{{%mail_queue}}',
			'mailsPerRound' => 10,
			'maxAttempts' => 3,
        ],
    ],
];

Following properties are available for customizing the mail queue behavior.

  • table: Name of the database table to store emails added to the queue.
  • mailsPerRound: Number of emails to send at a time.
  • maxAttempts: Maximum number of sending attempts per email.

Updating database schema

Apply the database migration to create the table required to store the mail queue messages. To do this, add following code to /config/console.php:

return [
    //....
    'components' => [
        'mailqueue' => [
            'class' => 'nterms\mailqueue\MailQueue',
			'table' => '{{%mail_queue}}',
        ],
    ],
];

then run yii migrate command in command line:

php yii migrate/up --migrationPath=@vendor/nterms/yii2-mailqueue/migrations/

Processing the mail queue

Now calling process() on Yii::$app->mailqueue will process the message queue and send out the emails. In one of your controller actions:


public function actionSend()
{
	Yii::$app->mailqueue->process();
}

Most preferably this could be a console command (eg: mail/send) which can be triggered by a CRON job.

Setting the CRON job

Set a CRON job to run console command:


*/10 * * * * php /var/www/html/myapp/yii mailqueue/process

Usage

You can then send an email to the queue as follows:

Yii::$app->mailqueue->compose('contact/html')
     ->setFrom('from@domain.com')
     ->setTo($form->email)
     ->setSubject($form->subject)
     ->setTextBody($form->body)
     ->queue();

While nterms\mailqueue\MailQueue extends from yii\swiftmailer\Mailer, you can replace it with this extension by adding yii2-swiftmailer configuations directly to mailqueue configurations as follows:

return [
    //....
    'components' => [
        'mailqueue' => [
            'class' => 'nterms\mailqueue\MailQueue',
			'table' => '{{%mail_queue}}',
			'mailsPerRound' => 10,
			'maxAttempts' => 3,
			'transport' => [
				'class' => 'Swift_SmtpTransport',
				'host' => 'localhost',
				'username' => 'username',
				'password' => 'password',
				'port' => '587',
				'encryption' => 'tls',
			],
        ],
    ],
];

And use following code for directly sending emails as you ususally do with yii2-swiftmailer:

Yii::$app->mailqueue->compose('contact/html')
     ->setFrom('from@domain.com')
     ->setTo($form->email)
     ->setSubject($form->subject)
     ->setTextBody($form->body)
     ->send();

License

MIT

]]>
0
[extension] jinxing/yii2-admin Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/extension/jinxing/yii2-admin https://www.yiiframework.com/extension/jinxing/yii2-admin myloveGy myloveGy

Yii2 Ace Admin 后台扩展模块

  1. 作者博客
  2. 简介
  3. 功能特性
  4. 安装
  5. 在自己模块中使用
  6. 使用文档
  7. 后台预览

ProgressLatest Stable Version Total Downloads Latest Unstable Version GitHub issues GitHub forks GitHub stars GitHub license

change to English

作者博客

作者博客

简介

使用的 ace admin 前端框架, 为yii2开发的一个后台模块; 对于二次开发比较方便,包含了基本的后台功能

说明文档

功能特性

  • 包含基本的后台功能

    • 管理员管理: 登录、登出、修改密码等
    • 菜单管理: 可视化动态菜单、根据权限显示菜单
    • 权限管理: 角色、权限、用户的管理
  • 使用yii2自带的RBAC权限管理
  • 对于二次开发比较方便
    • 定义基本控制器(封装了基本的CURD操作), 后续开发基于基础控制器继承修改
    • 拥有代码生成功能(类似于gii), 可视化生成代码模板, 简单操作即可生成 控制器controller、模型model, 视图views 文件,提高开发效率

安装

安装要求
  • PHP >= 5.4
  • MySQL
全新项目安装

全新项目安装可以直接使用liujx/yii2-app-advanced

在已有项目中安装

使用 composer 下载包文件

composer require jinxing/yii2-admin
配置模块信息

在你的 main.php 配置文件中添加下面配置

return [
    'modules' => [
        'admin' => [
            'class' => 'jinxing\admin\Module',
        ]
    ],
    'components' => [
        
        // 后台登录用户组件信息
        'admin' => [
            'class'           => 'yii\web\User',
            'identityClass'   => 'jinxing\admin\models\Admin',
            'enableAutoLogin' => true,
            'loginUrl'        => ['/admin/admin/default/login'],
            'idParam'         => '_adminId',
            'identityCookie'  => ['name' => '_admin', 'httpOnly' => true],
        ],
        
        // 后台使用的语言配置信息
        'i18n' => [
            'translations' => [
                'admin' => [
                    'class'          => 'yii\i18n\PhpMessageSource',
                    'sourceLanguage' => 'en',
                    'basePath'       => '@jinxing/admin/messages'
                ],
            ],
        ],
        
        // 配置权限使用数据库
        'authManager'  => [
            'class' => 'yii\rbac\DbManager',
        ],
                
    ]
];

在你的 params.php 配置文件添加如下配置信息

return [
    // 这个配置是为了导入权限信息需要配置的,就是配置后台模块的路径 
    'admin_rule_prefix' => 'admin',                        

    // 登录成功首页是否需要显示其他信息
    'projectOpenOther' => true,
    
    // 项目信息
    'projectName'      => 'Yii2 后台管理系统',              
    'projectTitle'     => 'Yii2 后台管理系统',
    'companyName'      => '<span class="blue bolder"> Liujinxing </span> Yii2 Admin 项目 &copy; 2016-2018',  
];
[高级版本配置参考](https://mylovegy.github.io/yii2-admin/docs/module.md#yii2高级版后台配置模板, '高级版本配置参考')
[基础版本配置参考](https://mylovegy.github.io/yii2-admin/docs/module.md#yii2基础版后台配置模板, '基础版本配置参考')
使用数据库迁移、导入后台所需的数据库信息、需要顺序执行下面命令
需要配置 console

console 配置中的 components 组件中加入权限配置信息

return [
    'components' => [
        // 权限配置
        'authManager'  => [
            'class' => 'yii\rbac\DbManager',
        ],
    ],
];
  • 高级版本的配置文件在 console/config/main.php
  • 基础版本的配置文件在 config/console.php
导入权限表信息
php yii migrate --migrationPath=@yii/rbac/migrations
导入后台表信息和默认权限、菜单信息
php yii migrate --migrationPath=@jinxing/admin/migrations
你可以愉快的使用了

访问地址

// 登录地址、域名需要根据你的域名修改
http://localhost/path/to?index.php?r=admin/default/login
默认的账号和密码
  1. 超级管理员

    • username: super
    • password: admin123
  2. 普通管理员

    • username: admin
    • password: admin888

在自己模块中使用

Yii2 高级版本中使用

定义一个基础控制,其他控制器都继承基础控制器

  1. 控制器继承jinxing\admin\controllers\Controller
    • 定义控制器使用的布局文件为 @jinxing/admin/views/layouts/main
    • 定义上传文件表单类使用自己的 ,例如:backend\models\forms\UploadForm
  2. 如果要记录操作日志和权限验证,定义行为

    • 记录日志行为类: jinxing\admin\behaviors\Logging

      默认只会记录: create, update, delete, delete-all, editable, upload 操作的日志, 需要添加或者修改,定义needLogActions 属性

    • 权限验证行为类: yii\filters\AccessControl 类的属性和配置参考

例子: `php namespace backend\controllers;

use jinxing\admin\behaviors\Logging; use jinxing\admin\controllers\Controller as BaseController; use yii\filters\AccessControl;

/**

  • Class Controller 后台的基础控制器
  • @package backend\controllers */ class Controller extends BaseController { /**

    • @var string 使用 yii2-admin 的布局 */ public $layout = '@jinxing/admin/views/layouts/main';

    /**

    • @var string 使用自己定义的上传文件处理表单 */ public $uploadFromClass = 'backend\models\forms\UploadForm';

    /**

    • 定义使用的行为 *
    • @return array */ public function behaviors() { return [

       'access' => [
           'class' => AccessControl::className(),
           'rules' => [
               [
                   'allow'       => true,
                   'permissions' => [$this->action->getUniqueId()],
               ],
           ],
       ],
              
       'logging' => [
           'class' => Logging::className(),
       ],
      

      ]; } } `

Yii2 基础版本中使用

yii2 基础版本需要为后台定义一个模块,这个模块可以直接继承jinxing\admin\Module

例子: `php namespace app\modules\admin;

use Yii; use jinxing\admin\Module;

/**

  • admin module definition class */ class Admin extends Module { /**

    • {@inheritdoc} */ public $controllerNamespace = 'app\modules\admin\controllers';

    /**

    • {@inheritdoc} */ public function init() { parent::init(); Yii::$app->errorHandler->errorAction = $this->getUniqueId() . '/admin/default/error'; } }
      
      

>如果不使用模块继承方式,配置参考高级版本

使用文档

文档说明
模块配置说明
控制器配置说明
前端MeTables配置说明

后台预览

  1. 登录页面 登录页
  2. 数据显示 数据显示
  3. 数据编辑 数据显示
  4. 权限分配 权限分配
  5. 代码生成 代码生成
]]>
0
[news] Yii 2.0.22 Tue, 02 Jul 2019 20:55:42 +0000 https://www.yiiframework.com/news/236/yii-2-0-22 https://www.yiiframework.com/news/236/yii-2-0-22 samdark samdark

We are very pleased to announce the release of Yii Framework version 2.0.22. Please refer to the instructions at https://www.yiiframework.com/download/ to install or upgrade to this version.

Version 2.0.22 is a minor release of Yii 2.0. In this release community members fixed 6 bugs. Additionally, two very minor enhancements were made.

  • \yii\validators\DateValidator got $strictDateFormat property that enables stricter validation mode.
  • Debug log message for \yii\base\Action now includes controller name.

Thanks to all Yii community members who contribute to the framework, translators who keep documentation translations up to date and community members who answer questions at forums.

Special thanks to Alexander Kartavenko who contributed majority of release fixes.

There are many active Yii communities so if you need help or want to share your experience, feel free to join them.

A complete list of changes can be found in the CHANGELOG.

]]>
0
[news] Sphinx extension 2.0.12 released Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/235/sphinx-extension-2-0-12-released https://www.yiiframework.com/news/235/sphinx-extension-2-0-12-released samdark samdark

We are very pleased to announce the release of Sphinx extension version 2.0.12. This release fix compatibiltiy with Yii 2.0.21.

See the CHANGELOG for details.

]]>
0
[news] Auth Client extension 2.2.4 released Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/234/auth-client-extension-2-2-4-released https://www.yiiframework.com/news/234/auth-client-extension-2-2-4-released samdark samdark

We are very pleased to announce the release of Auth Client extension version 2.2.4.

In this release there is one important fix about return URLs of OAuth services. Now, by default, only parameters specified via parametersToKeepInReturnUrl are kept while extra ones are removed. That should fix Google client that changed behavior recently.

See the CHANGELOG for details.

]]>
0
[news] Bootstrap 4 extension version 2.0.5 released Tue, 02 Jul 2019 10:28:00 +0000 https://www.yiiframework.com/news/233/bootstrap-4-extension-version-2-0-5-released https://www.yiiframework.com/news/233/bootstrap-4-extension-version-2-0-5-released samdark samdark

Bootstrap 4 extension version 2.0.5 was released. In this release ActiveField got two options, radioTemplate and radioHorizontalTemplate. Previously radio buttons were sharing templates with checkbox templates. Another changes is that both radios and checkboxes are custom-styled by default.

See CHANGELOG for details.

]]>
0
[news] Yii 2.0.21 Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/232/yii-2-0-21 https://www.yiiframework.com/news/232/yii-2-0-21 samdark samdark

We are very pleased to announce the release of Yii Framework version 2.0.21. Please refer to the instructions at https://www.yiiframework.com/download/ to install or upgrade to this version.

Version 2.0.21 is a minor release of Yii 2.0 which fixes some bugs, improves database connection performance and adding support for sameSite cookie option for regular and session cookies.

Info: yii\db\Query::select() and addSelect() now normalize the columns when saving them to $this->select, so code that works directly with that property directly may need to be modified.

Thanks to all Yii community members who contribute to the framework, translators who keep documentation translations up to date and community members who answer questions at forums.

There are many active Yii communities so if you need help or want to share your experience, feel free to join them.

A complete list of changes can be found in the CHANGELOG.

]]>
0
[news] Bootstrap 4 extension version 2.0.4 released Tue, 11 Jun 2019 13:28:56 +0000 https://www.yiiframework.com/news/231/bootstrap-4-extension-version-2-0-4-released https://www.yiiframework.com/news/231/bootstrap-4-extension-version-2-0-4-released samdark samdark

Bootstrap 4 extension version 2.0.4 was released. In this release two bugs were fixed.

See CHANGELOG for details.

Note: activateContainer option for Nav introduced in 2.0.3 became obsolete and it has therefore been deleted. Please make sure you are not using it. If you are, remove it from your code.

]]>
0
[news] Debug extension 2.1.5 released Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/228/debug-extension-2-1-5-released https://www.yiiframework.com/news/228/debug-extension-2-1-5-released samdark samdark

Debug extension version 2.1.5 was released.

It is now dispatching JavaScript event when toolbar is added to DOM. Additionally, a class that allows clicks in toolbar block was added.

See the CHANGELOG for details.

]]>
0
[news] Auth Client extension 2.2.3 released Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/227/auth-client-extension-2-2-3-released https://www.yiiframework.com/news/227/auth-client-extension-2-2-3-released samdark samdark

We are very pleased to announce the release of Auth Client extension version 2.2.3 making OpenIdConnect::validateClaims() for better extensibility.

See the CHANGELOG for details.

]]>
0
[news] Bootstrap 4 extension version 2.0.3 released Tue, 11 Jun 2019 12:23:01 +0000 https://www.yiiframework.com/news/226/bootstrap-4-extension-version-2-0-3-released https://www.yiiframework.com/news/226/bootstrap-4-extension-version-2-0-3-released samdark samdark

Bootstrap 4 extension version 2.0.3 was released. In this release four bugs were fixed. Additionally:

  • Modal::SIZE_EXTRA_LARGE constant was added
  • "disabled" option was added to Nav, Dropdown and Tabs

See CHANGELOG for details.

Thanks to Thoulah and simialbi for taking care of the extension.

]]>
0
[news] Imagine extension version 2.2.0 released Fri, 23 Aug 2019 17:37:04 +0000 https://www.yiiframework.com/news/225/imagine-extension-version-2-2-0-released https://www.yiiframework.com/news/225/imagine-extension-version-2-2-0-released samdark samdark

Imagine extension version 2.2.0 was released. The only change in the extension itself is about underlying version of Imagine package used. Now latest version will be installed by default.

See CHANGELOG for details.

]]>
0
[wiki] Nested Set with Yii2 Mon, 01 Apr 2019 07:50:53 +0000 https://www.yiiframework.com/wiki/2549/nested-set-with-yii2 https://www.yiiframework.com/wiki/2549/nested-set-with-yii2 sangprabo sangprabo

The nested set behaviour is an approach to store hierarchical data in relational databases. For example, if we have many categories for our product or items. One category can be a "parent" for other categories, means that one category consists of more than one category. The model can be drawn using a "tree" model. There are other approaches available but what we will learn in this article is specifically the NestedSetsBehavior made by Alexander Kochetov, which utilizing the Modified Preorder Tree Traversal algorithm.

Requirements :

  • Yii2 framework advanced template
  • Yii2 nested sets package

Install the package using composer

It is always recommended to use Composer to install any kind of package or extension for our Yii2-powered project.

$ composer require creocoder/yii2-nested-sets

Create the table

In this article, we will use Category for our model/table name. So we would like to generate the table using our beloved migration tool.

$ ./yii migrate/create create_category_table

We need to modify the table so it contains our desired fields. We also generate three additional fields named position, created_at, and updated_at.

<?php

use yii\db\Migration;

/**
 * Handles the creation for table `category`.
 */
class m160611_114633_create_category extends Migration
{
    /**
     * @inheritdoc
     */
    public function up()
    {
        $this->createTable('category', [
            'id'         => $this->primaryKey(),
            'name'       => $this->string()->notNull(),
            'tree'       => $this->integer()->notNull(),
            'lft'        => $this->integer()->notNull(),
            'rgt'        => $this->integer()->notNull(),
            'depth'      => $this->integer()->notNull(),
            'position'   => $this->integer()->notNull()->defaultValue(0),
            'created_at' => $this->integer()->notNull(),
            'updated_at' => $this->integer()->notNull(),
        ]);
    }

    /**
     * @inheritdoc
     */
    public function down()
    {
        $this->dropTable('category');
    }
}

Then, generate the table using the migration tool.

$ ./yii migrate

If everything is okay, then you could see that a new table named category already exists.

Generate the default CRUD using Gii

To initiate a model, we need to use Gii tool from Yii2. Call the tool from your localhost:8080/gii/model, and fill in the Table Name field with our existing table: category. Fill other fields with appropriate values, and don't forget to give a check to "Generate ActiveQuery" checklist item. This will generate another file that needs to be modified later.

Continue to generate the CRUD for our model with CRUD Generator Tool. Fill in each field with our existing model. After all files are generated, you can see that we already have models, controllers, and views but our work is far from done because we need to modify each file.

Modify models, controllers, and views

The first file we should modify is the model file: Category.

<?php

namespace common\models;

use Yii;
use creocoder\nestedsets\NestedSetsBehavior;

/**
 * This is the model class for table "category".
 *
 * @property integer $id
 * @property string $name
 * @property integer $tree
 * @property integer $lft
 * @property integer $rgt
 * @property integer $depth
 * @property integer $position
 * @property integer $created_at
 * @property integer $updated_at
 */
class Category extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'category';
    }

    public function behaviors() {
        return [
            \yii\behaviors\TimeStampBehavior::className(),
            'tree' => [
                'class' => NestedSetsBehavior::className(),
                'treeAttribute' => 'tree',
                // 'leftAttribute' => 'lft',
                // 'rightAttribute' => 'rgt',
                // 'depthAttribute' => 'depth',
            ],
        ];
    }

    public function transactions()
    {
        return [
            self::SCENARIO_DEFAULT => self::OP_ALL,
        ];
    }

    public static function find()
    {
        return new CategoryQuery(get_called_class());
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['name'], 'required'],
            [['position'], 'default', 'value' => 0],
            [['tree', 'lft', 'rgt', 'depth', 'position', 'created_at', 'updated_at'], 'integer'],
            [['name'], 'string', 'max' => 255],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id'         => Yii::t('app', 'ID'),
            'name'       => Yii::t('app', 'Name'),
            'tree'       => Yii::t('app', 'Tree'),
            'lft'        => Yii::t('app', 'Lft'),
            'rgt'        => Yii::t('app', 'Rgt'),
            'depth'      => Yii::t('app', 'Depth'),
            'position'   => Yii::t('app', 'Position'),
            'created_at' => Yii::t('app', 'Created At'),
            'updated_at' => Yii::t('app', 'Updated At'),
        ];
    }

    /**
     * Get parent's ID
     * @return \yii\db\ActiveQuery 
     */
    public function getParentId()
    {
        $parent = $this->parent;
        return $parent ? $parent->id : null;
    }

    /**
     * Get parent's node
     * @return \yii\db\ActiveQuery 
     */
    public function getParent()
    {
        return $this->parents(1)->one();
    }

    /**
     * Get a full tree as a list, except the node and its children
     * @param  integer $node_id node's ID
     * @return array array of node
     */
    public static function getTree($node_id = 0)
    {
        // don't include children and the node
        $children = [];

        if ( ! empty($node_id))
            $children = array_merge(
                self::findOne($node_id)->children()->column(),
                [$node_id]
                );

        $rows = self::find()->
            select('id, name, depth')->
            where(['NOT IN', 'id', $children])->
            orderBy('tree, lft, position')->
            all();

        $return = [];
        foreach ($rows as $row)
            $return[$row->id] = str_repeat('-', $row->depth) . ' ' . $row->name;

        return $return;
    }
}

As you can see, we import the extension using the keyword use:

use creocoder\nestedsets\NestedSetsBehavior;

and I also add the TimeStampBehavior for our additional fields, created_at and updated_at

\yii\behaviors\TimeStampBehavior::className(),

Next : Our modification to CategoryController file is at update, create, and delete function.

<?php

namespace backend\controllers;

use Yii;
use common\models\Category;
use common\models\CategorySearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

/**
 * CategoryController implements the CRUD actions for Category model.
 */
class CategoryController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['POST'],
                ],
            ],
        ];
    }

    /**
     * Lists all Category models.
     * @return mixed
     */
    public function actionIndex()
    {
        $searchModel = new CategorySearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * Displays a single Category model.
     * @param integer $id
     * @return mixed
     */
    public function actionView($id)
    {
        return $this->render('view', [
            'model' => $this->findModel($id),
        ]);
    }

    /**
     * Creates a new Category model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new Category();

        if ( ! empty(Yii::$app->request->post('Category'))) 
        {
            $post            = Yii::$app->request->post('Category');
            $model->name     = $post['name'];
            $model->position = $post['position'];
            $parent_id       = $post['parentId'];

            if (empty($parent_id))
                $model->makeRoot();
            else
            {
                $parent = Category::findOne($parent_id);
                $model->appendTo($parent);
            }

            return $this->redirect(['view', 'id' => $model->id]);
        }

        return $this->render('create', [
                'model' => $model,
            ]);
    }

    /**
     * Updates an existing Category model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @return mixed
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ( ! empty(Yii::$app->request->post('Category'))) 
        {
            $post            = Yii::$app->request->post('Category');

            $model->name     = $post['name'];
            $model->position = $post['position'];
            $parent_id       = $post['parentId'];

            if ($model->save())            
            {
                if (empty($parent_id))
                {
                    if ( ! $model->isRoot())
                        $model->makeRoot();
                }
                else // move node to other root 
                {
                    if ($model->id != $parent_id)
                    {
                        $parent = Category::findOne($parent_id);
                        $model->appendTo($parent);
                    }
                }

                return $this->redirect(['view', 'id' => $model->id]);
            }
        }

        return $this->render('update', [
            'model' => $model,
        ]);
    }

    /**
     * Deletes an existing Category model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param integer $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        $model = $this->findModel($id);

        if ($model->isRoot())
            $model->deleteWithChildren();
        else 
            $model->delete();

        return $this->redirect(['index']);
    }

    /**
     * Finds the Category model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param integer $id
     * @return Category the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = Category::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

As for our views files, we need to remove unnecessary fields from our form, such as the lft, rgt, etc, and add the sophisticated parent field to be a dropdown list. This requires a lot of effort, as you can see on the getTree function on our model.

<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;

use common\models\Category;

/* @var $this yii\web\View */
/* @var $model common\models\Category */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="category-form">

    <?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>

    <div class='form-group field-attribute-parentId'>
    <?= Html::label('Parent', 'parent', ['class' => 'control-label']);?>
    <?= Html::dropdownList(
        'Category[parentId]',
        $model->parentId,
        Category::getTree($model->id),
        ['prompt' => 'No Parent (saved as root)', 'class' => 'form-control']
    );?>

    </div>

    <?= $form->field($model, 'position')->textInput(['type' => 'number']) ?>

    <div class="form-group">
        <?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
    </div>

    <?php ActiveForm::end(); ?>

</div>

Complete files can be found at my GitHub page: https://github.com/prabowomurti/learn-nested-set

The screencast (subtitled English) here : https://www.youtube.com/watch?v=MjJEjF1arHs

]]>
0
[wiki] Events registration examples Mon, 11 Mar 2019 14:04:14 +0000 https://www.yiiframework.com/wiki/2548/events-registration-examples https://www.yiiframework.com/wiki/2548/events-registration-examples minitia82 minitia82

Register an event handler at Object-Level

e.g inside the init method of a Model

// this should be inside your model class. For example User.php
public function init(){
  $this->on(self::EVENT_NEW_USER, [$this, 'sendMail']);
  $this->on(self::EVENT_NEW_USER, [$this, 'notification']);
  // first parameter is the name of the event and second is the handler. 
  // For handlers I use methods sendMail and notification
  // from $this class.
  parent::init(); // DON'T Forget to call the parent method.
}

from https://stackoverflow.com/questions/28575636/how-to-use-events-in-yii2

Register an event handler at Class-Level

To register event handlers at Class-Level a good place can be inside the bootstrap process.

So, you can put the registration code as

Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
    Yii::debug(get_class($event->sender) . ' is inserted');
});

in a php file like the bootstrap.php used in Advanced-Template or through configuration, with your custom component for example

see docs

(https://www.yiiframework.com/doc/guide/2.0/en/structure-applications#bootstrap or https://www.yiiframework.com/doc/guide/2.0/en/structure-extensions#bootstrapping-classes)

]]>
0
[wiki] (draft) Understanding Yii 3 Sun, 30 Dec 2018 21:44:55 +0000 https://www.yiiframework.com/wiki/2547/draft-understanding-yii-3 https://www.yiiframework.com/wiki/2547/draft-understanding-yii-3 machour machour

Understanding Yii 3

  1. Introduction
  2. Changes overview
  3. Yii 3 composer packages
  4. Running your first Yii 3 powered application

Since this Wiki page is getting bigger and bigger, I decided to document things in a Yii 3 project instead.

Project source can be found at https://github.com/machour/yii3-kitchen-sink Live web site: https://yii3.idk.tn/

Follow the repo/website to get fresher informations, or better yet, pull the project and run it by yourself to get acquainted with Yii3

Introduction

This document is intended for an audience already familiar with Yii2. It's meant to bring together all information related to Yii 3 in one place to make it easier to get on track.

Yii 3 is the second major rewrite of the Yii framework.

Originally started in the 2.1 branch, it was later decided to switch to the 3.X series because of all the backward compatibility breakage. Starting with 3.0, Yii will follow the Sementic Versionning.

This rewrite addresses a lot of issues Yii 2 suffered from, like the framework being too coupled with jQuery, bower, bootstrap. [TODO: add more grieffs about Yii2]

Changes overview

Here are the main changes in Yii 3. You can check the complete CHANGELOG for an exhaustive list.

Source code splitting

The framework source code have been split into several packages, and at its core level, Yii no longer makes assumptions about your development stack, or the features you will be using.

This enable you to cherry pick the packages you need to compose your application.

This re-organisation is also a great news for maintainance, as these packages will be released separately, thus allowing more frequent updates.

Autoloading

The custom PHP class autoloader have been removed in favor of Composer's PSR-4 implementation. This means that in order for Yii to see your classes, you will have to explicitly register your namespace in composer.json. We will see an example later.

PSR compatibility

Yii 3 takes some positive steps following the PHP-FIG recommendations, by implementing the following PSRs:

  • Logging is now compliant with PSR-3
  • Caching is now compliant with PSR-16
  • Dependency Injection is now compliant with PSR-11
Application configuration

If you've ever installed an extension using Yii 2, you may/certainly have found yourself on the extension README file, looking for the chunk of configuration to copy/paste in your own config/main.php file.

This can often lead to:

  • a huge configuration file (which you may have decided to split into smaller files)
  • non-trivials configurations update when a new version of the extension is realeased with new/changed configurations options.

Yii 3 takes another approach. Every package bundle its own configuration, and will probably work out of the box. And you may override them, if you need to, from your configuration file.

This is all done by leveraging the hiqdev/composer-config-plugin composer plugin, which takes care of scanning & merging all the configurations when you run composer dump-autoload (also know as composer du).

You can read Yii2 projects alternative organization for an in-depth explanation of the motivation behind hiqdev/composer-config-plugin.

Packages authors will have the responsibility to avoid introducing BC breaks, by adopting a strict sementical versionning.

Dependencies injection

[TODO]

Yii 3 composer packages

Here are the new packages introduced in Yii 3, which can be found in this official list.

Let's introduce them briefly:

The Framework

This is the new kernel of Yii. It defines the base framework and its core features like behaviors, i18n, mail, validation..

You will rarely want to directly install yiisoft/yii-core. Instead, you will install one or more of the following:

This three packages, considered as Extensions, are responsible for implementing the basic functionnalities of each "channel" they refer to:

  • yii-console implements all that you need to build a console application (the base Controller for commands, the Command helper, ..)
  • yii-web implements all that you need to build a web application (Assets management, Sessions, Request handling ..)
  • yii-rest implements all that you need to build a REST interface (ActiveController, ..)
Librairies

In Yii 3, libraries do not depend on Yii and are meant to be usable outside the framework. Their package name is yiisoft/something without yii-prefix.

Drivers for yiisoft/db

The various drivers for DB have also been separated into packages:

Extensions

Extensions depends (at least) on yii-core. Aside from the 3 extensions already encountered above (yii-console, yii-web, yii-api), these packages are available

Development
View rendering engines
Data rendering
JS & CSS Frameworks integration
Widgets
Misc
Yii project template and application bases

This is a very basic Yii project template, that you can use to start your development.

You will probably want to pick one or more of these three starters to install in your project next:

Let's try running the web base template in the next section.

Running your first Yii 3 powered application

Let's try running a web application using Yii 3, and the provided project template.

Installing the project template
composer create-project --prefer-dist --stability=dev yiisoft/yii-project-template myapp
cd myapp

Here's the created structure:

.
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── config
│   ├── common.php
│   └── params.php
├── docker-compose.yml
├── hidev.yml
├── public
│   ├── assets
│   ├── favicon.ico
│   ├── index.php
│   └── robots.txt
├── runtime
└── vendor

You won't be able to start the web server right away using ./vendor/bin/yii serve, as it will complain about not knowing the "app" class.

In fact, this project template only introduce the bare minimum in your application: Caching, Dependencies injection, and Logging. The template doesn't make an assumption about the kind of application you're building (web, cli, api).

You could start from scratch using this bare template, select the extensions & packages you want to use and start developing, or you can pick one of the three starters provided.

Installing the web starter

Since we're doing a web application, we will need an asset manager. We can pick either one of those:

  • Asset-packagist & composer-merge-plugin (requires only PHP)
  • Foxy (requires npm or yarn)

Let's go with foxy (personal taste since composer is so slow from Tunisia):

composer require "foxy/foxy:^1.0.0"

We can now install the yii-base-web starter and run our application:

composer require yiisoft/yii-base-web
vendor/bin/yii serve

By visiting http://localhost:8080/, you should now see something like this:

50153967-44a6af00-02c8-11e9-9914-ceb463065cdf.png

Checking back our project structure, nothing really changed, aside from the creation of these three entries:

  • node_modules/
  • package-lock.json
  • package.json

So where do what we see in the browser comes from ?

Exploring yiisoft/yii-base-web structure:

If you explore the folder in vendor/yiisoft/yii-base-web, you will see that the template is in fact a project itself, with this structure:

.
├── LICENSE.md
├── README.md
├── composer.json
├── config
│   ├── common.php
│   ├── console.php
│   ├── env.php
│   ├── messages.php
│   ├── params.php
│   └── web.php
├── phpunit.xml.dist
├── public
│   └── css
│       └── site.css
├── requirements.php
├── runtime
└── src
    ├── assets
    │   └── AppAsset.php
    ├── commands
    │   └── HelloController.php
    ├── controllers
    │   └── SiteController.php
    ├── forms
    │   ├── ContactForm.php
    │   └── LoginForm.php
    ├── mail
    │   └── layouts
    ├── messages
    │   ├── et
    │   ├── pt-BR
    │   ├── ru
    │   └── uk
    ├── models
    │   └── User.php
    ├── views
    │   ├── layouts
    │   └── site
    └── widgets
        └── Alert.php

The folders and files should make sense to you if you already developed applications using Yii2 and the basic template.

]]>
0
[wiki] Batch Gridview data ajax send splitted in chunks displaying bootstrap Progress bar Sat, 24 Nov 2018 10:48:47 +0000 https://www.yiiframework.com/wiki/2546/batch-gridview-data-ajax-send-splitted-in-chunks-displaying-bootstrap-progress-bar https://www.yiiframework.com/wiki/2546/batch-gridview-data-ajax-send-splitted-in-chunks-displaying-bootstrap-progress-bar toaster toaster

The scenario in which this wiki can be useful is when you have to send an (huge) array of model ids and perform a time consuming computation with it like linking every model to other models. The idea is to split the array into smaller arrays and perform sequential ajax requests, showing the calculation progress using a Bootstrap Progress bar.

I have created a Country model and generated the CRUD operations using Gii. The model class look like this:

namespace app\models;
use Yii;
use yii\helpers\ArrayHelper;

/**
 * This is the model class for table "country".
 *
 * @property string $code
 * @property string $name
 * @property int $population
 *
 */
class Country extends \yii\db\ActiveRecord {

    /**
     * {@inheritdoc}
     */
    public static function tableName() {
        return 'country';
    }

    /**
     * {@inheritdoc}
     */
    public function rules() {
        return [
            [['code', 'name'], 'required'],
            [['population'], 'integer'],
            [['code'], 'string', 'max' => 3],
            [['name'], 'string', 'max' => 52],
            [['code'], 'unique'],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels() {
        return [
            'code' => 'Code',
            'name' => 'Name',
            'population' => 'Population',
        ];
    }
    /**
     * 
     * @return array
     */
    public static function getCodes(){
        return array_keys(ArrayHelper::map(Country::find()->select('code')->asArray()->all(), 'code', 'code'));
    }
}

I have also created another model that will take care to validate the ids and perform the time consuming calculation through the process() function. (in this example I just use a sleep(1) that will wait for one second for each element of the $codes array). I also want to keep track of the processed models, incrementing the $processed class attribute.

<?php

namespace app\models;

use app\models\Country;

/**
 * Description of BatchProcessForm
 *
 * @author toaster
 */
class BatchProcessForm extends \yii\base\Model {

    /**
     * The codes to process
     * @var string
     */
    public $codes;

    /**
     * The number of codes processed
     * @var integer
     */
    public $processed = 0;

    /**
     * @return array the validation rules.
     */
    public function rules() {
        return [
            ['codes', 'required'],
            ['codes', 'validateCodes'],
        ];
    }

    /**
     * Check whether codes exists in the database
     * @param type $attribute
     * @param type $params
     * @param type $validator
     */
    public function validateCodes($attribute, $params, $validator) {
        $input_codes = json_decode($this->$attribute);
        if (null == $input_codes || !is_array($input_codes)) {
            $this->addError($attribute, 'Wrong data format');
            return;
        }
        $codes = Country::getCodes();
        if (!array_intersect($input_codes, $codes) == $input_codes) {
            $this->addError($attribute, 'Some codes selected are not recognized');
        }
    }

    /**
     * Process the codes
     * @return boolean true if everything goes well
     */
    public function process() {
        if ($this->validate()) {
            $input_codes = json_decode($this->codes);
            foreach ($input_codes as $code) {
                sleep(1);
                $this->processed++;
            }
            return true;
        }
        return false;
    }

}

The code for the controller action is the following:

/**
 * Process an array of codes
 * @return mixed
 * @throws BadRequestHttpException if the request is not ajax
 */
public function actionProcess(){
    if(Yii::$app->request->isAjax){
        Yii::$app->response->format = Response::FORMAT_JSON;
        $model = new BatchProcessForm();
        if($model->load(Yii::$app->request->post()) && $model->process()){
            return ['result' => true, 'processed' => $model->processed];
        }
        return ['result' => false, 'error' => $model->getFirstError('codes')];
    }
    throw new \yii\web\BadRequestHttpException;
}

In my index.php view I have added a CheckboxColumn as first column of the Gridview that allows, out of the box, to collect the ids of the models selected via Javascript (in this case the values of the code attribute). I have also added a button-like hyperlink tag to submit the collected data (with id batch_process) and a Bootstrap Progress bar inside a Modal Window. The code of my view is the following:

<?php

use yii\helpers\Html;
use yii\grid\GridView;
use yii\bootstrap\Modal;

/* @var $this yii\web\View */
/* @var $searchModel app\models\CountrySearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = 'Countries';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="country-index">

    <h1><?= Html::encode($this->title) ?></h1>
    <?php // echo $this->render('_search', ['model' => $searchModel]); ?>

    <p>
        <?= Html::a('Create Country', ['create'], ['class' => 'btn btn-success']) ?>
        <?= Html::a('Batch Process', ['process'], ['class' => 'btn btn-info', 'id' => 'batch_process']) ?>
    </p>

    <?=
    GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'options' => [
            'id' => 'country-index'
        ],
        'columns' => [
            ['class' => 'yii\grid\CheckboxColumn'],
            'code',
            'name',
            'population',
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]);
    ?>
</div>

<?php Modal::begin(['header' => '<h5 id="progress">0% Complete</h5>', 'id' => 'progress-modal', 'closeButton' => false]); ?>

<?=
yii\bootstrap\Progress::widget([
    'percent' => 0,
     'options' => ['class' => 'progress-success active progress-striped']
]);
?>

<?php Modal::end(); ?>

<?php $this->registerJsFile('@web/js/main.js', ['depends' => [\app\assets\AppAsset::class]]); ?>

The Javascript file that split in chunks the array and send each chunk sequentially is main.js. Although I have registered the Javascript file using registerJsFile() method I highly recommend to better handle and organize js files using Asset Bundles. Here is the code:


function updateProgressBar(percentage) {
    var perc_string = percentage + '% Complete';
    $('.progress-bar').attr('aria-valuenow', percentage);
    $('.progress-bar').css('width', percentage + '%');
    $('#pb-small').text(perc_string);
    $('#progress').text(perc_string);
}

function disposeProgressBar(message) {
    alert(message);
    $('#progress-modal').modal('hide');
}

function showProgressBar() {
    var perc = 0;
    var perc_string = perc + '% Complete';
    $('.progress-bar').attr('aria-valuenow', perc);
    $('.progress-bar').css('width', perc + '%');
    $('#pb-small').text(perc_string);
    $('#progress').text(perc_string);
    $('#progress-modal').modal('show');
}

function batchSend(set, iter, take, processed) {
    var group = iter + take < set.length ? iter + take : set.length;
    var progress = Math.round((group / set.length) * 100);
    var dataObj = [];
    for (var i = iter; i < group; i++) {
        dataObj.push(set[i]);
    }
    iter += take;
    $.ajax({
        url: '/country/process', ///?r=country/process
        type: 'post',
        data: {'BatchProcessForm[codes]': JSON.stringify(dataObj)},
        success: function (data) {
            if (data.result) {
                updateProgressBar(progress);
                processed += data.processed;
                if (progress < 100) {
                    batchSend(set, iter, take, processed);
                } else {
                    var plural = processed == 1 ? 'country' : 'countries';
                    disposeProgressBar(processed + ' ' + plural + ' correctly processed');
                }
                return true;
            }
            disposeProgressBar(data.error);
            return false;
        },
        error: function () {
            disposeProgressBar('Server error, please try again later');
            return false;
        }
    });
}

$('#batch_process').on('click', function (e) {
    e.preventDefault();
    var keys = $('#country-index').yiiGridView('getSelectedRows');
    if (keys.length <= 0) {
        alert('Select at least one country');
        return false;
    }
    var plural = keys.length == 1 ? 'country' : 'countries';
    if (confirm(keys.length + ' ' + plural + ' selected.. continue?')) {
        showProgressBar();
        batchSend(keys, 0, 5, 0);
    }
});

The first three functions take care to show, update and hide the progress bar inside the modal window, while the batchSend function perform the array split and, using recursion, send the data through post ajax request, encoding the array as JSON string and calling itself until there is no more chunks to send. The last lines of code bind the click event of the #batch_process button checking if at least one row of Gridview has been selected. The number of elements on each array chunk can be set as the third argument of the batchSend function (in my case 5), you can adjust it accordingly. The first parameter is the whole array obtained by the yiiGridView('getSelectedRows') function. The final result is something like this:

batch_send1.gif

...looks cool, isn't it?

]]>
0
[wiki] Using multiple models in an identity Tue, 29 Jan 2019 23:11:01 +0000 https://www.yiiframework.com/wiki/2545/using-multiple-models-in-an-identity https://www.yiiframework.com/wiki/2545/using-multiple-models-in-an-identity samdark samdark

Let's assume we have two models: Customer and Supplier and we want both to log in. Yii is quite flexible when it comes to authentication and authorization so it's possible.

First of all, Yii assumes that there's a single type of user component used at once. Still, we're able to create a universal Identity that works with both customers and suppliers.

So we create models/Identity.php:

final class Identity implements IdentityInterface
{
    const TYPE_CUSTOMER = 'customer';
    const TYPE_SUPPLIER = 'supplier';

    const ALLOWED_TYPES = [self::TYPE_CUSTOMER, self::TYPE_SUPPLIER];

    private $_id;
    private $_authkey;
    private $_passwordHash;

    public static function findIdentity($id)
    {
        $parts = explode('-', $id);
        if (\count($parts) !== 2) {
            throw new InvalidCallException('id should be in form of Type-number');
        }
        [$type, $number] = $parts;

        if (!\in_array($type, self::ALLOWED_TYPES, true)) {
            throw new InvalidCallException('Unsupported identity type');
        }

        $model = null;
        switch ($type) {
            case self::TYPE_CUSTOMER:
                $model = Customer::find()->where(['id' => $number])->one();
                break;
            case self::TYPE_SUPPLIER:
                $model = Supplier::find()->where(['id' => $number])->one();
                break;
        }

        if ($model === null) {
            return false;
        }


        $identity = new Identity();
        $identity->_id = $id;
        $identity->_authkey = $model->authkey;
        $identity->_passwordHash = $model->password_hash;
        return $identity;
    }

    public static function findIdentityByAccessToken($token, $type = null)
    {
        $model = Customer::find()->where(['token' => $token])->one();
        if (!$model) {
            $model = Supplier::find()->where(['token' => $token])->one();
        }

        if (!$model) {
            return false;
        }

        if ($model instanceof Customer) {
            $type = self::TYPE_CUSTOMER;
        } else {
            $type = self::TYPE_SUPPLIER;
        }

        $identity = new Identity();
        $identity->_id = $type . '-' . $model->id;
        $identity->_authkey = $model->authkey;
        $identity->_passwordHash = $model->password_hash;
        return $identity;
    }

    public function validatePassword($password)
    {
        return password_verify($password, $this->_passwordHash);
    }

    public static function findIdentityByEmail($email)
    {
        $model = Customer::find()->where(['email' => $email])->one();
        if (!$model) {
            $model = Supplier::find()->where(['email' => $email])->one();
        }

        if (!$model) {
            return false;
        }

        if ($model instanceof Customer) {
            $type = self::TYPE_CUSTOMER;
        } else {
            $type = self::TYPE_SUPPLIER;
        }

        $identity = new Identity();
        $identity->_id = $type . '-' . $model->id;
        $identity->_authkey = $model->authkey;
        $identity->_passwordHash = $model->password_hash;
        return $identity;
    }

    public function getId()
    {
        return $this->_id;
    }

    public function getAuthKey()
    {
        return $this->_authkey;
    }

    public function validateAuthKey($authKey)
    {
        return $this->getAuthKey() === $authKey;
    }
}

In the above we assume that our ids are like customer-23 or supplier-34. When we need to get identity instance we split the id by - and getting both type and integer id for the model corresponding to that type.

Having identity we can tell Yii to use it via config/main.php:

[
    // ...
    'components' => [
        // ...
        'user' => [
            'identityClass' => 'app\models\Identity',
            'enableAutoLogin' => true,
        ],
    ],
],

The only thing left is to adjust models\LoginForm.php:

class LoginForm extends Model
{
    // ...
    
    public function getUser()
    {
        if ($this->_user === false) {
            $this->_user = Identity::findIdentityByEmail($this->username);
        }

        return $this->_user;
    }
}

That's it. Now you can log in using both models.

]]>
0
[wiki] Update and Delete buttons on Breadcrumb Fri, 23 Aug 2019 17:37:05 +0000 https://www.yiiframework.com/wiki/2544/update-and-delete-buttons-on-breadcrumb https://www.yiiframework.com/wiki/2544/update-and-delete-buttons-on-breadcrumb adinugro adinugro

The definition of breadcrumbs according to its documentation is as follow: Breadcrumbs displays a list of links indicating the position of the current page in the whole site hierarchy.

We can define the breadcrumbs easily by adding these lines.

$this->title = $model->formNo;
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Supplier receiving'), 'url' => ['index', 'type' => $model->type]];
$this->params['breadcrumbs'][] = ['label' => $this->title, 'url' => ['view', 'id' => $model->id]];

Reading the documentation, I encountered the template keyword. I was excited about the possibility to add buttons into breadcrumbs. Add these lines and you would have buttons on the right side of the breadcrumb.

$this->title = $model->formNo;
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Supplier receiving'), 'url' => ['index', 'type' => $model->type]];
$this->params['breadcrumbs'][] = ['label' => $this->title, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Delete'), 'template' =>
    Html::tag('span', Html::a(Html::icon('glyphicon glyphicon-trash white') . ' ' . Yii::t('app', 'Delete'), Url::to(['delete', 'id' => $model->id]), [
                'class' => 'btn btn-xs btn-danger',
                'title' => Yii::t('app', 'Delete'),
                'data-pjax' => '0',
                'data-method' => 'POST',
                'data-confirm' => Yii::t('app', 'Are you sure you want to delete this supplier receiving?'),
                    ]
            ), ['class' => 'pull-right'])];
$this->params['breadcrumbs'][] = ['label' => Yii::t('app', 'Update'), 'template' => Html::tag('span', Html::a(
                    Html::icon('glyphicon glyphicon-pencil') . ' ' . Yii::t('app', 'Update'), Url::to(['update', 'id' => $model->id, 'inview' => 1]), [
                'class' => 'btn btn-xs btn-warning',
                'title' => Yii::t('app', 'Update'),
                'role' => 'modal-remote',
                'data-toggle' => 'tooltip',
                    ]
            ), ['class' => 'pull-right', 'style' => 'margin-right: 5px;'])];

Actually you can use this line to define the template, but $links means the full link. A suggestion to the developer is to make the $url and $label variables to be available like $links, so that we can make the template more flexible and meaningful than above codes.

FYI,

  1. I use ajaxcrud extension, so that the update link has 'role' => 'modal-remote' to allow the update process taken place on the modal window. I added a inview parameter to distinguish the update from index or view. Both actions will be called using ajax request and will show the form on the modal, but the index update will redirect to index and refresh gridview while in the view, it should redirect to the view.
  2. On the template, I used span over li to make ' / ' character not appear on the links buttons.

A simple tip to make the view layout efficient.

]]>
0
[wiki] When to use Active Record Fri, 23 Aug 2019 17:37:05 +0000 https://www.yiiframework.com/wiki/2541/when-to-use-active-record https://www.yiiframework.com/wiki/2541/when-to-use-active-record samdark samdark

When to use Active Record is a common question among developers, Yii and overall.

I have about 500K records in my DB tables and each query there are 2 or 3 joins. I was getting data via AR, about a hundred records a time and noticed that using createCommand consumes less memory and CPU. I think with DAO instead of AR it will be faster.

It is true that Active Record consumes memory for storing objects and CPU cycles for instantiate these objects.

Is AR bad? It it for small projects only? We have lots of inserts, about 5000 records an hour and we're using AR for that. Should we re-write?

AR is a pleasure to use when you're managing not that many records at the same time. CRUD is very easy with it. Yii 2 dirty attribute support (only what was modified is saved) off-loads database and mitigates many parallel editing conflicts. If you don't have complex logic in your app and you don't need entity abstractions, AR is an ideal choice.

AR is OK for queries not too complicated when they return no more than a hundred objects. Yes, it is faster and less memory consuming to use query builder or asArray() but working with arrays is significantly less convenient.

For complex queries, such as aggregates or reports, AR isn't recommended. These are easier to express with query builder or SQL. Same goes for import and export routines.

]]>
0
[wiki] Getting information from the current locale Thu, 09 Aug 2018 18:56:33 +0000 https://www.yiiframework.com/wiki/2540/getting-information-from-the-current-locale https://www.yiiframework.com/wiki/2540/getting-information-from-the-current-locale CeBe CeBe

Yii 2.0 comes with a formatter component to format dates, numbers, and other values for international users according to their locale. This is very useful for displaying data. When working with incoming data or when using enhanced input methods like the MaskedInput widget you sometimes need to access the symbols used by the formatter to generate a pattern or parse the input.

The Yii formatter does not have methods to access this data, it relies on the PHP intl extension for formatting. If you want to access the formatting symbols you need to work with intl directly.

Getting decimal and thousand separator

$locale = 'de_DE';

$formatter = new \NumberFormatter($locale,\NumberFormatter::DECIMAL);

$decimalSeparator = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
$thousandSeparator = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL);

There are more symbols than shown above, for the full list of symbols see the list of NumberFormatter constants in the php manual.

Getting a currency symbol

Getting the currency symbol is a bit more complicated if you do not want the symbol of the default currency of a locale, but another currency:

$locale = 'de_DE'; // get the currency symbol of Germanys default currency EUR = "€"
$locale = 'de_DE@currency=USD'; // get the currency symbol of USD in German locale = "$"

$formatter = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);

$currencySymbol = $formatter->getSymbol(\NumberFormatter::CURRENCY_SYMBOL);

Note, that the NumberFormatter is instantiated with the CURRENCY constant instead of DECIMAL here.

Since Yii 2.0.14 Yii has this method built-in in the Locale class.

]]>
0
[wiki] What SQL-Statement creates yii? Fri, 27 Jul 2018 11:28:13 +0000 https://www.yiiframework.com/wiki/2539/what-sql-statement-creates-yii https://www.yiiframework.com/wiki/2539/what-sql-statement-creates-yii Necip Necip

The usual way to find out what Yii has created for an SQL query is to mutilate the SQL in the sourcecode and call the program again so that the SQL statement with errors is displayed. Or you can use the SQL logger, which must be switched on and off each time and logs all SQL statements, which leads to an enormous slowdown in program execution and decelerates your workflow.

These all is not necessary if you use XDebug and place a breakpoint after the function "getCommandBuilder" in the CActiveRecord.php and take a closer look at the return value in $command.

This database access is created in yii:

yii-sql11.png?w=474

This code is called by the yii framework

yii-sql21.png?w=474

getCommandBuilder returns this data structure with the generated SQL statement:

yii-sql32.png?w=474

Path to CActiveRecord.php

C:\xampp\htdocs\your_project\yii\framework\db\ar\CActiveRecord.php

]]>
0
[wiki] How to organize Design "things" in Yii 2 (themes and layout) Thu, 23 Aug 2018 17:32:30 +0000 https://www.yiiframework.com/wiki/2538/how-to-organize-design-things-in-yii-2-themes-and-layout https://www.yiiframework.com/wiki/2538/how-to-organize-design-things-in-yii-2-themes-and-layout olissongs olissongs
  1. Via "theming"
  2. Using layouts
  3. Both
  4. UseCase one
  5. UseCase two

Sometimes the App needs a nicer look & feel, so its necessary to organize the assets for this and Yii can help a lot to make it easy. In this article I provide tips for handling multiple "Designs". I use these three features:

  • AssetBundle
  • Layouts
  • Themes

What do you need for desingning your website:

  • CSS files
  • JS files
  • some Images or other media.

Lets call it "DesignAssets"

What Yii needs:

  • one or more Layout files
  • the view files
  • AssetBundle set in the layout-file

Lets call it "DesignTemplates".

So how to bundle these and where is the best place to put them in your application directory?

Via "theming"

  • myYiiApp
    • ...
    • designs
      • myDesign1
        • put here all your "DesignTemplates" (AssetBundle,layout, and view folder/files, when using themes)

Using layouts

  • myYiiApp
    • ...
    • views
      • layouts
        • myDesign1.php (layout file)
      • ...

Both

  • myYiiApp

    • ...
    • web

      • designs
        • myDesign1
          • put here all your "DesignAssets" (css, js, img, etc.)
    • ...

So you can work with the default security file-rights for the correct purpose.

UseCase one

Write an App and distribute it to some Customer. Here can it be necessary that every customer wants a personal design.

Solution: Using themes

you config in your web.php or main.php (advanced template) whats documented here

if you need special "DesignAssets"

put your "DesignAssets" und the web directory myYiiApp/web/designs/myDesign1/css and js and img folders

customize your myYiiApp/designs/myDesign1/assets/MyDesignAsset.php

and your layout file myYiiApp/designs/myDesign1/layout/main.php

thats it.

UseCase two

you need several designs for e.g. controllers. so my remmmendation is using layouts, because easy switching in controller action.

Solution with layouts

there is no need to configure anything in the config files

if you need special "DesignAssets"

put your "DesignAssets" und the web directory myYiiApp/web/designs/myDesign1/css and js and img folders

create and customize your myYiiApp/assets/MyDesignAsset.php

and your layout file myYiiApp/views/layout/mydesign1.php

in your controller action set your layout.

public function actionIndex() {
    $this->layout = 'mydesign1';
}

may it helps your start with designing Yii.

]]>
0
[wiki] An alternative way to ElasticSearch Sun, 12 Aug 2018 07:49:50 +0000 https://www.yiiframework.com/wiki/2255/an-alternative-way-to-elasticsearch https://www.yiiframework.com/wiki/2255/an-alternative-way-to-elasticsearch Necip Necip

This article is for those who have dealt with the complexity of Elasticsearch or any other indexing machines and are looking for an easier way to index the existing database without additional effort.

Why this post?

The amount of data increases every day. As a result, the search in the databases becomes longer and longer. Conventional data structures must be realigned in order to be able to access information more quickly. There are already database systems like Elasticsearch that can do this. However, such systems also have disadvantages.

The most noticeable major drawbacks are:

  • Learning a new query language. SQL-Plugin won’t get you far or is not flexible enough.
  • The existing programs must be rewritten in order to process the new result sets appropriately.
  • The safety regulations must be defined again.
  • A second database must be set up, which in principle contains the same data.

Who will benefit from this post?

This information is useful for any programmer who wants to integrate an index database into his existing system in a simple way without additional effort.

The basic idea behind Indexing-machines

We will use this simple Table to demonstrate what an Index-machine does

Tablename: object

UID	TITLE	DESCRIPTION
4711	Rudyard Kipling	If you can keep your head when all about you …
4712	John Magee	I have slipped the surly bonds of Earth and danced the skies on laugher-silvered wings …
4713	Wiliam Wordsworth	Ten thousand saw I at a glance, Tossing their heads in sprightly dance…

With this request we can find very specific texts in this single table:

SELECT ID, Title, Description
FROM object
WHERE Description like '%head%'

But what if we want to find ‚%head%‘ in all tables of our database? We have to write a code to do this job for us. This is inefficent and will work very slowy. The idea behind Elasticsearch and other indexing tables is – so far I understood – to break the strings in single tokens. That means in a very easy way that we have to transform the horicontal order of the table into a vertical order.

Tablename: ncp_index

UID	TABLENAME	FIELDNAME	ID	TOKEN
1001	object	Description	4711	if
1002	object	Description	4711	you
1003	object	Description	4711	can
…				
1010	object	Description	4712	I
1011	object	Description	4712	have
1012	object	Description	4712	slipped
…				

We can tokenize any field of any table of our database into the table ncp_index. Now we can find with a single query very fast any (tokenized) word in our hole database.

SELECT Tablenname, Fieldname, Token
FROM ncp_index
WHERE Token like '%head%'

That is the secret of any Index-Searchengine. Yes, the ncp_index table has a lot of redundant data that we can normalize as follows:

Every field is stored in a system table and has a unique id. let us call it field_id Every content of a field has a lot of same words. These words should be stored only once in a separat words-table.

Our ncp_index table looks now so:

UID	FIELD_ID	ID	TOKEN_ID
1001	123	4711	1
1002	123	4711	2
1003	123	4711	31010	123	4712	4
1011	123	4712	5
1012	123	4712	6
…	
		
Systemtable: fields

UID	TABLENAME	NAME
122	object	Name
123	object	Description
…		

Tablename: word

UID	TOKEN
1	if
2	you
3	can
…	

Some basic examples

/**
 * @author ncp <necips@live.de>
 */
class NCPSearch
{
    /**
     * @param $model
     * @param $tablename
     * @param $fieldnames
     */
    public static function delete_ncp_search_item($model, $tablename) {
        $criteria = new CDbCriteria;
        $criteria->condition = "tablename = :tablename " .
                    "AND id = :id ";
        $criteria->params[":tablename"] = $tablename;
        $criteria->params[":id"] = $model->uid;
        NCPIndexModel::model()->deleteAll($criteria);
    }
    /**
     * @param $model
     * @param $tablename
     * @param $fieldnames
     */
    public static function update_ncp_search_item($model, $tablename, $fieldnames) {
        NCPSearch::delete_ncp_search_item($model, $tablename);
        NCPSearch::insert_ncp_search_item($model, $tablename, $fieldnames);
    }
    /**
     * @param $model
     * @param $tablename
     * @param $fieldnames
     */
    public static function insert_ncp_search_item($model, $tablename, $fieldnames) {
        foreach ($fieldnames as $fieldname) {
            $NCP_index_model = new NCPIndexModel("create");
            $NCP_index_model->tablename = $tablename;
            $NCP_index_model->fieldname = $fieldname;
            $NCP_index_model->id = $model->uid;
            $NCP_index_model->save();
            // a very simple way to tokenize the strings!
            $raw = strip_tags($model->{$fieldname});
            $tokens = explode( ' ', $raw);
            foreach ($tokens as $token) {
                $NCP_token_model = new NCPTokenModel("create");
                $NCP_token_model->NCP_index_uid = $NCP_index_model->uid;
                $NCP_token_model->token = $token;
                $NCP_token_model->save();
            }
        }
    }
    /**
     * @param $models
     * @param $tablename
     * @param $fieldnames
     */
    public static function insert_ncp_search_items($models, $tablename, $fieldnames) {
        foreach ($models as $model) {
            NCPSearch::insert_ncp_search_item($model, $tablename, $fieldnames);
        }
    }
}


// main.php:

// initialize ncp_search table once with all tables which has to be indexed in the main function
NCPSearch::insert_ncp_search_items(UserModel::model()->findAll(), "user", ["login", "mail", "name_last", "name_first"]);
NCPSearch::insert_ncp_search_items(DepartmentModel::model()->findAll(), "department", ["title", "description"]);
NCPSearch::insert_ncp_search_items(ObjectModel::model()->findAll(), "object", ["title", "description"]);
  

// model.php:

class Object : Model
{
  function afterSave()  {
    
    
     // insert this code to synchronize the informations on ncp_index
     if ($this->status === ObjectStatus::DELETED)
            NCPSearch::delete_ncp_search_item($this, "object");
        else
            NCPSearch::update_ncp_search_item($this, "object", ["title", "description"]);       
            
    ...
  }
  
  ...
  
}

Conclusion

These are my basic observations on this subject. These are the first steps to a search-engine that can index existing tables so that informations can be found quickly.

Thanks to

Github

https://github.com/Necip8/ncp_search

Homepage https://ncpup.wordpress.com

I hope this information helps you to build your own super search engine!

]]>
0
[wiki] Pjax GridView: refresh page after delete Tue, 24 Jul 2018 14:11:51 +0000 https://www.yiiframework.com/wiki/867/pjax-gridview-refresh-page-after-delete https://www.yiiframework.com/wiki/867/pjax-gridview-refresh-page-after-delete hehbhehb hehbhehb

Normally, after clicking the delete button in gridview, the record will be deleted and the page will refresh, but the page number in query string is lost. This is not always the case we expect.

How to refresh current page with pjax after deleting the record? It seems there is no very simple solution.

  1. Controller file

     public function actionDelete($id)
     {
         $this->findModel($id)->delete();
         if (Yii::$app->request->isAjax) {
             Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
             return ['success' => true];
         }
         return $this->redirect(['index']);
     }
    
  2. index.php (view file)

    <?php
     $this->registerJs("
         $(document).on('ready pjax:success', function() {
             $('.pjax-delete-link').on('click', function(e) {
                 e.preventDefault();
                 var deleteUrl = $(this).attr('delete-url');
                 var pjaxContainer = $(this).attr('pjax-container');
                 var result = confirm('Delete this item, are you sure?');                                
                 if(result) {
                     $.ajax({
                         url: deleteUrl,
                         type: 'post',
                         error: function(xhr, status, error) {
                             alert('There was an error with your request.' + xhr.responseText);
                         }
                     }).done(function(data) {
                         $.pjax.reload('#' + $.trim(pjaxContainer), {timeout: 3000});
                     });
                 }
             });
    
         });
     ");
    ?>
    
    <?php Pjax::begin(['id' => 'my_pjax']); ?>
     <div class="shop-index">
         <?= GridView::widget([
             'dataProvider' => $dataProvider,
             'filterModel' => $searchModel,
             'columns' => [
                 'id',
                 [
                     'class' => 'yii\grid\ActionColumn',
                     'buttons' => [
                         'update' => function ($url, $model) {
                             return Html::a('<span class="glyphicon glyphicon-pencil"></span>', $url, [
                                 'class' => 'pjax-update-link',
                                 'title' => Yii::t('yii', 'Update'),
                             ]);
                         },
                         'delete' => function ($url, $model) {
                             return Html::a('<span class="glyphicon glyphicon-trash"></span>', false, [
                                 'class' => 'pjax-delete-link',
                                 'delete-url' => $url,
                                 'pjax-container' => 'my_pjax',
                                 'title' => Yii::t('yii', 'Delete')
                             ]);
                         }
                     ],
                 ],
             ],
         ]); ?>
     </div>
    <?php Pjax::end(); ?>
    
]]>
0
[wiki] Configuring PhpStorm IDE for Yii 2 Fri, 27 Apr 2018 13:08:08 +0000 https://www.yiiframework.com/wiki/865/configuring-phpstorm-ide-for-yii-2 https://www.yiiframework.com/wiki/865/configuring-phpstorm-ide-for-yii-2 CeBe CeBe

There are a few settings and plugins that can enhance the development experience with Yii in PHPStorm or IntelliJ IDEA. This article explains how to get the most out of your IDE.

This arcticle is valid for Yii 2 and above, there is an older article for Yii 1.1.

Plugins

  • Yii2 Support adds many useful tools that improve working with Yii. It makes working with class configuration, DI and views easier.

  • Yii2 Inspections is a very useful plugin that adds Yii specific code inspections to PHPStorm. It helps for example to manage @property annotations for getters and setters as well as translation messages.

  • Php Inspections (EA Extended) is not directly Yii related but has a lot of additional code inspections that help you write better code. There is also a paid version that has even more features, especially security related inspections.

Project Setup

  • Exclude runtime directories from code search. Debug toolbar stores a lot of stuff that clutters search results.

    runtime - right click - Mark Directory As - Excluded

  • Enable composer integration to tell PHPStorm to separate vendor files from project files.

    composer.json - right click - Composer - Init Composer ...

PHPUnit and Codeception

PHPStorm has integrations for PHPUnit as well as Codeception, so you can run your tests directly from the IDE.

Settings for that can be found at Run - Edit Configurations....

To add your Codeception tests, click the + button, select Codeception. Then enter the following details:

  • Name: "Codeception tests" - or whatever you want to name it
  • Test Scope: Defined in the Configuration file
  • Use alternative configuration file: "codeception.yml"
  • In case PHPStorm asks you to do it, configure a PHP Interpreter in PHPStorm settings
  • Configure Codeception binary as vendor/bin/codecept

You can now run your tests directly from PHPStorm.

For PHPUnit the steps are similar but Yii application templates do not provide PHPUnit tests by default so the options depend on your setup.

]]>
0
[wiki] How to login from different tables in Yii2 Thu, 05 Apr 2018 13:57:25 +0000 https://www.yiiframework.com/wiki/864/how-to-login-from-different-tables-in-yii2 https://www.yiiframework.com/wiki/864/how-to-login-from-different-tables-in-yii2 androidelp androidelp

The Problem: Yii2 utilizes by default UserIdentity configured in config/web.php for connection, this object appy one table to authentication ('identityClass' => 'app\painel\models\User'). How to authentication from diferent tables? Solution: Create instances in web.php to uses UserIdentify. eg:

$user = \Yii::$app->user;  
$school = \Yii::$app->school; 
$teacher = \Yii::$app->teacher;

My config/web.php

'user' => [
	'class'=>'yii\web\User',
	'identityClass' => 'app\models\User',
	'enableAutoLogin' => false,
	'authTimeout' => 60*30,
	'loginUrl' => ['dashboard/login'],
	'identityCookie' => [
		'name' => '_panelUser',
	]
],
'school'=>[
	'class'=>'yii\web\User',
	'identityClass' => 'app\models\SchoolUser',
	'enableAutoLogin' => false,
	'authTimeout' => 60*30,
	'loginUrl' => ['dashboard-school/login'],
	'identityCookie' => [
		'name' => '_panelSchool',
	]	
],
'teacher'=> [
	'class'=>'yii\web\User',
	'identityClass' => 'app\models\TeacherUser',
	'enableAutoLogin' => false,
	'authTimeout' => 60*30,
	'loginUrl' => ['dashboard-teacher/login'],
    'identityCookie' => [
		'name' => '_painelTeacher',
	]
],

Note that for each there is a identifyClass and one view login. Now, we need to create the models:

namespace app\models;
use Yii;
// My user
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface
{
    public static function tableName()
    {
        return '{{%user}}';
    }
    // to continues....

Model scholl:


namespace app\models;
use Yii;
// My School
class SchoolUser' extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface
{
    public static function tableName()
    {
        return '{{%schoolUser}}';
    }
    // to continues
    

Model Teacher:


namespace app\models;
use Yii;
// My School
class TeacherUser'' extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface
{
    public static function tableName()
    {
        return '{{%teacher}}';
    }
    // to continues....

Now In my example I want to have controllers for each type of access, without generating conflicts between them:

In Behavior of the controller i have defined for dashboard-school, teacher and user, the user object representing the authentication status or the ID of the user application component.


	//behaviors of the school
public function behaviors()
{
	return [
        'access' => [
            'class' => AccessControl::className(),
            'user'=>'school', // this user object defined in web.php
            'rules' => [
                [
                    'allow' => true,
                    'roles' => ['@'],
                ],
                [
                    'allow' => true,
                    'actions' => ['login'],                    
 'roles' => ['?'],

                ],
            ],
        ]
    ];
}

To use login:

//school
\Yii::$app->scholl->login($model, $this->rememberMe ? 3600*24*30 : 0);

//teacher
\Yii::$app->teacher->login($model, $this->rememberMe ? 3600*24*30 : 0);

For restrict access in views:

<?php if (!\Yii::$app->scholl->isGuest):?>
<h1>My scholl Name: <?=\Yii::$app->scholl->identity->name?>
<?php endif;?>

<?php if (!\Yii::$app->teacher->isGuest):?>
<h1>Teacher Name: <?=\Yii::$app->teacher->identity->name?>
<?php endif;?>

Always use the specific instance of the user you want to work with.

Criticism, suggestions and improvements, use the comments

]]>
0
[wiki] Use non Gmail/Gsuite on Gcloud projects Sun, 15 Jul 2018 14:00:50 +0000 https://www.yiiframework.com/wiki/863/use-non-gmailgsuite-on-gcloud-projects https://www.yiiframework.com/wiki/863/use-non-gmailgsuite-on-gcloud-projects gogl92 gogl92

Small companies and startups use cheap email services or even Cpanel's mail services which are less secure and compete directly with bigger email providers like Microsoft with Outlook and Google with Gmail. This creates a problem when you try to use their services to send/receive emails from this cheap services. google-cloud-platform.png

Google says this: Google Compute Engine does not allow outbound connections on ports 25, 465, and 587. By default, these outbound SMTP ports are blocked because of the large amount of abuse these ports are susceptible to. In addition, having a trusted third-party provider such as SendGrid, Mailgun, or Mailjet relieves Compute Engine and you from maintaining IP reputation with your receivers.

Some time ago I had a project that requieres this, send emails using a cpanel mail services but we have Google Cloud services so when the client send me the credentials to put it in production the app crashes in a critical time, client will not pay to use Gsuite and I have all the stuff ready for production and configured in Google Cloud, so I found a solution.

  • Make sure you have swiftmail extension installed (it also comes with the basic and advance template)
  1. First get a Gmail or Gsuite account to use it as a bridge between emails. The name doesn't matter it will never be seen by final users. let's say mail_service54@gmail.com or use a Gsuite custom email. It is also important that you have full priviledges to this email as you will need it in the next step.
  2. Enable less secure apps to your email. [https://support.google.com/accounts/answer/6010255?hl=en](Official Docs here)
  3. Now configure the swiftmailer extension to send emails with your account. I use this config for gmail/gsuite accounts:
    'mailer' => [
             'class' => 'yii\swiftmailer\Mailer',
             'transport' => [
                 'class' => 'Swift_SmtpTransport',
                 'host' => 'smtp.gmail.com',
                 'username' => 'yourmail@gmail.com',
                 'password' => 'your password',
                 'port' => '587',
                 'encryption' => 'tls',
             ],
         ],
    
  4. Test that you can send an email so we can get sure the past configuration works well.
  5. After you can send an email, login into your account on the web and go to settings > Accounts and Import > Send mail as
  6. Do the import process of the other service/cpanel email, usually they will send you a link/code to the other email and you will have to confirm it.
  7. Now you can from your gmail account send mails as some other mail.
  8. Do this in your Yii code:
    Yii::$app->mailer->compose()
     ->setFrom('from@cpanel-mail.com')
     ->setTo('to@domain.com')
     ->setSubject('Message subject')
     ->setTextBody('Plain text content')
     ->setHtmlBody('<b>HTML content</b>')
     ->send();
    

    And that's it!

This is the first post of many about using Yii/Open Source in business and enterprise level becuase Open source != not cost.

]]>
0
[wiki] Yii2 RESTful API with OAuth 2.0 Thu, 08 Nov 2018 00:08:15 +0000 https://www.yiiframework.com/wiki/862/yii2-restful-api-with-oauth-2-0 https://www.yiiframework.com/wiki/862/yii2-restful-api-with-oauth-2-0 sirin_ibin sirin_ibin

https://cdn.pbrd.co/images/GMN5ROs.jpg

Overview

This article is for the one’s who is already working with PHP/Yii2 or who wants to quick start developing a RESTful API using Yii2 framework with

  1. OAuth 2.0 authentication
  2. A developer dashboard
  3. API documentation template

Here I’m sharing the Live demo and Source code of a RESTful API with OAuth2 authentication/security developed using Yii2 framework You can use this if you want to quick start developing your own custom RESTful API by skipping 95% of your scratch works. Hopefully this will save lot of your time as this API includes all the basic stuffs you need to get started.

Developer Dashboard

This API also includes a developer dashboard with the API documentation which is developed in Yii2 framework. This will be useful to manage your developers access to the API documentation.

Why Yii2?

Yii2

It's Fast, It’s Secure and Professional!. Yii comes with rich features: MVC, DAO/ActiveRecord, I18N/L10N, caching, authentication and role-based access control, scaffolding, testing, etc. It can reduce your development time significantly.

What is a RESTful API?

REST is an architectural style for building APIs. It stands for “Representational State Transfer”. It means when we build an API, we build it in a way that HTTP methods and URIs mean something, and the API has to respond in a way that’s expected.

Something about OAuth 2.0

The OAuth 2.0 is an authorization framework which enables a third-party application to obtain limited access to an HTTP service.

DEMO

http://developers.yii2.nintriva.net/

Login: developer/developer

Source Code

https://github.com/sirinibin/Yii2-RESTful-API-with-OAuth2

Official Documentation

Documentation for this RESTful API can be found on the Yii 2.0 RESTful API with OAuth 2.0 Documentation. Security Vulnerabilities

If you discover a security vulnerability within this API, please send an e-mail to Sirin k at sirin@nintriva.com. All security vulnerabilities will be promptly addressed.

Installation instructions

https://github.com/sirinibin/Yii2-RESTful-API-with-OAuth2

Similar API Implementation in NodeJs,Laravel &GoLang

Expressjs 4.15/Mysql RESTful API with OAuth2

Expressjs 4.15/MongoDb RESTful API with OAuth2

Laravel 5.5 Lumen 5.5/Mysql RESTful API with OAuth2

GoLang/MongoDb Microservice with OAuth2

Linkedin Post1

Linkedin Post2

Sirin K

]]>
0
[wiki] How to get SEO friendly URL using Model and new getUrl() function Thu, 21 Sep 2017 04:25:33 +0000 https://www.yiiframework.com/wiki/861/how-to-get-seo-friendly-url-using-model-and-new-geturl-function https://www.yiiframework.com/wiki/861/how-to-get-seo-friendly-url-using-model-and-new-geturl-function shivam4u shivam4u

We all need SEO friendly URLs for our projects. its not always good to call route with params so we can generalise it for all models using a common function.

Following the general convention of model and control sharing common name, we can use this code to get seo friendly URL.

public function getControllerID() {
		$modelClass = get_class ( $this );
		$pos = strrpos ( $modelClass, '\\' );
		$class = substr ( $modelClass, $pos + 1 );
		return Inflector::camel2id ( $class );
	}
	public function getUrl($action = 'view', $id = null) {
		$params = [ 
				$this->getControllerID () . '/' . $action 
		];
		if ($id != null)
			$params ['id'] = $id;
		else
			$params ['id'] = $this->id;
		// add the title parameter to the URL
		$params ['title'] = ( string ) $this;
		// absolute url
		return Yii::$app->getUrlManager ()->createAbsoluteUrl ( $params, true );
	}

In code code where ever you need to url to a model , you just call $model->url or $model->getUrl('view').

You may have to additionally update urlManager in config with rules for pretty url.

'<controller:[A-Za-z-]+>/<id:\d+>/<title>' => '<controller>/view',
								'<controller:[A-Za-z-]+>/<id:\d+>' => '<controller>/view',
								'<controller:post>/<id:\d+>/<title>' => 'blog/view',
								'<controller:[A-Za-z-]+>/<action:[A-Za-z-]+>/<id:\d+>/<title>' => '<controller>/<action>',
								'<controller:[A-Za-z-]+>/<action:[A-Za-z-]+>/<id:\d+>' => '<controller>/<action>',
	

you will get url like this.

http://localhost/link/650/need-a-professional-developer

]]>
0
[wiki] Yii2 Report Grid Mon, 26 Mar 2018 10:10:29 +0000 https://www.yiiframework.com/wiki/860/yii2-report-grid https://www.yiiframework.com/wiki/860/yii2-report-grid chrisb34 chrisb34

A Yii2 Gridview designed specifically for reporting

  1. Why is this significant
  2. Widget Setup
  3. Column Configuration

There are some very advanced grids in the Yii2 community, specifically Kartik's amazing gridview extensions but they all designed for interactive screen use.

ReportGrid is designed to provide report results to users, without filtering or sorting.

But more importantantly it has sub-totalling and report totalling built into the gridview itself.

Why is this significant

Because it enables you to use closures (anonymous functions) within the sub-total fields. For example, say we want to build a report on order items, with a break at order level. At the order level, we want to report something off the order model but the dataProvider is on the order-item level.

With ReportGrid, we can do this by using a closure on the sub-total to return the $model->order->some_relationship->some_value

Installation The preferred way to install this extension is through composer. Either run:

$ php composer.phar require chrisb34/reportgrid "@dev"

or add:

"chrisb34/yii2-report-grid": "@dev"

to the require section of your composer.json file. Then run:

php composer.phar update

to get the updated package on your application install.

Widget Setup

As with most Yii2 widgets, you control the using options on widget creation. This widget is based on the Yii2 gridview widget, so anything mentioned here is over and above the base options on the gridview widget

Note: that this widget does not support pagination. It actively switches pagination off in the dataProvider

  • controlBreak : boolean, turn on all this functionality. defaults to true. If set to false will make this widget behave like a notmal gridView

  • totalRowOptions : array, array list of options eg: [ 'class'=>'total-row']

  • totalsHeader : boolean, whether to repeat the table header row just before the report totals.

  • exportCSV : boolean, whether to include the 'Export to CSV' button

  • afterRow : closure, provides the ability to output an extra row after every model row. Closure call in the format function( $model, $key, $index)

  • pageSummary : closure, provides the ability to output an extra row at the end of the report. Closure call in the format function( $model, $key, $index)

Usage

echo ReportGrid::widget([
    'dataProvider' => $dataProvider,
    'columns' => $gridColumns,
    'controlBreak' => true,
    'totalRowOptions' => ['class'=>'total-row'],
    'totalsHeader' => true,
    'exportCSV' => true,
    'afterRow' => function( $model, $key, $index)  {
    	return $someContent;
    },
    'pageSummary' => [
            Html::tag('tr','<td colspan=10><h1>Report Summary goes here</h1></td>'),
    ]
    
    ]);

Column Configuration

When you use sub-totalling in a report, your report layout must follow the same structure as your query. So the first thing is to define your query with the results in the correct order.

When defining columns, you first need to specify which columns will cause your report to break. Normally, these will also be in the same order as the columns themselves but this is not mandatory.

  • subTotalOn : integer, The break level runs from 1 upwards and the gridview then uses level zero as the report totals.

  • subTotal : array | boolean, with the following options;
    • if set to true, then reportGrid uses the attribute value, summing the model->attribute or model->value amounts.
    • value : string|attribute name|closure ~ function($model, $key, $index, $widget, $break) {}, the value used by the totalling function as opposed to the value displayed.
    • breakValue : string|attribute name|closure ~ function($model, $key, $index, $widget, $break) {}, what to display in the sub-total cell. note the addition of the $break variable which can be used to determine the current break level. For example: you may use if ($break!=1) return $model->some_amount; else return ' ';
    • showOnBreak | hideOnBreak : integer, show/hide the sub-total at the specified break level
    • format : boolean, uses the yii2 formatter to pre-format the cell contents eg: currency, html, text
    • totalMethod : the only available option at this stage is ReportColumn::TOTAL_BREAKDOWN, This will provide a summary table at the control break of this column values and summed values specified by totalOn.
    • totalOn : string|attribute name|closure ~ function($model, $key, $index, $widget, $break) { return $model->attribute; },, the value to be applied to the totalling.

Usage

'subTotal' => [
       'breakValue' => function($model, $key, $index, $widget, $break) {
           if ($break == 1)
               return   $model->category_name; 
           elseif ($break == 0)
               return 'REPORT TOTAL';
       },
       'hideOnBreak' => 2
       ]
	

for more info see: yii2.percipero.com

]]>
0
[wiki] How to make UrlManager createAbsoluteUrl work with sub-domains Sun, 25 Mar 2018 02:06:47 +0000 https://www.yiiframework.com/wiki/858/how-to-make-urlmanager-createabsoluteurl-work-with-sub-domains https://www.yiiframework.com/wiki/858/how-to-make-urlmanager-createabsoluteurl-work-with-sub-domains wadeshuler wadeshuler

Upon creating my Yii2 Members System, I have ran into a few snags along the way that forced me to extend and bend Yii2 to my will.

I will describe how my app is intended to work, so you know how this article fits into your project needs. My members system is designed to resemble the good ole' days, when we had site.com/members and site.com/admin. It is common to also have them on sub-domains as members.site.com and admin.site.com . The sub-domains add an extra layer of security, especially with the admin on it's own sub-domain separate from the users. Now, that alone wont save you from everything, but as I said, it's just an extra layer. Some of us need them separated like this, because the sub-domains are on different servers. For example, your API could be on an independent server. Or maybe your users and admin sections are on different servers or IPs. If you look at large systems like Microsoft or Adobe, they have many servers for many different uses. Users, API, time, activation, fonts, and many more... So it isn't crazy to want your apps on different sub-domains.

Unfortunately, Yii2 is flat out retarded when it comes to sub-domains. Hopefully they will implement what I am about to show you, or a better version of this. I am always open to a better way to do this.

When I Googled this issue, there wasn't much out there. I found info related to how to link to backend from frontend, and that is even in the official Yii2 docs. That DOES NOT work with sub-domains though! It only works for directories, ie: what comes after your domain, not the sub-domain. I did find one GitHub repo from Postor. Problem was, it wasn't very intuitive and looks like a broken unfinished repo. So I feel the one I made was better.

So in this guide, I am going to show you the best and only way I found to create links to another one of your Yii apps (ie: backend or frontend) that are on a sub-domain.

My method for handling sub-domains

Unfortunately, there isn't an accurate and reliable way to grab only the domain name. A bunch of regex or stripping, or pulling from a huge list of valid domain extensions, etc. Nothing you want running on a site with tons of users, it will create a bottle neck real quick. Yeah, you could implement caching and you should for large volume sites. However, I prefer to cache lean efficient code instead of using caching to save my rear on terrible logic.

So this REQUIRES us to define our domain and sub-domains in our common bootstrap file.

common/config/bootstrap.php

// URL Manager Aliases
Yii::setAlias('@domainName', (YII_ENV === 'dev') ? 'yii2-members-system.dev' : 'yourlivesite.com');
Yii::setAlias('@frontendSubdomain', 'users');
Yii::setAlias('@backendSubdomain', 'admin');

Create common/components/UrlManager.php

<?php
namespace common\components;

use Yii;
use yii\helpers\Url;
use yii\base\InvalidConfigException;

class UrlManager extends yii\web\UrlManager
{
    public $subDomain;
    public $domainName;

    protected $_hostInfo;

    public function getProperDomain()
    {
        if ( ! isset($this->domainName) || empty($this->domainName) ) {
            throw new InvalidConfigException('Request requires a domain name to be configured!');
        }

        $subDomain = (isset($this->subDomain) && !empty($this->subDomain)) ? $this->subDomain : '';
        $domain = empty($subDomain) ? '' : $subDomain . '.';
        $domain .= $this->domainName;

        return $domain;
    }

    public function getHostInfo()
    {
        if ($this->_hostInfo === null)
        {
            $secure = Yii::$app->getRequest()->getIsSecureConnection();
            $http = $secure ? 'https' : 'http';

            if (isset($_SERVER['HTTP_HOST'])) {
                $this->_hostInfo = $http . '://' . $this->getProperDomain();
            } elseif (isset($_SERVER['SERVER_NAME'])) {
                $this->_hostInfo = $http . '://' . $this->getProperDomain();
                $port = $secure ? $this->getSecurePort() : $this->getPort();

                if (($port !== 80 && !$secure) || ($port !== 443 && $secure)) {
                    $this->_hostInfo .= ':' . $port;
                }
            }
        }
        return $this->_hostInfo;
    }

}

Now in whichever app your needing to link to another subdomain, you need to edit it's main config. So if in backend you need to link to frontend (or mainsite needs to link to frontend as in my members system), then edit your backend config.

Add this to your config under the components array:

'urlManagerFrontend' => [
    'class' => 'common\components\UrlManager',
    'subDomain' => Yii::getAlias('@frontendSubdomain'),
    'domainName' => Yii::getAlias('@domainName'),
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'rules' => [
    ],
],

Now, wherever you need to create a link (or get the url for any reason) use CreateAbsoluteUrl inside the new UrlManager like so:

Yii::$app->urlManagerFrontend->createAbsoluteUrl(['site/login'])

In my app, it generates a link for my mainsite to the users app: http://users.yii2-members-system.dev/site/login. This was so on my mainsite I can link to the user's subdomain for them to login.

I hope this helps someone, and I hope Yii actually adopts a solution for this sort of linking and handling sub-domains.

]]>
0