Live News for Yii Framework News, fresh extensions and wiki articles about Yii framework. Mon, 20 May 2019 00:29:48 +0000 Zend_Feed_Writer 2 (http://framework.zend.com) https://www.yiiframework.com/ [extension] unique Mon, 20 May 2019 00:29:46 +0000 https://www.yiiframework.com/extension/unique https://www.yiiframework.com/extension/unique adil adil
  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
[extension] swoole-foundation/yii2-swoole-extension Mon, 20 May 2019 00:29:46 +0000 https://www.yiiframework.com/extension/swoole-foundation/yii2-swoole-extension https://www.yiiframework.com/extension/swoole-foundation/yii2-swoole-extension xialeistudio xialeistudio

yii2 swoole extension

  1. 快速开始
  2. 示例项目

在swoole环境下运行Yii2应用。

yii2-swoole基于Yii2组件化进行编程,对业务和Yii2无侵入性。

快速开始

  1. 初始化Yii2应用
  2. 安装扩展 `bash composer require swoole-foundation/yii2-swoole-extension `
  3. 新建服务器配置(config/server.php) `php <?php /**
    • @author xialeistudio
    • @date 2019-05-17 */ return [ 'host' => 'localhost', 'port' => 9501, 'mode' => SWOOLE_PROCESS, 'sockType' => SWOOLE_SOCK_TCP, 'app' => require DIR . '/web.php', // 原来的web.php配置 'options' => [
       'pid_file' => __DIR__ . '/../runtime/swoole.pid',
       'worker_num' => 2,
       'daemonize' => 0,
       'task_worker_num' => 2,
      

      ] ]; `

  4. 新增启动脚本(index.php) `php <?php /**

    • @author xialeistudio
    • @date 2019-05-17 */

    use swoole\foundation\web\Server; use Swoole\Runtime;

    Runtime::enableCoroutine(); defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', getenv('PHP_ENV') === 'development' ? 'dev' : 'prod');

    require DIR . '/vendor/autoload.php'; require DIR . '/vendor/yiisoft/yii2/Yii.php';

    $config = require DIR . '/config/server.php'; $server = new Server($config); $server->start(); `

  5. 启动应用 `bash php index.php `

示例项目

tests 目录下有测试用的完整项目。

]]>
0
[extension] sjaakp/yii2-pluto Mon, 20 May 2019 00:29:46 +0000 https://www.yiiframework.com/extension/sjaakp/yii2-pluto https://www.yiiframework.com/extension/sjaakp/yii2-pluto sjaakp sjaakp

yii2-pluto

  1. User management module for Yii2 framework
  2. Prerequisites
  3. Installation
  4. Options
  5. Profile
  6. Roles, Permissions and all that
  7. Sign up the first 'admin'
  8. Captcha
  9. Internationalization
  10. Override view-files
  11. Override identity-class
  12. Pluto

User management module for Yii2 framework

Pluto is a complete user management module for the Yii 2.0 PHP Framework.

It manages log in and log out of users, sign up, email-confirmation, blocking and assigning roles. Users can change their email-address, ask for a reset of their password. The site administrator can define roles and permissions and assign permissions to roles.

A demonstration of Pluto is here.

Prerequisites

Pluto relies on Role-Based Access Control (RBAC). Therefore, the authManager application component has to be configured. Pluto works with Yii's PhpManager as well as with the DbManager.

Because Pluto sends emails, the mailer component of the application has to be up and running. Be sure that the 'adminEmail' parameter of the application has a sensible value. If you prefer, you may set the 'supportEmail' parameter as well; if set, Pluto will use this.

Pluto uses Yii2 flash messages, so these have to be configured as well. If the site is set up using one of Yii's project templates, this will be taken care of.

Installation

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

"sjaakp/yii2-pluto": "*"

or run:

composer require sjaakp/yii2-pluto

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

Module

Pluto is a module in the Yii2 framework. It has to be configured in the main configuration file, usually called web.php or main.php in the config directory. Add the following to the configuration array:

<?php
// ...
'modules' => [
    'pluto' => [
        'class' => 'sjaakp\pluto\Module',
        // several options
    ],
],
// ...

The module has to be bootstrapped. Do this by adding the following to the application configuration array:

<php
// ...
'bootstrap' => [
    'pluto',
]
// ...

There probably already is a bootstrap property in your configuration file; just add 'pluto' to it.

Important: the module should also be set up in the same way in the console configuration (usually called console.php).

Console commands

To complete the installation, two console commands have to be run. The first will create a database table for the users:

yii migrate

The migration applied is called sjaakp\pluto\migrations\m000000_000000_init.

The second console command is:

yii pluto

This will set up the basic roles and permissions.

Actions

Pluto adds a bunch of actions to the application. The most important are:

RouteDescription
<example.com>/pluto/loginto log in
<example.com>/pluto/logoutto log out
<example.com>/pluto/signupto sign up (register)
<example.com>/pluto/forgotif the user forgot her password
<example.com>/pluto/settingsto change name or email-address
<example.com>/pluto/downloadto download user data in human and machine readable form (requirement of European legislation)
<example.com>/pluto/deleteto be completely forgotten by the site (also a requirement of the EU)
<example.com>/pluto/userUser management (only for 'support' and 'admin' Roles)
<example.com>/pluto/roleRole management (only for 'admin')
Roles

After installation of Pluto, the site recognizes two user Roles and a few Permissions. Read more about them in the Authorization chapter of the Yii-guide. The installed Roles are:

RoleDescription
'support'user who can manage user data (except those from 'admin')
'admin'user with unlimited Permissions, like creating more Roles and Permissions
Integrate in the user interface

Now that Pluto is installed, it has to be integrated in the user interface of the site. There are dozens of ways to accomplish this, but here are some general guidelines:

  • A guest user should be offered an opportunity to log in. Pluto's login screen has options to sign up (register) for new users, and to reset the password.
  • An authenticated user should be offered an opportunities to log out, as well as to change her settings, etc.
  • Users with special permissions should have options to access Pluto's User Management Pages and the like.

LoginMenu is a widget to integrate Pluto in the site's main menu:

<?php
use ...
use sjaakp\pluto\widgets\LoginMenu

$user = Yii::$app->user;

$navItems = [
    ['label' => 'Home', 'url' => '/' ],
    // ...
    ['label' => 'About', 'url' => ['/site/about']],
    // ... more menu items ...,
    LoginMenu::widget([
        'options' => [
           'class' => 'bg-primary'
        ]
    ]),
];

NavBar::begin([
    'options' => [
        'class' => '... navbar-dark bg-primary',
    ],
    // ... more NavBar options ...
]);
echo Nav::widget([
    'items' => $navItems,
]);
NavBar::end();

Take care to give LoginMenu the same background defining CSS class as NavBar, for instance bg-primary.

Options

The Pluto module has an extensive range of options. They are set in the application configuration like so:

 <?php
 // ...
 'modules' => [
     'pluto' => [
         'class' => 'sjaakp\pluto\Module',
         'passwordHint' => 'At least eight characters, one uppercase, one digit',
         // ...
         // ... more options ...
     ],
 ],
 // ...
 

The options (all are optional) are:

  • viewOptions array CSS options for certain aspects of Pluto's views, with the following key-value pairs. Optimized for Bootstrap4.
    • 'row' Options for the outer 'row'-div. Default value: [ 'class' => 'row justify-content-center' ].
    • 'col' Likewise for the inner 'col'-div. Default: [ 'class' => 'col-md-6 col-lg-5' ].
    • 'button' Options for the view's main button. Default: [ 'class' => 'btn btn-success' ].
    • 'link' Options for the secondary links. Default: [ 'class' => 'btn btn-sm btn-secondary' ].
  • views array See below. Default: [].
  • mailOptions array Options for the app mailer. Default: see source.
  • passwordFlags array Options for the password input. Keys: any of the action id's (like 'login' or 'forgot'), or 'all' (meaning, well, all of the actions). Values: string or array of the following flags. Default: [ 'all' => 'reveal' ].
    • 'reveal' Password input has a small 'reveal'-button.
    • 'double' User must fill in password twice (doesn't affect 'forgot', 'resend').
    • 'captcha' Dialog has captcha field.
  • passwordRegexp string Regular expression against which the password is matched. Complex example: '^\S*(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$' (meaning: at least 8 characters, of which at least one lower case, one upper case, and one digit. To experiment with this, use a site like Live Regex. Default: '/^\S*(?=\S{6,})\S*$/'.
  • passwordHint string Textual representation of the above. Default: 'At least 6 characters'.
  • defaultRole null|string|array Role(s) assigned to new users. Default: null.
  • firstDefaultRole null|string|array Role(s) assigned to the first new user. Default: 'admin'.
  • ruleNamespace string Namespace for Rule-classes (Conditions). Default: 'app\rbac'
  • tokenStamina integer Duration of the valid state of a sent email-token. Default: 21600 (six hours).
  • loginStamina integer Duration of 'Remember me'. Default: 2592000 (thirty days).
  • formClass null|string Yii2 class used for forms. If null, this is set to ActiveForm in the 'bootstrap' namespace. Default: null
  • multipleRoles boolean Whether more than one role can be assigned to a user. In my opinion this is generally a very bad idea. Therefore, default: false.
  • fenceMode boolean Whether the site is 'behind a fence', i.e. completely unaccessible for guest users. Every page leads to the login screen. Great for development stages. Default: false.
  • profileClass null|string|array Name of the class used as profile. Can also be a configuration array. Default: null.
  • identityClass string Class name of the identity object associated with the current user. May be changed into a class extended from sjaakp\pluto\models\User. Default: 'sjaakp\pluto\models\User'.

Profile

Apart from the User model, users can also have a Profile model. This can hold extra information that's intended to be public: a short bio, profile photo, avatar, location and the like. Pluto doesn't implement a Profile model itself, but it does support it.

A Profile is a standard ActiveRecord with one, very important, peculiarity: it's id field is not auto-incrementing.

Instead, the id field in the Profile's database table should be declared UNIQUE. The Profile takes the same id as the User it is associated with.

The Profile model should be configured as profileClass in Pluto's configuration.

Instead of just the class name, the 'profile' component can also be initialized with a configuration array, with the class name as value of the 'class' element, like on many other places in the Yii2 kingdom.

With this setup, Pluto will automatically create a Profile for each registered user. If a User is deleted, her Profile will be deleted as well.

Roles, Permissions and all that

For the uninitiated, Roles and Permissions can be daunting. The Authorization chapter of the Yii-guide offers some help. Basically, Roles are assigned to Users, and Permissions are used to structure the site. One or more Permissions are assigned to each Role.

Both Roles and Permissions can be subject to Conditions (Yii2 calls these 'Rules'). They are implemented as PHP classes, extending from yii\rbac\Rule. Pluto looks under namespace 'app\rbac' (settable by option ruleNamespace) for unregistered Condition's and offers 'admin' an opportunity to register them.

Pluto avoids the somewhat misleading term 'children' with respect to Roles and Permissions. Instead it uses 'Included Roles' or 'Included Permissions'.

Sign up the first 'admin'

With the default set-up, Pluto automatically assigns the 'admin' Role to the first user who signs up. If afterwards you come into a situation without a registered 'admin', there is no possibility to manage Roles. There are several solutions to this puzzle. One is: temporarely set Pluto's defaultRole to 'admin'. The importance of temporarely can't be stretched enough. You'll never want this setting in a live site.

Captcha

Pluto supports Yii2's standard Captcha, as well as Google's reCaptcha v2 ('I am not a robot'). A captcha-challenge will show up in the dialog when one of the passwordFlags is 'captcha'. If himiklab/yii2-recaptcha-widget is installed on the site, it will be Google's reCaptcha v2, otherwise Yii2's standard captcha.

Internationalization

All of Pluto's utterances are translatable. The translations are in the 'sjaakp\pluto\messages' directory.

You can override Pluto's translations by setting the application's message source in the main configuration, like so:

<?php
// ...
'components' => [
    // ... other components ...     
    'i18n' => [
         'translations' => [
              // ... other translations ...
             'pluto' => [    // override pluto's standard messages
                 'class' => 'yii\i18n\PhpMessageSource',
                 'basePath' => '@app/messages',  // this is a default
                 'sourceLanguage' => 'en-US',    // this as well
             ],
         ],
    ],
    // ... still more components ...
]

The translations should be in a file called 'pluto.php'.

If you want a single or only a few messages translated and use Pluto's translations for the main part, the trick is to set up 'i18n' like above and write your translation file something like:

 <?php
 // app/messages/nl/pluto.php
 
 $plutoMessages = Yii::getAlias('@sjaakp/pluto/messages/nl/pluto.php');
 
 return array_merge (require($plutoMessages), [
    'Settings' => 'Instellingen',   // your preferred translation
 ]);

At the moment, the only language implemented is Dutch. Agreed, it's only the world's 52th language, but it happens to be my native tongue. Please, feel invited to translate Pluto in other languages. I'll be more than glad to include them into Pluto's next release.

Override view-files

Any of the Pluto's view files can be overridden, perhaps to add a logo or change the structure. Just set the views setting of the module to something like:

 <?php
 // ...
 'modules' => [
     'pluto' => [
         'class' => 'sjaakp\pluto\Module',
         'views' => [
              'default' => [    // Pluto controller id
                  'login' => <view file>    // action => view
              ]
         ],
         // ...
         // ... more options ...
     ],
 ],
 // ...

<view file> can be of any form yii\web\controller::render() accepts.

Override identity-class

Pluto sets sjaakp\pluto\models\User as identityClass of the application's yii\web\User component. If you're ambitious, you might develop your own identity-class. This should extend from sjaakp\pluto\models\User and be set as Pluto's identityClass option.

Pluto

Pluto happens to be the name of a friendly guard dog I once knew. If you really hate that name, just set up the module like this:

<?php
// ...
'modules' => [
    'saturnus' => [
        'class' => 'sjaakp\pluto\Module',
        // several options
    ],
],
// ...
'bootstrap' => [
    'saturnus',
]
// ...

Your users will never be confronted with the name 'pluto'.

]]>
0
[extension] kartavik/yii2-enum Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/kartavik/yii2-enum https://www.yiiframework.com/extension/kartavik/yii2-enum KartaviK KartaviK

993323

Enum integration for Yii Framework 2.0

  1. Installation
  2. Usage
  3. Suggest
  4. Author
  5. License

Yii2 enum

  1. Installation
  2. Usage
  3. Suggest
  4. Author
  5. License

Latest Stable Version Build Status codecov

Based on myclabs\php-enum package;

Installation

composer require kartavik/yii2-enum

Usage

Example enum:

<?php

class YourEnum extends \MyCLabs\Enum\Enum
{
    public const FIRST_VALUE = 'first';
    public const SECOND_VALUE = 'second';
}
Validator

This validator used MyCLabs\Enum\Enum::isValid($value) method and also checked value on instance of your enum;

<?php

use YourEnum;
use Kartavik\Yii2;

/**
 * @property YourEnum $attribute1
 * @property YourEnum $attribute2
 */
class Record extends \yii\db\ActiveRecord
{
    public function behaviors(): array
    {
        return [
            'enum' => [
                'class' => Yii2\Behaviors\EnumMappingBehavior::class,
                'map' => [
                    'attribute1' => YourEnum::class,
                    'attribute2' => YourEnum::class,
                ],
                // Set attribute type if need explicitly specify it
                'attributesType' => [
                    'attribute1' => 'integer',
                    'attribute2' => 'float'
                ],
            ]
        ];
    }
    
    public function rules(){
        return [
            [
                ['attribute1', 'attribute2'],
                Yii2\Validators\EnumValidator::class,
                'targetEnum' => YourEnum::class,
            ]
        ];
    }
}

$record = new Record([
    'attribute1' => YourEnum::FIRST_VALUE, // use constant
    'attribute2' => YourEnum::SECOND_VALUE(), // use method
]);

$record->trigger(Yii2\Behaviors\EnumMappingBehavior::EVENT_TO_ENUMS); // trigger if you put values not instance of Enum

$record->validate(); // will return true
Behavior

It can be used for classes that extends ActiveRecord

<?php

use YourEnum;

/**
 * @property YourEnum $attribute1
 * @property YourEnum $attribute2
 */
class Record extends \yii\db\ActiveRecord
{
    public function behaviors(): array
    {
        return [
            'enum' => [
                'class' => \Kartavik\Yii2\Behaviors\EnumMappingBehavior::class,
                'map' => [
                    'attribute1' => YourEnum::class,
                    'attribute2' => YourEnum::class,
                ]
            ]
        ];
    }
}

$record = new Record([
    'attribute1' => YourEnum::FIRST_VALUE, // use const
    'attribute2' => YourEnum::SECOND_VALUE() // use method
]);

$this->trigger(\Kartavik\Yii2\Behaviors\EnumMappingBehavior::EVENT_TO_ENUMS);
$record->save(); // will return true

$record = Record::find()->where(['id' => $record->id])->all()[0];

print_r($record->attribute1); // Will output YourEnum object with value `first`

Record::updateAll(['attribute1' => YourEnum::SECOND_VALUE()]); // Updating records with new enum

$record = Record::find()->where(['id' => $record->id])->all()[0];

print_r($record->attribute1); // Will output YourEnum object with value `second`
Migration
PgSql
<?php

use Kartavik\Yii2\Database\Pgsql;

class CreateRecordTable extends Pgsql\Migration
{
    // You can use trait do receive all methods for enum
    use Pgsql\MigrationTrait;
    
    public function safeUp()
    {
         // simple usage
        $this->addEnum('test_enum_from_array', [/** your values */]);
         // use your enum that extends MyCLabs\Enum\Enum
         // use it for package, for big project this usage is not good practice
        $this->addEnum('test_enum_from_enum', YourEnum::class);
        
         // if enum already exists
        $column = $this->enum('test_enum_from_array');
         // you can do not to use addEnum to create it
        $column = $this->enum('test_enum_dynamic_from_array', [/** your values */]);
         // use your enum that extends MyCLabs\Enum\Enum
         // use it for package, for big project this usage is not good practice
        $column = $this->enum('test_enum_dynamic_from_enum', YourEnum::class);
        
        $this->createTable('record', [
            'enum' => $column->null()->default('default')
        ]);
    }
}
MySql
<?php

use Kartavik\Yii2\Database\Mysql;

class CreateRecordTable extends Mysql\Migration
{
    // You can use trait do receive all methods for enum
    use Mysql\MigrationTrait;
    
    public function safeUp()
    {
        $this->createTable('record', [
            'enum_column_from_array' => $this->enum(['1', '2', '3', '4']),
            // use your enum that extends MyCLabs\Enum\Enum
            // use it for package, for big project this usage is not good practice
            'enum_column_from_enum' => $this->enum(YourEnum::class),
        ]);
    }
}

Suggest

Author

License

MIT

]]>
0
[news] Auth Client extension 2.2.2 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/222/auth-client-extension-2-2-2-released https://www.yiiframework.com/news/222/auth-client-extension-2-2-2-released samdark samdark

We are very pleased to announce the release of Auth Client extension version 2.2.2 fixing Facebook logo to be compliant with Facebook brand guidelines.

See the CHANGELOG for details.

]]>
0
[extension] solutosoft/yii-settings Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/solutosoft/yii-settings https://www.yiiframework.com/extension/solutosoft/yii-settings leandrogehlen leandrogehlen

Yii Settings Extension

  1. Installation
  2. Configuration
  3. Usage:
  4. Events

This extension provides support for persistent settings for Yii2.

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

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist solutosoft/yii-settings

or add

"solutosoft/yii-settings": "*"

Configuration

To use the Setting Component, you need to configure the components array in your application configuration:

'components' => [
    'settings' => [
        'class' => 'Soluto\Settings\Settings',
    ],
],

Usage:

$settings = Yii::$app->settings;

$settings->set('key');

$settings->set('section.key');

// Checking existence of setting
$settings->exists('key');

// Removes a setting
$settings->remove('key');

// Removes all settings
$settings->remove();

Events

You can use beforeExecute event to store extra values and apply extra conditions on command execution

<?php

'components' => [
    'settings' => [
        'class' => 'Soluto\Settings\Settings',
        'on beforeExecute' => function ($event) {
            $event->data = ['user_id' => Yii::$app->user->id];
        }
    ],
],

$settings = Yii::$app->settings;

//INSERT (`key`,`value`, `user_id`) INTO `setting` VALUES ('website', 'http://example.org', 1)
$settings->set('website', 'http://example.org');

//SELECT `value` FROM `setting` WHER (`settings`.`key` = 'website' and `settings`.`user_id` = 1)
$settings->get('website', 'http://example.org');

]]>
0
[news] Debug extension 2.1.4 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/221/debug-extension-2-1-4-released https://www.yiiframework.com/news/221/debug-extension-2-1-4-released samdark samdark

We are very pleased to announce the release of Debug extension version 2.1.4 that fixes multiple bugs and adds ability to customize title of the user panel.

See the CHANGELOG for details.

]]>
0
[news] HTTP client extension 2.0.11 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/220/http-client-extension-2-0-11-released https://www.yiiframework.com/news/220/http-client-extension-2-0-11-released samdark samdark

We are very pleased to announce the release of HTTP client extension version 2.0.11.

This release fixes regression about uploading files with CURL introduced in 2.0.10.

See the CHANGELOG for details.

]]>
0
[extension] xtetis/yii2-bootstrap4-glyphicons Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/xtetis/yii2-bootstrap4-glyphicons https://www.yiiframework.com/extension/xtetis/yii2-bootstrap4-glyphicons xtetis xtetis

Bootstrap4 glyphicons for Yii2

  1. Installation
  2. Usage

If you want use Glyphicons in your Yii2 project with Bootstrap 4 (https://github.com/yiisoft/yii2-bootstrap4)

Installation

The preferred way to install this extension is through composer.

Add the repo to your composer.json.

"repositories":[
    ...
    {
        "type": "git",
        "url": "https://xtetis@bitbucket.org/xtetis/yii2-bootstrap4-glyphicons.git"
    }
    ...
]

Either run

php composer.phar require --prefer-dist xtetis/yii2-bootstrap4-glyphicons "*"

or add

"xtetis/yii2-bootstrap4-glyphicons": "*"

to the require section of your composer.json file.

Usage

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

<?php
use xtetis\bootstrap4glyphicons\assets\GlyphiconAsset;
GlyphiconAsset::register($this);
?>```



]]>
0
[extension] execut/yii2-settings Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/execut/yii2-settings https://www.yiiframework.com/extension/execut/yii2-settings eXeCUT eXeCUT

yii2-settings

Yii2 module for application configuring via administrate crud settings. The module can used both separately and as part of the execut/yii2-cms.

Installation

The preferred way to install this extension is through composer.

Install

Either run

$ php composer.phar require execut/yii2-settings

or add

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

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

Configuration

Add module bootstrap to backend application config: `php

'bootstrap' => [
...
    'settings' => [
        'class' => \execut\settings\bootstrap\Backend::class,
    ],
...
],

Add module bootstrap to common application config:
```php
    'bootstrap' => [
    ...
        'settings' => [
            'class' => \execut\settings\bootstrap\Common::class,
        ],
    ...
    ],

Add module bootstrap inside console application config: `php

'bootstrap' => [
...
    'settings' => [
        'class' => \execut\settings\bootstrap\Console::class,
    ],
...
],

Apply migrations via yii command:

./yii migrate/up --interactive=0 `

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

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(); echo Breadcrumbs::widget([

'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],

]); ` For more information about execut/yii2-navigation module, please read it documentation

Usage
Settings administration

Settings list

Section contains the following columns:

NameDescription
Id DB identifier
Name Setting description
Key Key for getting setting value from code
Value Setting value

For example, we want to manage the site name. To do this, add a setting with the key site_name:

Setting edit

On the website we can display this parameter using this line: `php <?= \yii::$app->settings->get('company-name') ?> `

Increase functionality

For adding more functionality inside module you can create plugin based on interface execut\settings\Plugin and connect it to module via common bootstrap depends config: `php

'bootstrap' => [
...
    'settings' => [
        'class' => \execut\settings\bootstrap\Common::class,
        'depends' => [
            'modules' => [
                'settings' => [
                    'plugins' => [
                        'own-plugin' => [
                            'class' => $pluginClass // You plugin class here
                        ],
                    ],
                ]
            ],
        ],
    ],
...
],


He has next methods:

Method | Description
-------|------------
getSettingsCrudFieldsPlugins | Getting list of crud fields. Follow to component execut/yii2-crud-fields documentation for more [information about crud fields](https://github.com/execut/yii2-crud-fields).
checkHasAccessToSetting | Check user access to setting
]]>
0
[extension] execut/yii2-loading-overlay Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/execut/yii2-loading-overlay https://www.yiiframework.com/extension/execut/yii2-loading-overlay eXeCUT eXeCUT

Yii2 loading overlay widget

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

Yii2 wrapper for jquery loading overlay javascript widget from jgerigmeyer

Widget page

Installation

The preferred way to install this extension is through composer.

Either run

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

or add

"execut/yii2-loading-overlay": "dev-master"

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

Usage

For usage javascript widget inside you javascript code simple register `\execut\loadingOverlay\LoadingOverlayAsset` on you page.

For javascript usage please, refer to widget documentation page

Example

Copy this code to app view file: `html Toggle overlay

<?php $this->registerJs(<<<JS jQuery(function ($) { var target = $('#target'); $('.toggle-loading').click(function () {
if (target.hasClass('loading')) {
  target.loadingOverlay('remove');
} else {
  target.loadingOverlay();
};

}); }); JS ); \execut\loadingOverlay\LoadingOverlayAsset::register($this); `

License

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

]]>
0
[extension] execut/yii2-composer-release-command Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/execut/yii2-composer-release-command https://www.yiiframework.com/extension/execut/yii2-composer-release-command eXeCUT eXeCUT

Yii2 command for fast releasing and versioning composer packages

  1. Installation
  2. Configuration example
  3. Usage
  4. License

This command can publish and calculate the version of the set of packages in your project at a one fast and simple run: `./yii release`

Installation

The preferred way to install this extension is through composer.

Either run

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

or add

"execut/yii2-composer-release-command": "dev-master"

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

Configuration example

Add to console config folowing rules: `php [

'controllerMap' => [
    'release' => [
        'class' => \execut\release\ReleaseController::class,
        'vendorFolder' => 'execut', // Folder(s) inside @vendor for releasing, supported list 
    ],
],

]; `

Usage

All released packages must be installed with .git via --prefer-source composer flag (see composer documentation). Fast way for adding git inside installed packages:

  1. Delete them
  2. Run `composer install --prefer-source` for fresh install of package with git server

After running console command `./yii release` the happen next operations:

  1. Each folder with .git, specified inside configuration file checked for new changes
  2. If has changes happen the next operations:
    1. git add .
    2. git pull origin master
    3. git checkout master
    4. git pull
    5. git commit with message passed via console argument --message(m) or entered inside console dialog
    6. git push
    7. Calculating and tagging new version by next rule: (major version).(minor version).(path version). Console argument --level(l) set level of calculation next version. 0 - major, 1 - minor, 2 - path (default)
    8. git push --tags

Console arguments:

Name Short name Description Default value
--message -m Commit message
--level -l level of calculated next version. 0 - major, 1 - minor, 2 - path 2

License

yii2-composer-release-command is released under the Apache License Version 2.0. See the bundled LICENSE.md for details.

]]>
0
[extension] vxm/yii2-async Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/vxm/yii2-async https://www.yiiframework.com/extension/vxm/yii2-async vuongminh1380 vuongminh1380

Yii2 Async

  1. About it
  2. Requirements
  3. Installation
  4. Usage

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

About it

An extension provide an easy way to run code asynchronous and parallel base on spatie/async wrapper for Yii2 application.

Requirements

Installation

Require Yii2 Async using Composer:

composer require vxm/yii2-async

Usage

Configure

Add the component to your application configure file:

[
    'components' => [
        'async' => [
            'class' => 'vxm\async\Async',
            'appConfigFile' => '@app/config/async.php' // optional when you need to use yii feature in async process.
        ]
    ]
]

Because async code run in difference process you need to setup yii environment to use components via property appConfigFile. Example of an async app config file:

define('YII_ENV', 'dev');
define('YII_DEBUG', true);

return [
    'id' => 'async-app',
    'basePath' => __DIR__,
    'runtimePath' => __DIR__ . '/runtime',
    'aliases' => [
        '@frontend' => dirname(__DIR__, 2) . '/frontend',
        '@backend' => dirname(__DIR__, 2) . '/backend'
    ]
];

Make sure all of your aliases define in it to support an autoload.

Run async code

After add it to application components, now you can run an async code:


Yii::$app->async->run(function() {
    
    Yii::$app->mailer->compose('mail')->send();
});

Async events

When creating asynchronous processes, you can add the following event hooks on a process in the second parameter.


Yii::$app->async->run(function() {

    if (rand(1, 2) === 1) {
    
        throw new \YourException;
    }
    
    return 123;
}, [
    'success' => function ($result) {
    
        echo $result; // 123
        
    },
    'catch' => function (\YourException $exception) {
        
        // catch only \YourException
        
    },
    'error' => function() {
    
        // catch all exceptions
        
    },
    'timeout' => function() {
    
        // call when task timeout default's 15s
        
    }
]);

Wait process

Sometime you need to wait a code executed, just call wait() after run():


Yii::$app->async->run(function() {
    
    sleep(10);
})->wait(); // sleep 10s

Or you can wait multi tasks executed:


Yii::$app->async->run(function() {
    
    sleep(5);
});

Yii::$app->async->run(function() {
    
    sleep(10);
});

Yii::$app->async->wait(); // sleep 10s not 15s because it's run on multi processes

Working with task

Besides using closures, you can also work with a Task. A Task is useful in situations where you need more setup work in the child process.

The Task class makes this easier to do.


use vxm\async\Task;

class MyTask extends Task
{

    public $productId;
    

    public function run()
    {
        // Do the real work here.
       
    }
}

// Do task async use like an anonymous above.

Yii::$app->async->run(new MyTask([
    'productId' => 123

]));

]]>
0
[extension] execut/yii2-cms Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/execut/yii2-cms https://www.yiiframework.com/extension/execut/yii2-cms eXeCUT eXeCUT

eXeCUT Yii2 CMS

  1. Installation
  2. Usage

Warning! Beta version. Please add tasks here if you find errors. I will try to fix them quickly

CMS, based on Yii2 modular system. All system modules are standalone Yii2 modules and can be used separately from CMS.

List of system features and modules:

Feature Module Expanded by modules Development status
Aliases for urls of records like page and logging their changes execut/yii2-alias yii2-files, yii2-images, yii2-news, yii2-pages, yii2-shops Complete
Goods execut/yii2-goods yii2-files, yii2-pages Complete
Files execut/yii2-files yii2-alias, yii2-goods, yii2-images, yii2-pages, yii2-seo Complete
Images execut/yii2-images yii2-files Complete
Menus execut/yii2-menu yii2-pages Complete
Site pages content execut/yii2-pages yii2-alias, yii2-files, yii2-goods, yii2-menu, yii2-seo, yii2-sitemap, yii2-settings Complete
SEO metadata execut/yii2-seo yii2-files, yii2-pages Complete
Site settings execut/yii2-settings yii2-rbac Complete
Robots.txt generation execut/yii2-robots-txt - Complete
Sitemap generation execut/yii2-sitemap yii2-pages, yii2-news, yii2-shops In progress
Site settings execut/yii2-settings yii2-pages, yii2-news, yii2-shops Complete
Information pages about chain of stores execut/yii2-shops yii2-seo In progress
Blog, articles and news execut/yii2-news yii2-seo In progress
Users manager execut/yii2-users yii2-rbac In progress
RBAC manager execut/yii2-rbac yii2-users In progress
Feedback execut/yii2-feedback yii2-users, yii2-antispam, yii2-settings In progress
Antispam protection execut/yii2-antispam - In progress
Orders execut/yii2-orders yii2-goods New
Basket execut/yii2-basket yii2-orders, yii2-antispam New

Supported databases:

  • PostgreSQL
  • MySQL

Installation

  • If you do not have yii2 app advanced, install it via instructions here
  • Register user via standard controller /site/signup and activate it by setting status to 10 inside database.
  • Require CMS via composer by running `composer require execut/yii2-cms`
  • Add bootstrapping of CMS inside your applications configs `(console|frontend|backend)/config/main.php`:
    return [
      ...
      'bootstrap' => [
          ...
          \execut\cms\bootstrap\Console::class, //for console application
          \execut\cms\bootstrap\Frontend::class, //for frontend application
          \execut\cms\bootstrap\Backend::class, //for backend application
      ],
      ...
    ];
    
  • Set CMS language inside `backend/config/main.php`. Now only supported `ru`:
    return [
      ...
      'language' => 'ru',
      ...
    ];
    
  • Apply migrations by running:
    ./yii migrate/up --interactive 0
    
  • Remove or rename unused files `frontend/web/robots.txtandfrontend/controllers/SiteController.php`
  • Congratulations! CMS installed

Usage

After installation CMS has 3 applications: frontend - here site for users, backend - administration panel and console.

For open CMS admin panel enter backend url. Here you can manage your site. Instructions for working with sections are on the page of the module responsible for a specific section. Links to pages listed in the table above.

Demo

]]>
0
[extension] slavkovrn/yii2-dtreemenu Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/slavkovrn/yii2-dtreemenu https://www.yiiframework.com/extension/slavkovrn/yii2-dtreemenu Viacheslav Kolesnikov Viacheslav Kolesnikov

TreeView Menu widget for Yii2 Framework

  1. Installation
  2. Usage

The extension uses dTree 2.05 and makes treeview menu from php array of structure defined.

DtreeMenu PHP Array generator.

Dtree Menu

Installation

The preferred way to install this extension is through composer.

Either run:

composer require slavkovrn/yii2-dtreemenu

or add

"slavkovrn/yii2-dtreemenu": "*"

to the require section of your composer.json file.

Usage

Set link to extension in your view:

<?php

use slavkovrn\dtreemenu\DtreeMenuWidget;

$tree=[
    0 => [
            'name' => 'Menu0 name',
            'description' => 'Tool tip description for Menu0',
            'href' => '/link_when_DblClicked.html',
            'children' => [
                1 => [
                        'name' => 'SubMenu1 name',
                        'description' => 'Tool tip description for SubMenu1',
                        'href' => '/link_when_DblClicked.html',
                        'children' => [
                            2 => [
                                    'name' => 'SubSubMenu2 name',
                                    'description' => 'Tool tip description for SubSubMenu2',
                                    'href' => '/link_when_DblClicked.html',
                                    'children' => [
                                         3 => [
                                                'name' => 'SubSubSubMenu3 name',
                                                'description' => 'Tool tip description for SubSubSubMenu3',
                                                'href' => '/link_when_DblClicked.html',
                                            ],
                                        4 => [
                                                'name' => 'SubSubSubMenu4 name',
                                                'description' => 'Tool tip description for SubSubSubMenu4',
                                                'href' => '/link_when_DblClicked.html',
                                            ],
                                   ]
                                ],
                            5 => [
                                    'name' => 'SubSubMenu5 name',
                                    'description' => 'Tool tip description for SubSubMenu5',
                                    'href' => '/link_when_DblClicked.html',
                                ],
                            6 => [
                                    'name' => 'SubSubMenu6 name',
                                    'description' => 'Tool tip description for SubSubMenu6',
                                    'href' => '/link_when_DblClicked.html',
                                ],
                        ]
                    ],
                7 => [
                        'name' => 'SubMenu7 name',
                        'description' => 'Tool tip description for SubMenu7',
                        'href' => '/link_when_DblClicked.html',
                    ],
                8 => [
                        'name' => 'SubMenu8 name',
                        'description' => 'Tool tip description for SubMenu8',
                        'href' => '/link_when_DblClicked.html',
                    ],
           ]
        ],
    9 => [
            'name' => 'Menu9 name',
            'description' => 'Tool tip description for Menu9',
            'href' => '/link_when_DblClicked.html',
        ],
    10 => [
            'name' => 'Menu10 name',
            'description' => 'Tool tip description for Menu10',
            'href' => '/link_when_DblClicked.html',
        ],
];
?>

<?= DtreeMenuWidget::widget([
	'id' => 'dtree',
	'class' => 'dtree',
	'tree' => $tree,
	'target' => '_blank',
	'useSelection' => false,
	'useLines' => true,
	'useIcons' => true,
	'useCookies' => true,
	'useStatusText' => false,
	'closeSameLevel' => true,
]) ?>

write comments to admin

]]>
0
[extension] vxm/yii2-mobile-first Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/vxm/yii2-mobile-first https://www.yiiframework.com/extension/vxm/yii2-mobile-first vuongminh1380 vuongminh1380

Yii2 Mobile First

  1. About it
  2. Requirements
  3. Installation
  4. Usage

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

About it

An extension provide an easy way to implementing mobile-first principle base on Mobile Detect wrapper for Yii2 application.

Requirements

Installation

Require Yii2 Mobile First using Composer:

composer require vxm/yii2-mobile-first

Usage

This extension give you two features:

  • Adaptive Filter support you redirect user to mobile site when detected user using mobile or tablet.
  • View Render Behavior support you rendering view file by device type (mobile, tablet, iOs, android...).
Adaptive Filter

To use this filter you just add it to an application config file:

[
    'id' => 'test',
    'basePath' => __DIR__,
    'vendorPath' => dirname(__DIR__) . '/vendor',
    'components' => [

    ],
    'as adaptiveFilter' => [
        'class' => 'vxm\mobileFirst\AdaptiveFilter',
        'redirectUrl' => ['https://m.yoursite.com', 'getParam1' => '1']
    ]
]

If user go to your site with url: yoursite.com/product?sort=price and you want to keep /product?sort=price url path when redirect user to mobile site: m.yoursite.com/product?sort=price you just config:

[
    'id' => 'test',
    'basePath' => __DIR__,
    'vendorPath' => dirname(__DIR__) . '/vendor',
    'components' => [

    ],
    'as adaptiveFilter' => [
        'class' => 'vxm\mobileFirst\AdaptiveFilter',
        'redirectUrl' => ['https://m.yoursite.com', 'getParam1' => '1'],
        'keepUrlPath' => true
    ]
]
View Render Behavior

It is a way to replace a set of views with another by user device without the need of touching the original view rendering code. You can use it to systematically change the look and feel of an application depend on user device. For example, when call $this->render('about') in SiteController, you will be rendering the view file @app/views/site/about.php, if user use mobile device, the view file @app/views/site/mobile/about.php will be rendered, instead.

To use it, you need to attach it to the view application component in configure file:

[
    'id' => 'test',
    'basePath' => __DIR__,
    'vendorPath' => dirname(__DIR__) . '/vendor',
    'components' => [
        'view' => [
            'as mobileFirst' => [
                'class' => 'vxm\mobileFirst\ViewRenderBehavior',
                'dirMap' => [
                    'mobile' => 'mobile',
                    'tablet' => 'tablet'
                ]
            ]
        ]
    ]
]

The dirMap property governs how view files should be replaced by user device. It takes an array of key-value pairs, where the keys are the device types and the values are the corresponding view sub-directory. The replacement is based on user device: if user device match with any key in the dirMap array, a view path will be added with the corresponding sub-directory value. Using the above configuration example, when user using mobile device because it match the key mobile, a view path will be added mobile look like @app/views/site/mobile/about.php. Of course you can change the value or add more cases:

[
    'id' => 'test',
    'basePath' => __DIR__,
    'vendorPath' => dirname(__DIR__) . '/vendor',
    'components' => [
        'view' => [
            'as mobileFirst' => [
                'class' => 'vxm\mobileFirst\ViewRenderBehavior',
                'dirMap' => [
                    'mobile' => 'mobile-tablet',
                    'tablet' => 'mobile-tablet',
                    'ios' => 'ios',
                    'android' => 'android'
                ]
            ]
        ]
    ]
]

The above configuration if user using mobile or tablet device, the view path will be added mobile-tablet.

]]>
0
[news] Mehdi Achour joining core team Wed, 01 May 2019 12:45:49 +0000 https://www.yiiframework.com/news/219/mehdi-achour-joining-core-team https://www.yiiframework.com/news/219/mehdi-achour-joining-core-team samdark samdark

Mehdi Achour, @machour joined Yii team. He uses Yii since 2012 for all his PHP projects, ranging from simple web sites to complex rental platforms.

Mehdi is going to give back to the project as much as it gave him, by helping with the Yii 3 development and deliver an awesome new version of the framework.

]]>
0
[extension] zhuravljov/yii2-pagination Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/zhuravljov/yii2-pagination https://www.yiiframework.com/extension/zhuravljov/yii2-pagination KiTE KiTE

Yii2 Pagination Widgets

  1. Installation
  2. Usage

Latest Stable Version Total Downloads

Installation

The preferred way to install the extension is through composer. Add to the require section of your composer.json file:

"zhuravljov/yii2-paginations": "~1.0"

Usage

Way to add page size widget to each GridView and ListView of an application using DI container definition:

<?php
return [
    'container' => [
        'definitions' => [
            \yii\widgets\LinkPager::class => \zhuravljov\yii\pagination\LinkPager::class,
        ],
    ],
];

Advanced container configuration of LinkPager and LinkSizer widgets:

<?php
return [
    'container' => [
        'definitions' => [
            \yii\widgets\LinkPager::class => \zhuravljov\yii\pagination\LinkPager::class,
            \zhuravljov\yii\pagination\LinkPager::class => [
                'maxButtonCount' => 5,
            ],
            \zhuravljov\yii\pagination\LinkSizer::class => [
                'sizes' => [5, 10, 20, 50, 100],
            ],
            \yii\data\Pagination::class => [
                'defaultPageSize' => 10,
                'pageSizeLimit' => [1, 100],
            ],
        ],
    ],
];

There is StoredPagination to store page size that was selected before by user. DI container definition looks like:

<?php
return [
    'container' => [
        'definitions' => [
            \yii\data\Pagination::class => \zhuravljov\yii\pagination\StoredPagination::class,
        ],
    ],
];

There is StoredSort to store selected sorting. DI container definition looks like:

<?php
return [
    'container' => [
        'definitions' => [
            \yii\data\Sort::class => \zhuravljov\yii\pagination\StoredSort::class,
        ],
    ],
];
]]>
0
[news] Bootstrap 4 extension version 2.0.2 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/218/bootstrap-4-extension-version-2-0-2-released https://www.yiiframework.com/news/218/bootstrap-4-extension-version-2-0-2-released samdark samdark

We are very pleased to announce the release of Bootstrap 4 extension version 2.0.2. In this release progress widget was fixed to work properly with Russian locale and Pagination widget was added.

See CHANGELOG for details.

]]>
0
[news] Debug extension 2.1.3 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/217/debug-extension-2-1-3-released https://www.yiiframework.com/news/217/debug-extension-2-1-3-released samdark samdark

We are very pleased to announce the release of Debug extension version 2.1.3 that adds an ability to customize var dumper in the DumpPanel via varDumpCallback.

See the CHANGELOG for details.

]]>
0
[news] HTTP client extension 2.0.10 released Tue, 30 Apr 2019 15:11:00 +0000 https://www.yiiframework.com/news/216/http-client-extension-2-0-10-released https://www.yiiframework.com/news/216/http-client-extension-2-0-10-released samdark samdark

We are very pleased to announce the release of HTTP client extension version 2.0.10.

This release adds an ability to set multiple request parameters with the same name for multipart requests.

See the CHANGELOG for details.

]]>
0
[extension] sjaakp/yii2-loadmore Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/sjaakp/yii2-loadmore https://www.yiiframework.com/extension/sjaakp/yii2-loadmore sjaakp sjaakp

yii2-loadmore

  1. Installation
  2. Using LoadMorePager
  3. Options
  4. Refinement 1: summary
  5. Refinement 2: efficiency
Load More button for Yii2

LoadMorePager, the main part of the yii2-loadmore package, is a widget that can be used as a pager for a GridView or a ListView of the Yii 2.0 PHP Framework. In stead of the usual LinkPager, a 'Load More' button is rendered. Clicking it, adds a bunch of new items to the list. With every click, the list grows until there are no more items to show.

A demonstration of LoadMorePager is here.

Installation

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

"sjaakp/yii2-loadmore": "*"

or run:

composer require sjaakp/yii2-loadmore

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

Using LoadMorePager

Use LoadMorePager in a GridView just by setting the latter's pager property to a configuration array with the former's class, like:

<?php
    use yii\grid\GridView;
    use sjaakp\loadmore\LoadMorePager;
?>
...
<?= GridView::widget([
    'dataProvider' => ...
    'pager' => [
        'class' => LoadMorePager::class
    ],
    // ...other GridView options, like 'columns'... 
])  ?>
...
    

That's all that's needed for basic functionality. The Load More button will appear as a standard link. In a ListView, set the pager property likewise.

Options

LoadMorePager's options can be set like so:

<?php
    use yii\grid\GridView;
    use sjaakp\loadmore\LoadMorePager;
?>
...
<?= GridView::widget([
    'dataProvider' => ...
    'pager' => [
        'class' => LoadMorePager::class,
        'label' => 'Show more data'
    ], 
    // ...other GridView options, like 'columns'... 
])  ?>
...

LoadMorePager has three options:

label

string The text of the Load More button. Default: 'Load more'.

options

array The HTML options of the Load More button. Set this to something like [ 'class' => 'btn btn-secondary' ] to give the button the looks of a real button (assuming that you use Bootstrap). Default: [] (empty array).

indicator

string Optional. The CSS selector for the indicator element(s). While the list is waiting for new items, the indicator element(s) get the extra CSS class 'show'. Great for showing a 'spinner' after the Load More button is clicked. Default: null.

Refinement 1: summary

In its basic setup, LoadMorePager will not update the GridView's or ListView's summary, if present. To correct that, wrap the {end} token in the list's summary setting with a <span> having the class 'summary-end'. For example:

<?php
    use yii\grid\GridView;
    use sjaakp\loadmore\LoadMorePager;
?>
...
<?= GridView::widget([
    'dataProvider' => ...
    'pager' => [
        'class' => LoadMorePager::class,
        'label' => 'Show more data'
    ], 
    'summary' => 'Showing {begin}-<span class="summary-end">{end}</span> of {totalCount} items',
    // ...other GridView options, like 'columns'... 
])  ?>
...

Refinement 2: efficiency

Clicking the Load More button sends an Ajax call to the server, which sends a complete page back to the browser. Only a small part is actuallly used. This works, but it could be made quite a bit more efficient by taking the following steps.

Put the list in a separate subview

In stead of the usual view file:

<?php
    /* loadmore.php */
    use yii\grid\GridView;
    use sjaakp\loadmore\LoadMorePager;
?>
// other stuff on the page
...
<?= GridView::widget(...) ?>
...
// more other stuff
...

Create two view files, one main view which renders a subview:

<?php
    /* loadmore.php */
?>
// other stuff on the page
...
<?= $this->render('_loadmore.php', [
    'dataProvider' => $dataProvider
]) ?>
...
// more other stuff
...
 

The subview:

<?php
    /* _loadmore.php */
    use yii\grid\GridView;
    use sjaakp\loadmore\LoadMorePager;
?>
// no other stuff!
<?= GridView::widget(...) ?>

Modify the action function in the controller

Change the usual:

public function actionLoadmore()    {
    $dataProvider = ...;

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

into:

public function actionLoadmore()    {
    $dataProvider = ...;

    if (Yii::$app->request->isAjax) {
        return $this->renderAjax('_loadmore', [
            'dataProvider' => $dataProvider,
        ]);
    }

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

This makes the server only render the subview if an Ajax call is made by the Load More button.

How do I change the number of returned items?

Do this by modifying the pagination value of the list's dataProvider, like:

 $dataProvider = new ActiveDataProvider([
     'query' => ... ,
     'pagination' => [
         'pageSize' => 12
     ]
 ]);
]]>
0
[extension] raoul2000/yii2-bootswatch4-asset Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/raoul2000/yii2-bootswatch4-asset https://www.yiiframework.com/extension/raoul2000/yii2-bootswatch4-asset Raoul Raoul

yii2-bootswatch4-asset

  1. Installation
  2. Usage
  3. About Versioning
  4. License

Asset bunlde around the Bootswatch Theme Suite based on bootstrap 4.

Latest Stable Version Total Downloads

If you are using Bootstrap 3, please refer to the dedicated extension yii2-bootswatch-asset.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist raoul2000/yii2-bootswatch4-asset "*"

or add

"raoul2000/yii2-bootswatch4-asset": "*"

to the require section of your composer.json file.

Usage

Note that this asset bundle does NOT include Bootstrap 4 files, but only the Bootswatch CSS files dedicated to overload Bootstrap default theme. To use the Bootstrap 4 files with your Yii2 application, check the yii2-bootstrap4 extension.

To use a bootswatch theme in your Yii2 application add the BootswatchAsset bundle to your main AppAsset bundle:


// ./assets/AppAsset.php

class AppAsset extends AssetBundle
{
    public $basePath = '@webroot';
    public $baseUrl = '@web';
    public $css = [
        'css/site.css',
    ];
    public $js = [
    ];
    public $depends = [
        'yii\web\YiiAsset',
    	'raoul2000\bootswatch4\BootswatchAsset',
    ];
}
?>

Then at some point you must select the theme name you want to use. In the example below, the theme materia is set in the main layout file.


// ./views/layouts/main.php

raoul2000\bootswatch4\BootswatchAsset::$theme = 'materia';
AppAsset::register($this);

About Versioning

By convention this extension is using the same version number as the project thomaspark/bootswatch it depends on. Consequently, the first version of this extension is 4.3.1.

License

yii2-bootswatch4-asset is released under the BSD 3-Clause License. See the bundled LICENSE.md for details.

]]>
0
[extension] vasadibt/yii2-cron Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/vasadibt/yii2-cron https://www.yiiframework.com/extension/vasadibt/yii2-cron vasadibt vasadibt

Yii2 Cron job Manager

Create Cron jobs from browser, and look that run logs

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist vasadibt/yii2-cron "*"

or add

"vasadibt/yii2-cron": "*"

to the require section of your composer.json file.

Migration

Run the following command in Terminal for database migration:

yii migrate/up --migrationPath=@vasadibt/cron/migrations

Or use the namespaced migration (requires at least Yii 2.0.10):

// Add namespace to console config:
'controllerMap' => [
    'migrate' => [
        'class' => 'yii\console\controllers\MigrateController',
        'migrationPath' => [
            '@vasadibt/cron/migrations',
        ],
    ],
],

Then run: yii migrate/up

Web Application Config

Turning on the Cron Job Manager Module in the web application:

Simple example:

'modules' => [
    'cron' => [
        'class' => 'vasadibt\cron\Module',
    ],
],
Console Application Config

Turning on the Cron Job Manager Module in the console application:

Simple example:

'modules' => [
    'cron' => [
        'class' => 'vasadibt\cron\Module',
    ],
],
Schedule Config

Set the server schedule to run the following command

On Linux:

Add to the crontab with the user who you want to run the script (possibly not root) with the crontab -e command or by editing the /etc/crontab file

* * * * * <your-application-folder>/yii cron/cron/run 2>&1

On Windows:

Open the task scheduler and create a new task

]]>
0
[extension] sjaakp/yii2-collapse Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/sjaakp/yii2-collapse https://www.yiiframework.com/extension/sjaakp/yii2-collapse sjaakp sjaakp

Yii2-collapse

  1. Installation
  2. Using the Collapse widget
  3. Using the CollapseGroup widget
  4. Using the Accordion widget

Yii2-collapse offers three widgets for the Yii 2.0 PHP Framework:

  • Collapse renders a Bootstrap Collapse element with a toggle link and a collapsible panel;

  • CollapseGroup two or more Collapses of which only one can be open;

  • Accordion renders a Bootstrap Accordion element with several panels of which only one can be open. An Accordion essentially is a kind of CollapseGroup. The difference is that the Collapse's are all direct children of the surrounding element.

All three widgets can be used with either Bootstrap 3.x or Bootstrap 4.x.

A demonstration of the widgets is here.

Installation

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

"sjaakp/yii2-collapse": "*"

or run:

composer require sjaakp/yii2-collapse

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

Using the Collapse widget

Using the Collapse widget in an Yii2 view file can be as simple as:

<?php
use sjaakp\collapse\Collapse;
?>
    ...
    <?php Collapse::begin('Details') ?>
        <h4>Some more details</h4>
        <p>The first detail... </p>
    <?php Collapse::end() ?>
    ... 

The HTML between begin() and end() can be as complicated as you like.

Instead of initializing Collapse with the label text, it can also be initialized with an array of several options, like:

<?php
use sjaakp\collapse\Collapse;
?>
    ...
    <?php Collapse::begin([
        'label' => 'Details',
        'options' => [ 'class' => 'bg-info' ], // give the panel an extra class
        'open' => true      // initially open the panel
    ]) ?>
        <h4>Some more details</h4>
        <p>The first detail... </p>
    <?php Collapse::end() ?>
    ... 

Using the CollapseGroup widget

The CollapseGroup widget can be used like:

<?php
use sjaakp\collapse\CollapseGroup;
?>
    ...
    <?php CollapseGroup::begin([/* options */]) ?>
    ...
    <?php CollapseGroup::beginCollapse('Details) ?>
        <h4>Some details</h4>
        <p>The first detail... </p>
    <?php CollapseGroup::endCollapse() ?>
    ...
    <?php CollapseGroup::beginCollapse('More details) ?>
        <h4>Some more details</h4>
        <p>The first detail... </p>
    <?php CollapseGroup::endCollapse() ?>
    ...
    <?php CollapseGroup::end() ?>
    ... 

beginCollapse() can also be initiallized with an array of Collapse options.

Using the Accordion widget

Use the Accordion widget as follows:

<?php
use sjaakp\collapse\Accordion;
?>
    ...
    <?php Accordion::begin('Details') ?>
        <h4>Some details</h4>
        <p>The first detail... </p>
    <?php Accordion::next('More details') ?>
        <h4>Some more details</h4>
        <p>The tenth detail... </p>
    <?php Accordion::next('Even more details') ?>
        <h4>Even some more details</h4>
        <p>The twentieth detail... </p>
    <?php Accordion::end() ?>
    ... 

As with Collapse, Accordion can also be initialized with an array of several options.

Common options

Collapse and Accordion (but not CollapseGroup) both have the following options:

  • label string The text of the (first) label.
  • encode bool Whether to HTML-encode the label(s). Default: true.
  • open bool Whether the (first) panel is initially open. Default: false (Collapse), true (Accordion).
  • toggleOptions array HTML options for the toggle link(s). Default: ['class' => 'btn-collapse']. This class styles the toggle link with a triangle.
Collapse option
  • options array HTML options for the panel. 'tag' is a special option, defining the HTML-tag. If it is not set, the HTML-tag is 'div'
CollapseGroup option
  • options array HTML options for the surrounding element. 'tag' is a special option, defining the HTML-tag. If it is not set, the HTML-tag is 'div'
Accordion options
  • options array HTML options for the surrounding element. 'tag' is a special option, defining the HTML-tag. If it is not set, the HTML-tag is 'div'

  • panelOptions array HTML options for the panels.

]]>
0
[news] Bootstrap extension version 2.0.10 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/215/bootstrap-extension-version-2-0-10-released https://www.yiiframework.com/news/215/bootstrap-extension-version-2-0-10-released samdark samdark

We are very pleased to announce the release of Bootstrap extension version 2.0.10.

See the CHANGELOG for details.

]]>
0
[news] Debug extension 2.1.2 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/214/debug-extension-2-1-2-released https://www.yiiframework.com/news/214/debug-extension-2-1-2-released samdark samdark

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

See the CHANGELOG for details.

]]>
0
[news] Yii 2.0.18 Tue, 23 Apr 2019 14:04:30 +0000 https://www.yiiframework.com/news/213/yii-2-0-18 https://www.yiiframework.com/news/213/yii-2-0-18 samdark samdark

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

Version 2.0.18 is a minor release of Yii 2.0 which fixes some bugs.

No known changes that could affect existing applications were made.

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] Auth Client extension 2.2.1 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/212/auth-client-extension-2-2-1-released https://www.yiiframework.com/news/212/auth-client-extension-2-2-1-released samdark samdark

We are very pleased to announce the release of Auth Client extension version 2.2.1 fixing a bug when OAuthToken is incorrectly instantiated if configuration array has incorrect order.

See the CHANGELOG for details.

]]>
0
[news] HTTP client extension 2.0.9 released Tue, 23 Apr 2019 11:21:30 +0000 https://www.yiiframework.com/news/211/http-client-extension-2-0-9-released https://www.yiiframework.com/news/211/http-client-extension-2-0-9-released samdark samdark

We are very pleased to announce the release of HTTP client extension version 2.0.9.

This release includes work made by Alexander Kartavenko, @alexkart. There are two bugs fixed:

  • Fixed type error in StreamTransport when $http_response_header = null
  • Added Content-Length: 0 header when sending request with empty body

And enhancements made in files uploading and downloading with CURL transport reducing memory usage significantly. Details could be found in the guide.

See the CHANGELOG for details.

]]>
0
[extension] sjaakp/yii2-polyglot Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/sjaakp/yii2-polyglot https://www.yiiframework.com/extension/sjaakp/yii2-polyglot sjaakp sjaakp

yii2-polyglot

  1. Installation
  2. Using yii2-polyglot
  3. Bootstrap
  4. Widgets
Ultralight language chooser for Yii2

yii2-polyglot is an application component plus two widgets with flag buttons to choose the application language. It can be used in the Yii 2.0 PHP Framework.

yii2-polyglot was developed as an alternative to other language choosers, which in my opinion are often overly complex.

yii2-polyglot lets the user choose her favourite language by clicking on a flag button. The chosen language becomes the site's main language and is stored in a cookie.

A demonstration of Yii2-polyglot is here.

Installation

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

"sjaakp/yii2-polyglot": "*"

or run:

composer require sjaakp/yii2-polyglot

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

Using yii2-polyglot

First of all, Polyglot should be installed as an application component. This is done in the main configuration file, usually called web.php or main.php in the config directory. Add the following to the configuration array:

<?php

'components' => [
    // ... other components, like 'cache' and 'errorHandler'
    'polyglot' => [
        'class' => 'sjaakp\polyglot\Polyglot',
        'languages' => [
            'en-US' => 'English',
            'de-DE' => 'Deutsch',
            'fr-FR' => 'Français',
            // ... more languages
        ]
    ],
    // ... even more components
    

The language property is an array of the languages (or more correctly the locales) the web site supports. The keys of this array are the names of the locales in the ICU-format, just like Yii recommends. One of the keys should be the same as the language-property of the application.

The values of the array should be one of the following:

  • string human-readable name of the language. It appears as popup tooltip.

  • array with two keys:

    • "label" the human-readable language name;
    • "flag" the name of the flag that will be displayed, without the .png-part.

So, to show the Dutch language with the Belgian flag, we would use:

<php 

'components' => [
    // ... other components, like 'cache' and 'errorHandler'
    'polyglot' => [
        'class' => 'sjaakp\polyglot\Polyglot',
        'languages' => [
            'en-US' => 'English',
            // ... more languages
            'nl-NL' => [
                'label' => 'Nederlands',
                'flag' => 'be'
            ]
        ]
    ],
    // ... even more components

If the array value is just a string, Polyglot tries to devise the flag name itself.

A bunch of flags (247 of them) can be found in yii2-polyglot's assets/flags directory. They are made by famfamfam, by the way.

Bootstrap

Polyglot has to be bootstrapped. Do this by adding the following to the application configuration array:

<php

'bootstrap' => [
    'polyglot',
]

There probably already is a bootstrap property in your configuration file; just add 'polyglot' to it.

Polyglot options

Apart from the languages-settings, Polyglot has three more options:

  • useCookie bool If set to false, Polyglot will not store the preferred language in a cookie, but in the PHP session. As a consequence, the language choice will only persist for one session. Default: true.
  • cookieName string Also used as the session key if useCookie is false. Default: "polyglot".
  • cookieStamina integer Cookie expiration time in seconds. Default: 31536000 (one year).

Widgets

There are two widgets in the yii2-polyglot package. PolyglotButtons displays the language options as a row of flag buttons. PolyglotDropdown is a dropdown menu. Rendering a yii2-polyglot widget anywhere in a View is just a matter of:

<?php
use sjaakp\polyglot\PolyglotButtons;
?>
...
<?= PolyglotButtons::widget() ?>;
...

Or:

<?php
use sjaakp\polyglot\PolyglotDropdown;
?>
...
<?= PolyglotDropdown::widget() ?>;
...

As you will most likely want to have the Polyglot widget on all of your pages, the preferable place for a widget would be the layout viewfile (or one of the layout viewfiles).

Widget options

PolyglotButtons and PolyglotDropdown have the following options:

  • options array HTML options for the surrounding element. Default: [].
  • buttonOptions array HTML options for the individual flag buttons. Default: [].
  • toggleOptions array (PolyglotDropdown only) HTML options for the toggle button. Default: ['class' => 'nav-link'].
]]>
0
[extension] vxm/yii2-js-params Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/extension/vxm/yii2-js-params https://www.yiiframework.com/extension/vxm/yii2-js-params vuongminh1380 vuongminh1380

Yii2 JS Params

  1. About it
  2. Requirements
  3. Installation
  4. Usage

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

About it

An extension provide an easy way to passed variables from your server to the JavaScript in rendering process of Yii2 view component.

Requirements

Installation

Require Yii2 JS Prams using Composer:

composer require vxm/yii2-js-params

Usage

You can passed any variables you want when render view with addition jsParams element in view params:

use yii\web\Controller;

class TestController extends Controller
{

    public function actionTest()
    {
        return $this->render('test', [
            'jsParams' => [
                'test' => 'vxm'
            ]
        ]);
    }
}

And get this data on the frontend side from window.serverParams:

demo.png

Note: all variables will passed at View::POS_HEAD please make sure a definition ($this->head()) on your layout file.

Global params

Sometime you need to passed some params to all of view file, you can config it in your app config file:

'components' => [
    'view' => [
        'params' => [
            'jsParams' => ['test' => 'vxm']
        ]
    ]
]

Or config an anonymous function:

'components' => [
    'view' => [
        'params' => [
            'jsParams' => function() {
            
                return ['identity' => Yii::$app->user->identity->toArray()]
            }
        ]
    ]
]

Now use it on client side:

<script>

    console.log(window.serverParams.identity);

</script>
]]>
0
[news] Shorter release interval Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/210/shorter-release-interval https://www.yiiframework.com/news/210/shorter-release-interval samdark samdark

Since OpenCollective campaign is almost there allowing one core team member focusing on the project, we are ready to start tagging releases more. From now on every Tuesday is "release day" and overall policy is the following:

  • Extension releases are tagged every week if there are changes since last release.
  • Main framework package release is tagged about once a month if there are changes since last release.
]]>
0
[news] Auth Client extension 2.2.0 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/209/auth-client-extension-2-2-0-released https://www.yiiframework.com/news/209/auth-client-extension-2-2-0-released samdark samdark

We are very pleased to announce the release of Auth Client extension version 2.2.0 upgrading LinkedIn client to v2 and updating Google client image used in the auth widget.

See the CHANGELOG for details.

]]>
0
[news] HTTP client extension 2.0.8 released Tue, 16 Apr 2019 12:38:48 +0000 https://www.yiiframework.com/news/208/http-client-extension-2-0-8-released https://www.yiiframework.com/news/208/http-client-extension-2-0-8-released samdark samdark

We are very pleased to announce the release of HTTP client extension version 2.0.8.

  • Fixed a bug that Response::detectFormatByContent() falsely detected HTML as XML
  • Added extra check to Message::addData() to prevent error on trying to merge non-array
  • Made it possible configuring JsonParser to parse JSON as objects instead of arrays
  • Added MockTransport for test environments

See the CHANGELOG for details.

]]>
0
[news] Smarty extension 2.0.8 released Mon, 20 May 2019 00:29:47 +0000 https://www.yiiframework.com/news/207/smarty-extension-2-0-8-released https://www.yiiframework.com/news/207/smarty-extension-2-0-8-released samdark samdark

We are pleased to announce the release of Smarty extension version 2.0.8 that makes EVENT_BEFORE_RUN and EVENT_AFTER_RUN consistent with behavior of Widget::end() method.

]]>
0
[news] Yii 1.1.21 is released Tue, 02 Apr 2019 07:57:52 +0000 https://www.yiiframework.com/news/206/yii-1-1-21-is-released https://www.yiiframework.com/news/206/yii-1-1-21-is-released CeBe CeBe

We are very pleased to announce that Yii Framework version 1.1.21 is released. You can download it at yiiframework.com/download/.

This release is a release of Yii 1.1 that has reached maintenance mode and will, only receive necessary security fixes and fixes to adjust the code for compatibility with PHP 7 if they do not cause breaking changes. This allows you to keep your servers PHP version up to date in the environments where old Yii 1.1 applications are hosted and stay within the version ranges supported by the PHP team. Yii 1.1.21 is compatible with PHP 7.3 that, at the time of this writing, has an announced security support until December 6, 2021.

We recommend to use Yii 2.0 for new projects as well as introducing Yii 2.0 for developing new features in existing Yii 1.1 apps, as described in the Yii 2 guide. Upgrading a whole app to Yii 2.0 will, in most cases, result in a total rewrite so this option provides a way for upgrading step by step and allows you to keep old applications up to date even with low budget.

This release includes a few PHP 7 compatibility fixes and security improvements.

For the complete list of changes in this release, please see the change log. For upgrading, always make sure to read the upgrade instructions, however in this release there are no changes that require changes.

We would like to express our gratitude to all contributors who have spent their precious time helping improve Yii and made this release possible.

To comment on this news, you can do so in the related forum post.

]]>
0
[news] Debug extension 2.1.1 released Sat, 30 Mar 2019 20:39:11 +0000 https://www.yiiframework.com/news/205/debug-extension-2-1-1-released https://www.yiiframework.com/news/205/debug-extension-2-1-1-released samdark samdark

We are very pleased to announce the release of Debug extension version 2.1.1.

This version fixes some bugs including accessibility ones and adds multiple enhancements:

  • The toolbar is now resizeable. Default height could be set in the configuration.
  • Module pageTitle property added. It allows setting page title to be used.
  • The color contrast of the toolbar was improved.

See the CHANGELOG for details.

]]>
0
[news] Preparing Yii for the long run Fri, 29 Mar 2019 18:54:12 +0000 https://www.yiiframework.com/news/204/preparing-yii-for-the-long-run https://www.yiiframework.com/news/204/preparing-yii-for-the-long-run samdark samdark
  1. OpenCollective
  2. Goals
  3. Help us to move Yii forward

In order for such a big project as Yii to function properly, we need core contributors watching it constantly: making sure it goes in the right way, managing releases, making decisions. Time proved that while it is possible to do it having a full-time job, it is not as focused, fast and committing as needed.

Previously it was possible to support Yii in many ways: contributing code, participating in community activities, translating documentation. Donating to the project was not among them. The reasons for it were that:

  • We are not the best about paperwork.
  • The idea of how to spend money for the good of the project was very vague.

OpenCollective

An experiment of Alexander Makarov, @samdark, at Patreon proved that many community members find donating the best way to support Yii. The Patreon has drawbacks though. First of all, that's funding of Alexander's work. While the major part of it is Yii, that is not the same as the funding of Yii project overall. Also, Patreon does not provide any transparency regarding spending funds, and we want to make this part clear.

We have found that OpenCollective covers both drawbacks so decided to try it:

  • It allows for supporting the project financially.
  • It handles all the paperwork.
  • There is no need for legal entity (actually we have moved towards e.V. foundation significantly but that is still a huge amount of paperwork, and we would better spend time on what we are good at).
  • It is transparent.

Goals

The funding is collected to make it possible for core team members to work primarily on Yii with minimal or no amount of consulting jobs. The first person willing to try it is Alexander Makarov, @samdark, but others may join later.

Other than that, we may spend funds on our server infrastructure, development tools, design, marketing the framework and other activities and services that move Yii forward.

All that is to:

  • Support Yii 2 releasing new versions of both framework and official extensions.
  • Develop Yii 3 and further major versions. Here is the current roadmap of what is planned.

Help us to move Yii forward

Become Yii backer, starting at $1/month or become an official Yii sponsor, starting at $100/month. All backers and sponsors will be listed in a dedicated page (thanks to OpenCollective we would not forget anyone, they are providing a good API for it).

Become Yii backer or sponsor

The times ahead should be exciting for Yii. Let's make it together!

You may discuss this news on the forum.

]]>
0
[news] Yii 2.0.17 Fri, 22 Mar 2019 21:51:24 +0000 https://www.yiiframework.com/news/203/yii-2-0-17 https://www.yiiframework.com/news/203/yii-2-0-17 samdark samdark

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

Version 2.0.17 is a minor release of Yii 2.0 which contains some bugfixes including a security fix.

No known changes that could affect existing applications were made.

Both basic and advanced applications got fixes for recent Codeception, got updated debug and gii versions to version 2.1.0. Basic application now uses swiftmailer 2.1.0.

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.

Below we summarize some of the enhancements and changes that slipped into this release. A complete list of changes can be found in the CHANGELOG.

]]>
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 Mon, 20 May 2019 00:29:48 +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 Mon, 20 May 2019 00:29:48 +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
[wiki] Show raw SQL query Sat, 14 Jan 2017 19:53:41 +0000 https://www.yiiframework.com/wiki/857/show-raw-sql-query https://www.yiiframework.com/wiki/857/show-raw-sql-query darioo darioo

Here's a quick tip to dump the SQL for query.

$query = new Books::find()->where('author=2');
echo $query->createCommand()->sql;

or to get the SQL with all parameters included try:

$query->createCommand()->getRawSql()

Thanks to http://chris-backhouse.com/Yii2-Output-the-SQL-from-a-query-builder/1027

]]>
0