Live News for Yii Framework News, fresh extensions and wiki articles about Yii framework. Sat, 26 May 2018 15:09:05 +0000 Zend_Feed_Writer 2 (http://framework.zend.com) https://www.yiiframework.com/ [news] Queue extension 2.1.0 released Wed, 23 May 2018 21:35:19 +0000 https://www.yiiframework.com/news/176/queue-extension-2-1-0-released https://www.yiiframework.com/news/176/queue-extension-2-1-0-released samdark samdark

We are very pleased to announce the release of Queue extension version 2.1.0.

Additionally to fixing bugs, the version brings two major enhancements on board. First, there is now Amazon SQS queue support.

Second, cli\Queue:EVENT_WORKER_LOOP worker loop event was added. It is called on each iteration between requests to queue.

Other than that, there are slightly updated documentation and new Japanese translation.

Full changelog is available at GitHub.

]]>
0
[extension] chabibnr/ayom Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/chabibnr/ayom https://www.yiiframework.com/extension/chabibnr/ayom chabibnr chabibnr

993323

aYom Project Template (Admin-LTE Yii2 Oauth2 Mimin)

  1. Minimum Penggunaan
  2. Installasi
  3. Konfigurasi
  4. Jalankan Server
  5. DEFAULT USER & PASSWORD

Minimum Penggunaan

PHP 5.4

Installasi

Installasi dengan Composer

Jika kamu tidak memiliki Composer, kamu bisa menginstalnya dengan mengikuti tutorial di getcomposer.org.

Kamu bisa menginstal dengan menjalankan perintah berikut:

php composer.phar create-project --prefer-dist --stability=dev chabibnr/ayom ayom

ATAU ~~~ composer create-project --prefer-dist --stability=dev chabibnr/ayom ayom ~~~

Konfigurasi

Database

Ubah berkas config/db.php dengan data yang sesunguhnya, seperti:

return [
    'class' => 'yii\db\Connection',
    'dsn' => 'mysql:host=localhost;dbname=ayom',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
];

Selanjutnya import database `ayom.sql`

Jalankan Server

php yii serve

DEFAULT USER & PASSWORD

user : admin
pass : admin

user : member
pass : member
]]>
0
[extension] ozerich/yii2-rocketsms Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/ozerich/yii2-rocketsms https://www.yiiframework.com/extension/ozerich/yii2-rocketsms Ozerich Ozerich

yii2-rocketsms

  1. Installation
  2. Usage

Yii2 component for SMS provider RocketSMS.by

Installation

  1. The preferred way to install this extension is through composer.

    Either run

    php composer.phar require ozerich/yii2-rocketsms "*"
    

    or add

    "ozerich/yii2-rocketsms": "*"
    

    to the require section of your composer.json file.

  2. Add component configuration to your config.php

    'components' => [
        'sms' => [
            'class' => 'blakit\rocketsms\RocketSms',
            'login' => 'your_login',
            'password' => 'your_password'
        ]
    ]

Usage

Send SMS:

try {
    $response = \Yii::$app->sms->send('+375296000000', 'Test Message');
    echo 'SMS sent, message ID is ' . $response->getMessageId();
} catch (ErrorResponseException $exception) {
    echo 'Error sending SMS: ' . $exception->getError();
} catch (InvalidCredentialsException $exception) {
    echo 'RocketSMS credentials are invalid';
}

Check Balance:

try {
    $response = \Yii::$app->sms->balance();
    echo 'Your balance: ' . $response->getBalance() . 'BYN, ' . $response->getCredits() . ' SMS';
} catch (InvalidCredentialsException $exception) {
    echo 'RocketSMS credentials are invalid';
}

Get message status:

try {
    $response = \Yii::$app->sms->status('MESSAGE_ID');
    echo 'Message status: ' . $response->getStatus();
} catch (ErrorResponseException $exception) {
    echo 'Message not found';
} catch (InvalidCredentialsException $exception) {
    echo 'RocketSMS credentials are invalid';
}
]]>
0
[extension] mubat/yii2-sitemap-generator Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/mubat/yii2-sitemap-generator https://www.yiiframework.com/extension/mubat/yii2-sitemap-generator mubat mubat

yii2-sitemap-generator

Simple widget for Yii2 framework to generate sitemap.

Support XML format generation.

Support multi language.

Installation

Composer

The preferred way to install this extension is through Composer.

Either run `php composer require mubat/yii2-sitemap-generator`

or add `"mubat/yii2-sitemap-generator" : "~1.0"to the require section of yourcomposer.json`

Widget contains 2 models:

  1. Sitemap - base model. It contains SitemapElement array and methods to generate XML. If $languages array published, model will generate 'alternate' links.
  2. SitemapElement - represents one <url> element. It contains:
    • $loc - requrired - page url (as array). Before insert into XML it will be process by yii2\helpers\Url::toRoute() method.
    • $updated_at - optional - last page update;
    • $changefreq - requrired, default 'weekly' - from class constant.
    • $priority - requrired, default 0.4 - page priority.
]]>
0
[extension] mubat/yii2-inherit-model-behavior Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/mubat/yii2-inherit-model-behavior https://www.yiiframework.com/extension/mubat/yii2-inherit-model-behavior mubat mubat

yii2-inherit-model-behavior

Use this behavior to connect inherit ActiveRecord with (one-to-many relation)

In parent ActiveRecord should be column that uses to store ID of inherit ActiveRecord.

Extension supports 2 request formats:

  • default Yii2 input data, like:
    //$_POST[]
    [
      'Object' => [
          'option_1' => 'value',
          'option_2' => 'another value',
      ]
    ]
    
  • simple input names (usable for API), like:
    //$_POST[]
    [
      'option_1' => 'value',
      'option_2' => 'another value',
    ]
    

Installation

The preferred way to install this extension is through Composer.

Either run php composer.phar require mubat/yii2-inherit-model-behavior "~1.0"

or add "mubat/yii2-inherit-model-behavior": "~1.0" to the require section of your composer.json

Usage examples

  • Usage: `php public function behaviors() {

      $behaviors = parent::behaviors();
      $behaviors['image'] = [
          'class' => InheritModelBehavior::class,
          'dependClass' => Image::class, //required
          'virtualOption' => 'image', //required
          'linkAttribute' => 'image_id',
          'relationMethod' => 'savedImage',
          'simpleRequest' => true,
      ];
      return $behaviors;
    

    }

    /* @return \yii\db\ActiveQuery / public function getSavedImage() {

      return $this->hasOne(Image::class, ['id' => 'image_id']);
    

    } `

]]>
0
[wiki] pjax gridview delete button issue Fri, 11 May 2018 04:06:08 +0000 https://www.yiiframework.com/wiki/867/pjax-gridview-delete-button-issue https://www.yiiframework.com/wiki/867/pjax-gridview-delete-button-issue 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
[extension] apollo11/yii2-logger Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/apollo11/yii2-logger https://www.yiiframework.com/extension/apollo11/yii2-logger apollo11 apollo11

Yii2 Custom Logger

  1. Installation
  2. Basic Usage

Sending Yii2 application logs to different targets asynchronously or synchronously.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist apollo11/yii2-logger "~1.0"

or add

"apollo11/yii2-logger": "~1.0"

to the require section of your composer.json file.

The package offers:

  1. Abstract Target class with support of sending messages asynchronously. It also has possibility to hide sensitive information when sending $_POST or other $GLOBALS data to target.
  2. Slack target: Sending messages to slack channel

Basic Usage

The package supports three target classes: EmailTarget, SlackTarget, DbTarget.

All target classes have support for sending messages asynchronously and hide passwords(or other sensitive data) provided by user. If you set async to true than you must provide the consoleAppPath.

EmailTarget and DbTarget work pretty much in the simillar way as it is described in Yii Documentation.

Add the following code to your project configuration file under components -> log -> targets `php 'class' => , // If async is set to true you have to provide consoleAppPath 'async' => true, 'consoleAppPath' => Yii::getAlias('@console/yii'), // If you would like to use different php binary, when sending messages asynchronously you can set it from here // 'phpExecPath' => 'php', // Provide here keys which will be hidden before sending messages. It is case insensitive 'excludeKeys' => [

'*PASSWORD*', // Will hide all keys from $GLOBALS objects which contains "password".
'*PASSWORD', // Will hide all keys from $GLOBALS objects which ends with "password".
'PASSWORD*', // Will hide all keys from $GLOBALS objects which starts with "password".

], `

SlackTarget
'class' => apollo11\logger\SlackTarget::class,
'except' => ['yii\web\HttpException:*', 'yii\web\HeadersAlreadySentException'],
'webhookUrl' => <Slack channel webhook url>,
'icon_url' => '<Slack sender icon url>',
'icon_emoji' => '<Slack sender icon emoji>', // If both, icon_url and icon_emoji is provided system will use icon_emoji
'levels' => ['error', 'warning'],
'title_link' => '<Url which will be opened when clicking on title of the slack message>',
'async' => true,
'consoleAppPath' => Yii::getAlias('@console/yii'),
'username' => '<Username which will be used as sender on slack channer>',
'excludeKeys' => [],
Important

If you set async property to true, you must add the following code into your console application controllerMap

'async' => [
    'class' => \apollo11\logger\AsyncController::class,
],
]]>
0
[extension] chouaibi/yii2-blacklist-validator Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/chouaibi/yii2-blacklist-validator https://www.yiiframework.com/extension/chouaibi/yii2-blacklist-validator chouaibi chouaibi

Yii 2 blacklist validator

A Validator that will check if a model attribute is blacklisted.

Installation and usage

Installation
$ composer require chouaibi/yii2-notinarray-validator

or

Add the package to your composer.json file. ` json { "require": {

"chouaibi/yii2-blacklist-validator" : "dev-master"

} } ` then run

$ composer update
Usage

    use chouaibi\validators\BlackListValidator;

    public function rules() {
        return [
            [['attribute'], BlackListValidator::className(), 'array' => ['black','listed','values']],
        ];
    }

With custom message ` php

use chouaibi\validators\BlackListValidator;

public function rules() {
    return [
        [['attribute'], BlackListValidator::className(), 'array' => ['black','listed','values'],'message' => 'The attribute value is reserved. Please check our reserved values ...'],
    ];
}

]]>
0
[news] Gii extension 2.0.7 released Wed, 02 May 2018 22:09:25 +0000 https://www.yiiframework.com/news/175/gii-extension-2-0-7-released https://www.yiiframework.com/news/175/gii-extension-2-0-7-released samdark samdark

We are very pleased to announce the release of Gii extension version 2.0.7. The release corrects Gii behavior adapting it to changes introduced in version 2.0.15 of the framework. Additionally there are fixes in model and CRUD generators.

]]>
0
[extension] yiimaker/yii2-social-share Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/yiimaker/yii2-social-share https://www.yiiframework.com/extension/yiimaker/yii2-social-share greeflas greeflas

24204902

Extension for sharing on social networks

  1. Installation
  2. Usage
  3. Tests
  4. Contributing
  5. License

Build Status Scrutinizer Code Quality Monthly Downloads Total Downloads Latest Stable Version Latest Unstable Version

With this extension you can share data from your web pages to any social network! Features: SEO support, default icons for social networks, easy creation of custom drivers for other social networks and more!

Documentation is at docs/guide/README.md.

Extension supports from the box next social network drivers:

drivers for messengers:

and other drivers:

also you can create your driver, it's very simple!

Installation

The preferred way to install this extension is through composer.

Either run

$ composer require yiimaker/yii2-social-share

or add

"yiimaker/yii2-social-share": "~2.2"

to the require section of your composer.json.

Usage

Call widget in view file

<?= \ymaker\social\share\widgets\SocialShare::widget([
    'configurator'  => 'socialShare',
    'url'           => \yii\helpers\Url::to('absolute/route/to/page', true),
    'title'         => 'Title of the page',
    'description'   => 'Description of the page...',
    'imageUrl'      => \yii\helpers\Url::to('absolute/route/to/image.png', true),
]); ?>

Tests

You can run tests with composer command

$ composer test

or using following command

$ codecept build && codecept run

Contributing

For information about contributing please read CONTRIBUTING.md.

License

License

This project is released under the terms of the BSD-3-Clause license.

Copyright (c) 2017-2018, Yii Maker

]]>
0
[extension] yiimaker/yii2-email-templates Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/yiimaker/yii2-email-templates https://www.yiiframework.com/extension/yiimaker/yii2-email-templates greeflas greeflas

24204902

Email templates module

  1. Installation
  2. Usage
  3. Tests
  4. Contributing
  5. License

Extension for creating email templates and managing by using your site dashboard. You can create email templates with CRUD module in your backend or Gii generator.

Documentation is at docs/guide/README.md.

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

Installation

The preferred way to install this extension is through composer.

Either run

$ composer require yiimaker/yii2-email-templates

or add

"yiimaker/yii2-email-templates": "~4.0"

to the require section of your composer.json.

Usage

  1. Create template with placeholders using your site dashboard or Gii generator

    ##### Key

    register-notification - this is unique key of this template for using in your code

    ##### Subject

    Notification from {site-name}

    In this example email subject has one placeholder {site-name}

    ##### Body

    Hello, {username}! Welcome to {site-name} :)

    Email body has two placeholders: {username} and {site-name}.

    > All keys should be wrapped by {}.

  2. Now you can get this template in your code

    `php $template = Yii::$app->get('templateManager')->getTemplate('register-notification'); `

    This method returns a template model object.

  3. Then you should parse this template

    `php $template->parseSubject([

    'site-name' => Yii::$app->name,
    

    ]);

    $template->parseBody([

    'username' => Yii::$app->getIdentity()->username,
    'site-name' => Yii::$app->name,
    

    ]); `

    or use another method

    `php $template->parse([

    'subject' => [
        'site-name' => Yii::$app->name,
    ],
    'body' => [
        'username' => Yii::$app->getIdentity()->username,
        'site-name' => Yii::$app->name,
    ],
    

    ]); `

    this methods replace placeholders in template with real data.

  4. Now you can use data of this template in your logic

    `php Yii::$app->get('mailer')->compose()

     ->setSubject($template->subject)
     ->setHtmlBody($template->body)
     // ...
    

    `

Tests

You can run tests with composer command

$ composer test

or using following command

$ codecept build && codecept run

Contributing

For information about contributing please read CONTRIBUTING.md.

License

License

This project is released under the terms of the BSD-3-Clause license.

Copyright (c) 2017-2018, Yii Maker

]]>
0
[extension] yiimaker/yii2-translatable Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/yiimaker/yii2-translatable https://www.yiiframework.com/extension/yiimaker/yii2-translatable greeflas greeflas

24204902

Translatable behavior

  1. Installation
  2. Usage
  3. Tests
  4. Contributing
  5. License

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

Translatable behavior aggregates logic of linking translations to the primary model.

Installation

The preferred way to install this extension is through composer.

Either run

$ composer require yiimaker/yii2-translatable

or add

"yiimaker/yii2-translatable": "~1.0"

to the require section of your composer.json.

Usage

  1. Add behavior to the your primary model
public function behaviors()
{
    return [
        // ...
        'translatable' => [
            'class' => TranslatableBehavior::className(),
            // 'translationRelationName' => 'translations',
            // 'translationLanguageAttrName' => 'language',
            // 'attributeNamePattern' => '%name% [%language%]',
            'translationAttributeList' => [
                'title',
                'description',
            ],
        ],
    ];
}
  1. And use getTranslation() or translateTo() methods
// product is an active record model with translatable behavior
$product = new Product();

// sets translation for default application language
$product->title = 'PhpStrom 2018.1';
$product->description = 'Лицензия PhpStrom IDE версия 2018.1';

// gets translation for English language
$translation = $product->getTranslation('en');
$translation->title = 'PhpStrom 2018.1';
$translation->description = 'License of the PhpStrom IDE version 2018.1';

// sets description for French language
$product->translateTo('fr')->description = 'La licence de PhpStorm IDE la version 2018.1';

$product->insert();

translateTo() it's just an alias for getTranslation() method.

After saving the model you can fetch this model from the database and translatable behavior will fetch all translations automatically.

$product = Product::find()
    ->where(['id' => 1])
    ->with('translations')
    ->one()
;

// gets translation for English language
$product->translateTo('en')->description; // License of the PhpStrom IDE version 2018.1
// gets translation for French language
$product->translateTo('fr')->description; // La licence de PhpStorm IDE la version 2018.1

// check whether Ukrainian translation not exists
if (!$product->hasTranslation('uk')) {
    $product->translateTo('uk')->description = 'Ліцензія PhpStrom IDE версія 2018.1';
}

// update Enlish translation
$product->translateTo('en')->title = 'PhpStorm IDE';

$product->update();

Tests

You can run tests with composer command

$ composer test

or using following command

$ codecept build && codecept run

Contributing

For information about contributing please read CONTRIBUTING.md.

License

License

This project is released under the terms of the BSD-3-Clause license.

Copyright (c) 2017-2018, Yii Maker

]]>
0
[extension] dekar91/yii2-datalayer Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/dekar91/yii2-datalayer https://www.yiiframework.com/extension/dekar91/yii2-datalayer DekaR DekaR

Yii2 DataLayer helper

This extension is managed to help you fulfill dataLayer variable with initial data on fly. Some Google enhanced e-commerce features are also available.

Installation

  • The minimum required PHP version is PHP 7.1,
  • Yii2 is required.
    Using composer

    Add following line in your require section: ` "dekar91/yii2-datalayer": "@stable"

Then, register the component in your application config:
    'dataLayer' => [
        'class' => 'dekar91\datalayer\DataLayer'
    ],


## Configuration
Plugin involves both PHP and JavaScript functionality. PHP component supports following parameters:

| Parameter  | Default | Description |
| ------------- | ------------- | ------------- |
| autoPublish  | true | Whether catch EVENT_END_PAGE event in order to render DataLayer. If false you should render datalayer by yourself though getJs or render method  |
| observers  | ['ec' => ['class' => DataLayerEc::class]] |Array of classes may be used like wrapper on datalayer accessible by key each element must be following format: 'key' => ['class' => {name of class to be loaded}, 'options' => {Additional options}.   |
| customEvents  | [] | Array of event must be handled by JavaScript.Format: ['jsSelector' => 'nameOfEvent', 'customEventData'] |

Configuration example:
    'dataLayer' => [
        'class' => 'dekar91\datalayer\DataLayer',
        'options' => [
            'autoPublish' => true,
            'observers' => ['ec' => ['class' => DataLayerEc::class]],
            'customEvents' => [
                ['.btn-checkout', 'click' , ['event' => 'checkoutEvent']],
                ]
            ]
    ],

with this configuration you DataLayer will be published, DataLayerEc can be used by Yii::app()-> dalaLayer->ec,
click on .btn-checkout will be handled and event information will be pushed in dataLayer.

## Usage
### Basic usage
You can push in dataLayer before rendering though **Yii::app()-> dalaLayer->push();**

#### Methods
| Method  | Description |
| ------------- | ------------- |
| render($return = false) | Render or return dataLayer Js variable |
| push(array $data, string $key = null) | push data to dataLayer with corresponding key. |
| &getItem($key) | return element of dataLayer by link |

### Enhanced e-commerce
Some basic functions of [Enhanced e-commerce](https://developers.google.com/analytics/devguides/collection/analyticsjs/enhanced-ecommerce) are supported by default class DataLayerEc.
 Please look though google documentation for further details.
 
**Be careful!** Do not push data in ajax request, it will not take effect.

#### Methods:
| Method  |
| ------------- |
|currencyCode(string $currencyCode)|
|addProductImpression(array $product)|
|addPromoClick(array $product, array $action = [])|
|addPromoImpression(array $product)|
|addProductClick(array $product, array $action = [])|
|addProductDetails(array $product, array $action = [])|
|addToCart(array $product)|
|removeFromCart(array $product)|
|checkout(array $product, array $action = [])|
|checkoutOption($step, $checkoutOption)|
|purchase(array $purchase, array $products)|
|refund(array $transactionId, array $products = [])|



### User-defined observers
It's possible to extend dataLayer functionality by custom classes. While class is registered though observers property it can be used by Yii::app()->dataLayer->customClass. DataLayer object will be passed as first parameter in constructor.

]]>
0
[extension] kowap/yii2-lightgallery Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/kowap/yii2-lightgallery https://www.yiiframework.com/extension/kowap/yii2-lightgallery kowap kowap

jQuery lightgallery for Yii2

  1. Installation
  2. Usage

More information about gallery here.

Installation

The preferred way to install this extension is through composer.

Either run

composer require kowap/yii2-lightgallery

or add

"kowap/yii2-lightgallery": "*"

to the require section of your composer.json file.

Usage

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

<?php
    echo \kowap\lightgallery\LightGalleryWidget::widget([
        'items' => [
            [
                'thumb' => '../thumb/image_1.jpg',
                'src' => '../big/image_1.jpg'
            ],
            [
                'thumb' => '../thumb/image_2.jpg',
                'src' => '../big/image_2.jpg'
            ]
        ],
        // more options http://sachinchoolur.github.io/lightGallery/docs/api.html
        'options' => [
            'mode' => 'lg-zoom-in-big',
            'download' => false,
            'zoom' => false,
            'share' => false
        ]
    ]);
?>

]]>
0
[extension] la-haute-societe/yii2-save-relations-behavior Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/la-haute-societe/yii2-save-relations-behavior https://www.yiiframework.com/extension/la-haute-societe/yii2-save-relations-behavior Juban_ Juban_

Yii2 Active Record Save Relations Behavior

  1. Features
  2. Installation
  3. Configuring
  4. Usage
  5. Populate additional junction table columns in a many-to-many relation
  6. Validation
  7. Populate the model and its relations with input data

Automatically validate and save related Active Record models.

Latest Stable Version Total Downloads Code Coverage Build Status Latest Unstable Version License

Features

  • Both hasMany() and hasOne() relations are supported
  • Works with existing as well as new related models
  • Composite primary keys are supported
  • Only pure Active Record API is used so it should work with any DB driver

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist la-haute-societe/yii2-save-relations-behavior "*"

or add

"la-haute-societe/yii2-save-relations-behavior": "*"

to the require section of your composer.json file.

Configuring

Configure model as follows `php use lhs\Yii2SaveRelationsBehavior\SaveRelationsBehavior;

class Project extends \yii\db\ActiveRecord {

use SaveRelationsTrait; // Optional

public function behaviors()
{
    return [
        'timestamp'     => TimestampBehavior::className(),
        'blameable'     => BlameableBehavior::className(),
        ...
        'saveRelations' => [
            'class'     => SaveRelationsBehavior::className(),
            'relations' => [
                'company',
                'users',
                'tags'  => [
                    'extraColumns' => function ($model) {
                        /** @var $model Tag */
                        return [
                            'order' => $model->order
                        ];
                    }
                ]
            ],
        ],
    ];
}

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

...
/**
 * @return ActiveQuery
 */
public function getCompany()
{
    return $this->hasOne(Company::className(), ['id' => 'company_id']);
}

/**
 * @return ActiveQuery
 */
public function getProjectUsers()
{
    return $this->hasMany(ProjectUser::className(), ['project_id' => 'id']);
}

/**
 * @return ActiveQuery
 */
public function getUsers()
{
    return $this->hasMany(User::className(), ['id' => 'user_id'])->via('ProjectUsers');
}

/**
 * @return ActiveQuery
 */
public function getTags()
{
    return $this->hasMany(Tag::className(), ['id' => 'tag_id'])->viaTable('ProjectTags', ['project_id' => 'id']);
}

} ` > Though not mandatory, it is highly recommended to activate the transactions for the owner model.

Usage

Every declared relations in the relations behavior parameter can now be set and saved as follow: `php $project = new Project(); $project->name = "New project"; $project->company = Company::findOne(2); $project->users = User::findAll([1,3]); $project->save(); You can set related model by only specifying its primary key:php $project = new Project(); $project->name = "Another project"; $project->company = 2; $project->users = [1,3]; $project->save(); ` You can even set related models as associative arrays like this:

$project = Project::findOne(1);
$project->company = ['name' => 'GiHub', 'description' => 'Awesome']; // Will create a new company record
// $project->company = ['id' => 3, 'name' => 'GiHub', 'description' => 'Awesome']; // Will update an existing company record
$project->save();

Attributes of the related model will be massively assigned using the `load() method. So remember to declare the according attributes as safe in the rules of the related model.

Notes:

  • Related models are saved during the EVENT_BEFORE_VALIDATE event of the owner model. Transaction will start at this point according to the transactions() method of the model.
  • Only newly created or changed related models will be saved.

See the PHPUnit tests for more examples.

Populate additional junction table columns in a many-to-many relation

In a many-to-many relation involving a junction table additional column values can be saved to the junction table for each model. See the configuration section for examples.

Note: If junction table properties are configured for a relation the rows associated with the related models in the junction table will be deleted and inserted again on each saving to ensure that changes to the junction table properties are saved too.

Validation

Every declared related models will be validated prior to be saved. If any validation fails, for each related model attribute in error, an error associated with the named relation will be added to the owner model.

For hasMany() relations, the index of the related model will be used to identify the associated error message.

It is possible to specify the validation scenario for each relation by declaring an associative array in which the scenario key must contain the needed scenario value. For instance, in the following configuration, the links related records will be validated using the Link::SOME_SCENARIO scenario: `php ...

public function behaviors()
{
    return [
        'saveRelations' => [
            'class'     => SaveRelationsBehavior::className(),
            'relations' => ['company', 'users', 'links' => ['scenario' => Link::SOME_SCENARIO]]
        ],
    ];
}  

... ` > Tips: > For relations not involving a junction table by using the via() or viaTable() methods, you should remove the attributes pointing to the owner model from the 'required' validation rules to be able to pass the validations.

Note: If an error occurs for any reason during the saving process of related records in the afterSave event, a yii\db\Exception will be thrown on the first occurring error. An error message will be attached to the relation attribute of the owner model. In order to be able to handle these cases in a user-friendly way, one will have to catch yii\db\Exception exceptions.

Populate the model and its relations with input data

This behavior adds a convenient method to load relations models attributes in the same way that the load() method does. Simply call the loadRelations() with the according input data.

For instance: `php $project = Project::findOne(1); /**

  • $_POST could be something like:
  • [
  • 'Company' => [
  • 'name' => 'YiiSoft'
  • ],
  • 'ProjectLink' => [
  • [
  • 'language' => 'en',
  • 'name' => 'yii',
  • 'link' => 'http://www.yiiframework.com'
  • ],
  • [
  • 'language' => 'fr',
  • 'name' => 'yii',
  • 'link' => 'http://www.yiiframework.fr'
  • ]
  • ]
  • ]; */ $project->loadRelations(Yii::$app->request->post());
    
    

You can even further simplify the process by adding the SaveRelationsTrait to your model. In that case, a call to the load() method will also automatically trigger a call to the loadRelations() method by using the same data, so you basically won't have to change your controllers.

]]>
0
[extension] akiraz2/yii2-app Mon, 30 Apr 2018 18:24:56 +0000 https://www.yiiframework.com/extension/akiraz2/yii2-app https://www.yiiframework.com/extension/akiraz2/yii2-app akiraz2 akiraz2

Yii2 Fast Simple Advanced App Packagist Version Total Downloads

  1. Features
  2. Available modules
  3. Installation
  4. Development
  5. Support
  6. Contributing
  7. Licensing

Yii2-app is Fast and Ready-to-production advanced project template.

For you, I downgrade requirement to PHP v5.6. But PHP 7.1 is better! because it is really fast.

Please, enable php intl extension for better work.

Default, the template includes three tiers: frontend, backend, and console, each of which is a separate Yii application.

NOTE: Template is in initial development. Anything may change at any time.

Features

  • Gentelella Admin template is beautiful and simple bootstrap, compatible with yii2 assets: yiister/yii2-gentelella, Demo
  • Yii2 User is strong and proved user-module with many features: dektrium/yii2-user (login adminus, password adminus)
  • Frontend and Backend User Controllers are filtered (by dektrium/yii2-user)
  • DB cache, but I recommend Redis Cache - it is really fast
  • Yii2 queue (DB table queue), but you can use Redis-queue or other yii2-queue docs
  • Queue Manager with backend (/queuemanager/default/index) using ignatenkovnikita/yii2-queuemanager
  • Log DB Target with backend (/log/index) - simply view log messages
  • .htaccess - config for pretty urls (rewrite index.php), may be later add nginx config
  • UrlManagerFrontend for backend app (all url rules in file frontend/config/urls.php, hostInfo in common/config/params.php)
  • i18n translations in common/messages with config (current only English and Russian, language translation are welcome!)
  • ContactForm in frontend app is improved: himiklab/yii2-recaptcha-widget, all email are saved to DB (common/models/EmailForm Model), optionally send message to Viber messenger via bot (install requirements Bogdaan/viber-bot-php and config, uncomment code in Model)
  • postcss config (frontend/web/src/pcss//*.css)
  • Gii generator:
    1. added yii2-queue Jobs generator
    2. yii2 migration generator (from existing table) Insolita/yii2-migrik
    3. schmunk42/yii2-giiant - really steroid, but in development with bugs

Available modules

These modules can be easy installed to Yii2-App using Composer:

Installation

Yii2-app template can be installed using composer. Run following command to download and install Yii2-app: composer create-project --prefer-dist akiraz2/yii2-app my-site After installation run init

Migrations

NOTE: Make sure that you have properly configured db application component and run the following command

php yii migrate/up --migrationPath=@vendor/dektrium/yii2-user/migrations
php yii migrate --migrationPath=@yii/log/migrations/
php yii migrate --migrationPath=vendor/ignatenkovnikita/yii2-queuemanager/migrations/
php yii migrate/up
Web server config

For newbies, I will recommend to read these instructions yiisoft/yii2-app-advanced/start-installation.md (apache, nginx, etc\hosts

Development

Messages

Change in common/config/main.php 'language' => 'ru-RU', 'sourceLanguage' => 'en-US',

Add your language in common/messages/config.php `

'languages' => [
    'ru-RU',
],
In shell 

php yii message/extract common/messages/config.php `

POSTCSS

NOTE: Dont forget install nodejs :) and run command npm install if you want use post locally

Add WebStorm file-watcher, postcss.config.js is ready for use

  1. scope file[my-site]:frontend/web/src/pcss//*.css
  2. program C:\Users\user4957\AppData\Roaming\npm\postcss.cmd
  3. arguments $ContentRoot$\frontend\web\css\style.css --config $ContentRoot$\post.config.js

Support

If you have any questions or problems with Yii2-App you can ask them directly by using following email address: akiraz@bk.ru.

Contributing

If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome. +PSR-2 style coding.

I can apply patch, PR in 2-3 days! If not, please write me akiraz@bk.ru

Licensing

Yii2-App is released under the BSD License. See the bundled LICENSE.md for details.

]]>
0
[extension] akiraz2/yii2-stat Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/akiraz2/yii2-stat https://www.yiiframework.com/extension/akiraz2/yii2-stat akiraz2 akiraz2

Yii2 Multi Web Statistic Module Packagist Version Total Downloads Software License

  1. Features
  2. Installation
  3. Usage
  4. Development
  5. Support
  6. Contributing
  7. Licensing

NOTE: Module is in initial development. Anything may change at any time. На данный момент текущая рабочая версия v0.2 - есть только счетчики яндекса и google и собственный счетчик в DB

Модуль статистики и аналитики для вашего сайта. Много систем на ваш выбор, подключаются либо в конфиге модуля либо в админке:

  • Яндекс-Метрика
  • Google Analytics
  • Liveinternet
  • TopMail
  • Bigmir (для украинской аудитории)
  • Alexa
  • Hotlog
  • Rambler
  • Openstat
  • и даже на выбор собственная система для отслеживания посетителей по их IP-адресам и cookie.

NOTE: Используются самые свежие версии кода счетчика (yandex-metrika2, gtag.js).

Для разработки модуля Yii2 Stat были использованы наработки данных модулей:

Иногда не все посещения сайта фиксируются счетчиками Яндекса или Google. Чтобы посещение точно было засчитано (а это очень важно для отслеживания рекламных источников), используют серверные логи или в нашем случае можно использовать минимально рабочий счетчик на PHP.

Features

  • вы можете использовать внешние сервисы на свой вкус, выбор простым конфигурированием модуля
  • есть собственная простая система сбора статистики
  • данные хранятся в отдельной таблице базы данных или на ваше усмотрение (Redis, etc)
  • статистика формируется на основе уникальных IP адресов посетителей сайта/приложения и Cookie
  • можно посмотреть страну, город, какой браузер и расширение, referer
  • источник перехода (inner, search, direct, ads (from UTM-tags), unknown)
  • отсеивание поисковых ботов (11шт)
  • есть возможность добавления IP, которые не нужны в статистике в черный спискок
  • удобная фильтрация вывода результатов статистики (за день, период, по определенному IP)

Какая информация выводится по каждому отдельному посетителю:

  • его уникальный IP адрес с возможностью получения информации о его местонахождении
  • URL просматриваемой страницы и количество переходов
  • время посещения определенной страницы

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist akiraz2/yii2-stat "dev-master"

or add

"akiraz2/yii2-stat": "dev-master"

to the require section of your composer.json file.

Migration

Migration run

yii migrate --migrationPath=@akiraz2/stat/migrations
Config

Config common modules in common/config/main.php

    'modules' => [
        'stat' => [
            'class' => akiraz2\stat\Module::class,
            'yandexMetrika' => [ // false by default
               'id' => 13788753,
               'params' => [
                   'clickmap' => true,
                   'trackLinks' => true,
                   'accurateTrackBounce' => true,
                   'webvisor' => true
               ]
            ],
            'googleAnalytics' => [ // false by default
                'id' => 'UA-114443409-2',
            ],
            'ownStat' => true, //false by default
            'ownStatCookieId' => 'yii2_counter_id', // 'yii2_counter_id' default
            'onlyGuestUsers' => true, // true default
            'countBot' => false, // false default
            'appId' => ['app-frontend'], // by default count visits only from Frontend App (in backend app we dont need it)
            'blackIpList' => [] // ['127.0.0.1'] by default
            
            // размещаем нашу админ панель на backend с проверкой доступа или ролями (здесь используется dektrium/user)
            'controllerMap' => [
                'dashboard' => [
                    'class' => 'akiraz2\stat\controllers\DashboardController',
                    'as access' => [
                        'class' => \yii\filters\AccessControl::class,
                        'rules' => [
                            [
                                'allow' => true,
                                'roles' => ['@'],
                                'matchCallback' => function () {
                                    return Yii::$app->user->identity->getIsAdmin();
                                },
                            ],
                        ],
                    ],
                ],
            ],
        ],
     ],    

Usage

// переработать

Для перехода на страницу статистики

Development

Please translate to your language! Edit config @vendor/akiraz2/yii2-stat/src/messages/config.php, add your language and run script: `php php ./yii message/extract @akiraz2/stat/messages/config.php ` translate file will be in @vendor/akiraz2/yii2-stat/src/messages/ or your configured path

Support

If you have any questions or problems with Yii2-Stat you can ask them directly by using following email address: akiraz@bk.ru.

Contributing

If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome. +PSR-2 style coding.

I can apply patch, PR in 2-3 days! If not, please write me akiraz@bk.ru

Licensing

Yii2-Stat is released under the MIT License. See the bundled LICENSE.md for details.

]]>
0
[news] Swiftmailer extension 2.1.1 released Tue, 24 Apr 2018 23:26:51 +0000 https://www.yiiframework.com/news/174/swiftmailer-extension-2-1-1-released https://www.yiiframework.com/news/174/swiftmailer-extension-2-1-1-released samdark samdark

We are very pleased to announce the release of Swiftmailer extension version 2.1.1 that fixes yii\swiftmailer\Mailer::setTransport had no effect after sending of first message.

]]>
0
[news] Smarty extension 2.0.7 released Tue, 24 Apr 2018 23:11:22 +0000 https://www.yiiframework.com/news/173/smarty-extension-2-0-7-released https://www.yiiframework.com/news/173/smarty-extension-2-0-7-released samdark samdark

We are very pleased to announce the release of Smarty extension version 2.0.7 that fixes widget registration and rendering code generation inside subtemplates and adds an ability to use SmartyBC class.

]]>
0
[extension] cozumel/yii2-twemoji Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/cozumel/yii2-twemoji https://www.yiiframework.com/extension/cozumel/yii2-twemoji Cozumel Cozumel

Yii2 Twemoji

  1. Installation
  2. Usage
  3. CSS

Latest Stable Version Total Downloads License

A simple way to add Twemoji support to your Yii2 project.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist cozumel/yii2-twemoji "*"

or add

"cozumel/yii2-twemoji": "*"

to the require section of your composer.json file.

Usage

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

use cozumel\twemoji\TwemojiAsset;

TwemojiAsset::register($this);

CSS

Because every project will have different size requirements, the css is not part of the extension. The default size of the emojis is 72x72. You can change this easily with some css. `css img.emoji { height: 1em; width: 1em; margin: 0 .05em 0 .1em; vertical-align: -0.1em; } `

]]>
0
[extension] chiliec/yii2-vote Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/chiliec/yii2-vote https://www.yiiframework.com/extension/chiliec/yii2-vote Chiliec Chiliec

Vote for Yii2

  1. Installation
  2. Documentation
  3. List of contributors
  4. Other vote solutions for Yii2
  5. Articles and tutorials
  6. Usage examples
  7. License
  8. How to contribute

Latest Stable Version Total Downloads Build Status Code Climate Test Coverage License

How yii2-vote works

Installation

Next steps will guide you through the process of installing yii2-vote using composer. Installation is a quick and easy three-step process.

Step 1: Install component via composer

Run command

php composer.phar require --prefer-dist chiliec/yii2-vote "^4.2"

or add

"chiliec/yii2-vote": "^4.2"

to the require section of your composer.json file.

Step 2: Configuring your application

Add following lines to your main configuration file:

'bootstrap' => [
    'chiliec\vote\components\VoteBootstrap',
],
'modules' => [
    'vote' => [
        'class' => 'chiliec\vote\Module',
        // show messages in popover
        'popOverEnabled' => true,
        // global values for all models
        // 'allowGuests' => true,
        // 'allowChangeVote' => true,
        'models' => [
        	// example declaration of models
            // \common\models\Post::className(),
            // 'backend\models\Post',
            // 2 => 'frontend\models\Story',
            // 3 => [
            //     'modelName' => \backend\models\Mail::className(),
            //     you can rewrite global values for specific model
            //     'allowGuests' => false,
            //     'allowChangeVote' => false,
            // ],
        ],      
    ],
],

And add widget in view:

<?php echo \chiliec\vote\widgets\Vote::widget([
    'model' => $model,
    // optional fields
    // 'showAggregateRating' => true,
]); ?>

Also you can add widget for display top rated models:

<?php echo \chiliec\vote\widgets\TopRated::widget([
    'modelName' => \common\models\Post::className(),
    'title' => 'Top rated models',
    'path' => 'site/view',
    'limit' => 10,
    'titleField' => 'title',
]) ?>
Step 3: Updating database schema

After you downloaded and configured Yii2-vote, the last thing you need to do is updating your database schema by applying the migrations:

$ php yii migrate/up --migrationPath=@vendor/chiliec/yii2-vote/migrations

Documentation

Extended information about configuration of this module see in docs/README.md. There you can find:

List of contributors

Other vote solutions for Yii2

Articles and tutorials

Usage examples

  • Your site could be the first in this list

License

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

How to contribute

See CONTRIBUTING.md for details.

Enjoy and don't hesitate to send issues and pull requests :)

]]>
0
[extension] yii-elastic-search Thu, 19 Apr 2018 02:35:49 +0000 https://www.yiiframework.com/extension/yii-elastic-search https://www.yiiframework.com/extension/yii-elastic-search mh2k9 mh2k9
  1. Requirements
  2. Installation
  3. Usage
  4. Resources

It is an yii-1.x extension for performing ElasticSearch queries. This extension is based on Official low-level client for ElasticSearch

Requirements

  • PHP 7.0 or higher

Installation

  1. Download the extension
  2. Copy elasticSearch extension to your project extension direcory
  3. Add components to main.php
'es' => [
    'class' => 'application.extensions.elasticSearch.ElasticSearch',
    'host' => '127.0.0.1:9200',
    // Array of index types. Array keys indicate the name of indexes
    'es_index_type' => [
        'my_index' => 'my_type',
        'my_index2' => 'my_type2',
        'my_index3' => 'my_type2',
        // list all indexes and types [key value pare]
    ]
]

Usage

Query by ID

$response = Yii::app()->es->getById('my_index', 'my_id');

Output look like

Array
(
    [_index] => my_index
    [_type] => my_type
    [_id] => my_id
    [_version] => 1
    [found] => 1
    [_source] => Array
    (
        [id] => my_id
        .....
    )
)

Get by query

$queryBody = [];
$queryBody['_source'] = 'field1, field2, field3'; // An example of selected fields
$queryBody['body'] = [
    'query' => [
        'bool' => [
            'must' => [
                'bool' => [
                    'should' => [
                        [ 'match' => [ 'condition_field_name' => "condition_value" ] ]
                    ]
                ]
            ]
        ]
    ]
];

$response = Yii::app()->es->getByQuery('my_index', $queryBody);

Query as per official documentation

$params = [
    'index' => 'my_index',
    'type' => 'my_type',
    'id' => 'my_id'
];

$response = Yii::app()->es->getClientInstance()->get($params);

Resources

]]>
0
[extension] imanilchaudhari/yii2-currency-converter Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/imanilchaudhari/yii2-currency-converter https://www.yiiframework.com/extension/imanilchaudhari/yii2-currency-converter imanilchaudhari imanilchaudhari

Yii2 Currency Converter

  1. Why Use It
  2. Important Notice
  3. Requirements
  4. Installation
  5. Usage
  6. Available Currency Codes
  7. Contributors
  8. Open Exchange Rates APi Integration

Build Status Latest Stable Version Latest Unstable Version Total Downloads

This extension will help to find out current currency conversion rate. This extension uses Yahoo's currency conversion API.

Why Use It

  • Reliable Rate. Uses Yahoo API, Open Exchange Rates API.
  • Conversion without curreny code (from country code).
  • Caching of rate, to avoid connecting to Yahoo again and again.

Important Notice

As of recent changes on Yahoo Terms of Service. As such, the service is being discontinued. I highly recommend you to use Open Exchange Rates API. As suggested by chaimleich on this pull request. You can find Open Exchnage Rates working example below.

Requirements

  • PHP version 5.4 or later
  • Curl Extension (Optional)

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist imanilchaudhari/yii2-currency-converter "1.0"

or add

"imanilchaudhari/yii2-currency-converter": "1.0"

to the require section of your composer.json file.

Usage

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

use Yii;
use imanilchaudhari\CurrencyConverter\CurrencyConverter;

$converter = new CurrencyConverter();
$rate =  $converter->convert('USD', 'NPR');

print_r($rate);  // it will print current Nepalese currency (NPR) rate according to USD


Available Currency Codes

$currencies = [
        'AF' => 'AFA',
        'AL' => 'ALL',
        'DZ' => 'DZD',
        'AS' => 'USD',
        'AD' => 'EUR',
        'AO' => 'AOA',
        'AI' => 'XCD',
        'AQ' => 'NOK',
        'AG' => 'XCD',
        'AR' => 'ARA',
        'AM' => 'AMD',
        'AW' => 'AWG',
        'AU' => 'AUD',
        'AT' => 'EUR',
        'AZ' => 'AZM',
        'BS' => 'BSD',
        'BH' => 'BHD',
        'BD' => 'BDT',
        'BB' => 'BBD',
        'BY' => 'BYR',
        'BE' => 'EUR',
        'BZ' => 'BZD',
        'BJ' => 'XAF',
        'BM' => 'BMD',
        'BT' => 'BTN',
        'BO' => 'BOB',
        'BA' => 'BAM',
        'BW' => 'BWP',
        'BV' => 'NOK',
        'BR' => 'BRL',
        'IO' => 'GBP',
        'BN' => 'BND',
        'BG' => 'BGL',
        'BF' => 'XAF',
        'BI' => 'BIF',
        'KH' => 'KHR',
        'CM' => 'XAF',
        'CA' => 'CAD',
        'CV' => 'CVE',
        'KY' => 'KYD',
        'CF' => 'XAF',
        'TD' => 'XAF',
        'CL' => 'CLF',
        'CN' => 'CNY',
        'CX' => 'AUD',
        'CC' => 'AUD',
        'CO' => 'COP',
        'KM' => 'KMF',
        'CD' => 'CDZ',
        'CG' => 'XAF',
        'CK' => 'NZD',
        'CR' => 'CRC',
        'HR' => 'HRK',
        'CU' => 'CUP',
        'CY' => 'EUR',
        'CZ' => 'CZK',
        'DK' => 'DKK',
        'DJ' => 'DJF',
        'DM' => 'XCD',
        'DO' => 'DOP',
        'TP' => 'TPE',
        'EC' => 'USD',
        'EG' => 'EGP',
        'SV' => 'USD',
        'GQ' => 'XAF',
        'ER' => 'ERN',
        'EE' => 'EEK',
        'ET' => 'ETB',
        'FK' => 'FKP',
        'FO' => 'DKK',
        'FJ' => 'FJD',
        'FI' => 'EUR',
        'FR' => 'EUR',
        'FX' => 'EUR',
        'GF' => 'EUR',
        'PF' => 'XPF',
        'TF' => 'EUR',
        'GA' => 'XAF',
        'GM' => 'GMD',
        'GE' => 'GEL',
        'DE' => 'EUR',
        'GH' => 'GHC',
        'GI' => 'GIP',
        'GR' => 'EUR',
        'GL' => 'DKK',
        'GD' => 'XCD',
        'GP' => 'EUR',
        'GU' => 'USD',
        'GT' => 'GTQ',
        'GN' => 'GNS',
        'GW' => 'GWP',
        'GY' => 'GYD',
        'HT' => 'HTG',
        'HM' => 'AUD',
        'VA' => 'EUR',
        'HN' => 'HNL',
        'HK' => 'HKD',
        'HU' => 'HUF',
        'IS' => 'ISK',
        'IN' => 'INR',
        'ID' => 'IDR',
        'IR' => 'IRR',
        'IQ' => 'IQD',
        'IE' => 'EUR',
        'IL' => 'ILS',
        'IT' => 'EUR',
        'CI' => 'XAF',
        'JM' => 'JMD',
        'JP' => 'JPY',
        'JO' => 'JOD',
        'KZ' => 'KZT',
        'KE' => 'KES',
        'KI' => 'AUD',
        'KP' => 'KPW',
        'KR' => 'KRW',
        'KW' => 'KWD',
        'KG' => 'KGS',
        'LA' => 'LAK',
        'LV' => 'LVL',
        'LB' => 'LBP',
        'LS' => 'LSL',
        'LR' => 'LRD',
        'LY' => 'LYD',
        'LI' => 'CHF',
        'LT' => 'EUR',
        'LU' => 'EUR',
        'MO' => 'MOP',
        'MK' => 'MKD',
        'MG' => 'MGF',
        'MW' => 'MWK',
        'MY' => 'MYR',
        'MV' => 'MVR',
        'ML' => 'XAF',
        'MT' => 'EUR',
        'MH' => 'USD',
        'MQ' => 'EUR',
        'MR' => 'MRO',
        'MU' => 'MUR',
        'YT' => 'EUR',
        'MX' => 'MXN',
        'FM' => 'USD',
        'MD' => 'MDL',
        'MC' => 'EUR',
        'MN' => 'MNT',
        'MS' => 'XCD',
        'MA' => 'MAD',
        'MZ' => 'MZM',
        'MM' => 'MMK',
        'NA' => 'NAD',
        'NR' => 'AUD',
        'NP' => 'NPR',
        'NL' => 'EUR',
        'AN' => 'ANG',
        'NC' => 'XPF',
        'NZ' => 'NZD',
        'NI' => 'NIC',
        'NE' => 'XOF',
        'NG' => 'NGN',
        'NU' => 'NZD',
        'NF' => 'AUD',
        'MP' => 'USD',
        'NO' => 'NOK',
        'OM' => 'OMR',
        'PK' => 'PKR',
        'PW' => 'USD',
        'PA' => 'PAB',
        'PG' => 'PGK',
        'PY' => 'PYG',
        'PE' => 'PEI',
        'PH' => 'PHP',
        'PN' => 'NZD',
        'PL' => 'PLN',
        'PT' => 'EUR',
        'PR' => 'USD',
        'QA' => 'QAR',
        'RE' => 'EUR',
        'RO' => 'ROL',
        'RU' => 'RUB',
        'RW' => 'RWF',
        'KN' => 'XCD',
        'LC' => 'XCD',
        'VC' => 'XCD',
        'WS' => 'WST',
        'SM' => 'EUR',
        'ST' => 'STD',
        'SA' => 'SAR',
        'SN' => 'XOF',
        'CS' => 'EUR',
        'SC' => 'SCR',
        'SL' => 'SLL',
        'SG' => 'SGD',
        'SK' => 'EUR',
        'SI' => 'EUR',
        'SB' => 'SBD',
        'SO' => 'SOS',
        'ZA' => 'ZAR',
        'GS' => 'GBP',
        'ES' => 'EUR',
        'LK' => 'LKR',
        'SH' => 'SHP',
        'PM' => 'EUR',
        'SD' => 'SDG',
        'SR' => 'SRG',
        'SJ' => 'NOK',
        'SZ' => 'SZL',
        'SE' => 'SEK',
        'CH' => 'CHF',
        'SY' => 'SYP',
        'TW' => 'TWD',
        'TJ' => 'TJR',
        'TZ' => 'TZS',
        'TH' => 'THB',
        'TG' => 'XAF',
        'TK' => 'NZD',
        'TO' => 'TOP',
        'TT' => 'TTD',
        'TN' => 'TND',
        'TR' => 'TRY',
        'TM' => 'TMM',
        'TC' => 'USD',
        'TV' => 'AUD',
        'UG' => 'UGS',
        'UA' => 'UAH',
        'SU' => 'SUR',
        'AE' => 'AED',
        'GB' => 'GBP',
        'US' => 'USD',
        'UM' => 'USD',
        'UY' => 'UYU',
        'UZ' => 'UZS',
        'VU' => 'VUV',
        'VE' => 'VEF',
        'VN' => 'VND',
        'VG' => 'USD',
        'VI' => 'USD',
        'WF' => 'XPF',
        'XO' => 'XOF',
        'EH' => 'MAD',
        'ZM' => 'ZMK',
        'ZW' => 'USD'
    ];

Contributors

Open Exchange Rates APi Integration

Here is a code snippets suggested by chaimleich on this pull request. `php

use Yii; use imanilchaudhari\CurrencyConverter\Provider\OpenExchangeRatesApi;

class CurrencyConverter extends \imanilchaudhari\CurrencyConverter\CurrencyConverter {

/**
 * @inheritdoc
 */
public function getRateProvider()
{
    if (!$this->rateProvider) {
        $this->setRateProvider(new OpenExchangeRatesApi([
            'appId' => Yii::$app->params['openExchangeRate']['appId'],
        ]));
    }

    return $this->rateProvider;
}

} `

]]>
0
[extension] imanilchaudhari/yii2-social-share Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/imanilchaudhari/yii2-social-share https://www.yiiframework.com/extension/imanilchaudhari/yii2-social-share imanilchaudhari imanilchaudhari

Yii2 social share- A beautiful social share buttons for yii2.

  1. Installation
  2. Usage
  3. About

This is a social share buttons for yii2 projects.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist imanilchaudhari/yii2-social-share "dev-master"

or add

"imanilchaudhari/yii2-social-share": "dev-master"

to the require section of your composer.json file.

Usage

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

<?= \imanilchaudhari\socialshare\ShareButton::widget([
        'style'=>'horizontal',
        'networks' => ['facebook','googleplus','linkedin','twitter'],
		'data_via'=>'imanilchaudhari', //twitter username (for twitter only, if exists else leave empty)
]); ?>

About

This is a replica of SocialShareButton by Yii Expert.

]]>
0
[extension] light/yii2-ajaxform Sat, 26 May 2018 15:09:05 +0000 https://www.yiiframework.com/extension/light/yii2-ajaxform https://www.yiiframework.com/extension/light/yii2-ajaxform lichunqiang lichunqiang

993323

Yii2 Ajax Form

  1. Overview
  2. Install
  3. Usage
  4. Test
  5. LICENSE

Build Status version Download Issues

Overview

Using jquery.form to make ActiveForm has ability to submit via ajax but not fullpage reload.

Install

Using composer:

$ composer require light/yii2-ajaxform=*

Usage

use light\widgets\ActiveForm;
use yii\web\JsExpression;

ActiveForm::begin([
	'ajaxSubmitOptions' => [
		'success' => new JsExpression('function(response) {console.log(response)}'),
		'complete' => new JsExpression('function() {console.log("request completed.")}')
	]
])

Options
  • Default enabled enableAjaxSubmit is true
  • ajaxSubmitOptions you can find in jquery.form

Test

$ phpunit

LICENSE

MIT

Bitdeli Badge

]]>
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
[news] MongoDB extension 2.1.7 released Tue, 24 Apr 2018 23:09:22 +0000 https://www.yiiframework.com/news/172/mongodb-extension-2-1-7-released https://www.yiiframework.com/news/172/mongodb-extension-2-1-7-released samdark samdark

We are very pleased to announce the release of MongoDB extension version 2.1.7 that fixes Yii 2.0.14+ incompatibility and enhances Session component error reporting.

]]>
0
[news] Shell extension version 2.0.1 released Mon, 26 Mar 2018 14:53:24 +0000 https://www.yiiframework.com/news/171/shell-extension-version-2-0-1-released https://www.yiiframework.com/news/171/shell-extension-version-2-0-1-released samdark samdark

We are very pleased to announce the release of Shell extension version 2.0.1 which updates psy/psysh dependency to 0.8.x versions.

]]>
0
[wiki] Use non Gmail/Gsuite on Gcloud projects Mon, 26 Mar 2018 01:33:16 +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
[news] Finally releasing the new Yiiframework.com website Mon, 26 Mar 2018 14:51:57 +0000 https://www.yiiframework.com/news/169/finally-releasing-the-new-yiiframework-com-website https://www.yiiframework.com/news/169/finally-releasing-the-new-yiiframework-com-website CeBe CeBe

We are very happy to announce that the new yiiframework.com website is finally ready for deployment.

A huge thanks to Сергей Хильков (eshill) for his design work, to Jacob Moen and Nikola Trifunović for the countless hours spent on tweaking the frontend code and doing pages markup. Thanks to prodex, Robert Korulczyk and other contributors for fixes and additions.

There is a forum topic for discussion on this announcement.

Content

The new website will keep most of the content that is currently available online. We tried to keep existing content in the same places, so URLs should be the same as before. If you find that content is missing that was available before, please report to website project issues.

You can have a look at the new site on https://new.yiiframework.com/. Please note that this is just a preview. All content there will be re-imported destroying all the changes made when we'll deploy production version. Be careful with the forum however as it is real production one proxied to the new site :)

The new website puts more focus on the documentation, making Guide and API docs the first items in the navigation. You can now also directly search for API entries from the main navigation search field. You can search for class names and also method and property names, e.g. ActiveRecord.save() or just .save() or ::save().

Wiki and Extensions are available as before. Extensions now integrate with packagist, so if your extension is listed on packagist.org you no longer have to maintain two different places, the content is automatically synced with packagist if you enter the packagist URL in the extension properties.

The community section still has the old forum, which will continue to operate as before for now. We might replace the forum with a better solution in the future. Also badges and ranking functionality has been ported from the old website.

Other information about Yii is now grouped under the "More" point in the navigation.

User accounts

We have imported all user accounts from the old website. You should be able to log in with your user name and password as before. If it does not work, there is a password reset option. In case you lost access to your account, we'll be there to help, please report to website project issues or write an email to admin@yiiframework.com.

You can now log in with github. To connect your existing login with your github account, log in regularly first, then go to your profile page (click on your user name on the top right) and authorize github. You won't need to type password again.

Feedback

If you have feedback about the new website, or you found a bug, please report in the Github issue tracker.

Roadmap

We are going to switch to the new website on March 23, 2018 in the time frame 8:00 to 12:00 UTC. During the switch, you will not be able to write comments, wikis, forum entries etc. Also the documentation may not be available. You can use http://stuff.cebe.cc/yii2docs/ to view the documentation.

We will be avilable in the Slack chat and on IRC #yii on freenode, so if you need help, get there.

]]>
0
[news] Releasing Yii 2.0.15 and database extensions with security fixes Mon, 09 Apr 2018 21:18:03 +0000 https://www.yiiframework.com/news/168/releasing-yii-2-0-15-and-database-extensions-with-security-fixes https://www.yiiframework.com/news/168/releasing-yii-2-0-15-and-database-extensions-with-security-fixes CeBe CeBe

Today we are releasing several versions for Yii 2.0.x and official extensions to fix a security issue.

The problem addressed in these patches exists in ActiveRecord shortcut methods findOne() and findAll(), which may allow SQL injection if input is not prepared properly. We consider this as a security issue in Yii because the documentation for these methods did not contain an explicit warning that there are cases when passing unfiltered user input might be dangerous. Thanks to analitic1983 for making us aware of the issue.

The nature of this issue does not solely exists in the Yii Framework but depends on how an application uses Yii. We have changed Yii to be more robust against the worst impact of the problem (SQL injection), but applications may still be vulnerable and changes to application code are necessary in some cases. As a safety measure, findOne() and findAll() are now limited to filter on columns that are AR properties only. In the following we will explain the problem in more detail and show which application code is affected and what needs to be adjusted on upgrade.

For discussion on this issue, there is a forum topic.

Summary of Affected Classes, Methods and Composer Packages

  1. Not Affected Code
  2. Affected Code
  • yii\db\ActiveRecord::findOne() and yii\db\ActiveRecord::findAll() in yiisoft/yii2 referenced as CVE-2018-7269. Methods allow SQL injection if input is not prepared properly. Attackers could probably execute arbitrary SQL queries or circumvent access checking methods applied on query level.
  • yii\redis\ActiveRecord::findOne() and yii\redis\ActiveRecord::findAll() in yiisoft/yii2-redis referenced as CVE-2018-8073. Methods allow remote code execution in redis servers lua script environment. Attackers could probably manipulate data on the redis server.
  • yii\elasticsearch\ActiveRecord::findOne() and yii\elasticsearch\ActiveRecord::findAll() in yiisoft/yii2-elasticsearch referenced as CVE-2018-8074. Methods may allow injecting different search condition than desired or cause an error response from the elasticsearch server.

Is my Application Affected?

  1. Not Affected Code
  2. Affected Code

This vulnerability affects all releases of the 2.0.x branch. It is fixed in Yii 2.0.15. For versions below 2.0.15, we have released two patch versions, 2.0.13.2 and 2.0.12.1, which apply the fix to 2.0.13.1 and 2.0.12 respectively. Users of 2.0.14, can upgrade to 2.0.15, there are no other changes made in this release.

Not Affected Code

The methods findOne() and findAll() accept a single argument, which can be scalar or array. If the calling code ensures that a scalar is passed or if client inputs cannot modify the array's structure, your application is not affected by this issue. The following code examples are not affected by this issue (examples shown for findOne() are valid also for findAll()):

// yii\web\Controller ensures that $id is scalar
public function actionView($id)
{
    $model = Post::findOne($id);
    // ...
}
// casting to (int) or (string) ensures no array can be injected (an exception will be thrown so this is not a good practise)
$model = Post::findOne((int) Yii::$app->request->get('id'));
// explicitly specifying the colum to search, passing a scalar or array here will always result in finding a single record
$model = Post::findOne(['id' => Yii::$app->request->get('id')]);

Affected Code

The following code however is vulnerable, an attacker could inject an array with an arbitrary condition and even exploit SQL injection:

$model = Post::findOne(Yii::$app->request->get('id'));

For the above example, the SQL injection part is fixed with the patches provided in this release, but an attacker may still be able to search records by different condition than a primary key search and violate your application business logic. So passing user input directly like this can cause problems and should be avoided.

How do I Upgrade?

  1. Not Affected Code
  2. Affected Code

If you are using Yii 2.0.14:

composer require "yiisoft/yii2":"~2.0.15.0"

If you are using Yii 2.0.13:

composer require "yiisoft/yii2":"~2.0.13.2"

If you are using Yii 2.0.12:

composer require "yiisoft/yii2":"~2.0.12.1"

If you are using yii2-redis extension:

composer require "yiisoft/yii2-redis":"~2.0.8"

If you are using yii2-elasticsearch extension:

composer require "yiisoft/yii2-elasticsearch":"~2.0.5"

Update: We have since released further patches to lower the impact of the BC break introduced by the security fix, so you get versions 2.0.15.1, 2.0.13.3 and 2.0.12.2 from the above.

Upgrading isn't Enough!

  1. Not Affected Code
  2. Affected Code

Upgrading Yii addresses the SQL injection but doesn't make findOne() and findAll() safe in general. Check all usages of findOne() and findAll() in your application. Also note, that where() and filterWhere() never escape column names, so if you need to pass a variable as a column name, make sure it is safe.

]]>
0
[news] Imagine extension version 2.1.1 released Thu, 22 Feb 2018 22:47:48 +0000 https://www.yiiframework.com/news/167/imagine-extension-version-2-1-1-released https://www.yiiframework.com/news/167/imagine-extension-version-2-1-1-released samdark samdark

We are very pleased to announce the release of Imagine extension version 2.1.1 which both fixes bugs and makes small enhancements.

This release updates 'Imagine' dependency to include versions 0.7.x.

See CHANGELOG for details.

]]>
0
[news] Faker extension version 2.0.4 released Mon, 19 Feb 2018 20:36:11 +0000 https://www.yiiframework.com/news/166/faker-extension-version-2-0-4-released https://www.yiiframework.com/news/166/faker-extension-version-2-0-4-released samdark samdark

We are very pleased to announce the release of Faker extension version 2.0.4 which both fixes bugs and makes small enhancements.

See CHANGELOG for details.

]]>
0
[news] Yii 2.0.14 is released Thu, 08 Mar 2018 23:11:09 +0000 https://www.yiiframework.com/news/165/yii-2-0-14-is-released https://www.yiiframework.com/news/165/yii-2-0-14-is-released SilverFire SilverFire
  1. Scalability and concurrency
  2. Validator enhancements
  3. Behaviors
  4. Databases and ActiveRecord
  5. Error handling
  6. Security
  7. PHP 7.2
  8. Widgets, forms and clientside
  9. Events
  10. APIs, serializers and filters
  11. Console
  12. Routing
  13. i18n
  14. Helpers
  15. DI container
  16. Project templates
  17. Preparing for 2.1

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

Version 2.0.14 is a minor release of Yii 2.0 which contains more than a hundred enhancements and bug fixes including security fixes. It is also the last version of Yii 2.0 that contains enhancements. This means that we will focus on including new features into the 2.1.x branch and 2.0.x will only receive bug fixes from now on. We will make an announcement on the time frames for supporting different branches with the release of version 2.1.

There are minor changes that may affect your existing applications, so make sure to check the UPGRADE.md file.

Thanks to all Yii community members who contribute to the framework. We did it together!

You may follow the development progress of Yii 2 by starring or watching Yii 2.0 GitHub Project. There are many active Yii communities so if you need help or want to share your experience, feel free to join them.

Since there is Yii 2.1 in development now, make sure you have a version constraint in your composer.json, that does not allow it to be installed automatically on update, so when next major version of Yii is released, your project won't break by itself. A version constraint that does not include 2.1 is for example ~2.0.14, make sure you do not have >= or * in version constraints in composer.json.

Below we summarize some of the most important features/fixes included in this release. A complete list of changes can be found in the CHANGELOG.

Scalability and concurrency

While not important at early project stages, scalability and concurrency issues are major obstacles for business growth. In this release we have identified and fixed a concurrency issue when writing values and regenerating IDs in yii\web\DbSession and three issues that may appear in master-slave setups while using yii\web\DbSession, yii\validators\UniqueValidator and yii\validators\ExistValidator.

Validator enhancements

Additionally to what's mentioned in previous section, there are enhancements in built-in validators.

First, the ExistValidator is now able to check relations when its new targetRelation property is set. That basically means the following rules definition is now possible:

public function rules()
{
    return [
        [['customer_id'], 'exist', 'targetRelation' => 'customer'],
    ];
}

public function getCustomer()
{
    return $this->hasOne(Customer::class, ['id' => 'customer_id']);
}

Another enhancement is about FileValidator. It got a new property called minFiles to specify the minimum number of files a user must upload.

Behaviors

yii\behaviors\BlameableBehavior got a defaultValue property that is used in case user ID could not be determined. That is often the case when Active Record model is used within console application.

New yii\behaviors\AttributeTypecastBehavior property typecastAfterSave could be set to true to make values typecasted after model is saved. That makes attribute types consistent if they're casted when saved to database.

New yii\behaviors\CacheableWidgetBehavior was added. It automatically caches widget contents according to duration and dependencies specified and could be added to a widget like the following:

use yii\behaviors\CacheableWidgetBehavior;

public function behaviors()
{
  return [
      [
          'class' => CacheableWidgetBehavior::className(),
          'cacheDuration' => 0,
          'cacheDependency' => [
              'class' => 'yii\caching\DbDependency',
              'sql' => 'SELECT MAX(updated_at) FROM posts',
          ],
      ],
  ];
}

Databases and ActiveRecord

This release adds lots of great things related to databases and ActiveRecord that were worked by Dmitry Naumenko, Sergey Makinen, Robert Korulczyk, Nikolay Oleynikov and other community members.

Custom data types and object conditions

Custom data types support was implemented. Added JSON support for MySQL and PostgreSQL and arrays support for PostgreSQL. In order to do that, Query Builder internals were refactored significantly and now support object format for conditions:

$query->andWhere(new OrCondition([
    new InCondition('type', 'in', $types),
    ['like', 'name', '%good%'],
    'disabled=false',
]));

There are two good things about it. First, it's easier to support existing conditions and add new ones for Yii team. Additionally to conditions for JSON and arrays, it already resulted in a new BetweenColumnsCondition. There could be more added in Yii 2.1. Second, it's convenient to add custom conditions now.

Query Builder flexibility

Query Builder flexibility was improved overall. It is now possible to pass yii\db\Query anywhere, where yii\db\Expression was supported. For example, it is now possible to use it like the following:

$subquery = (new Query)
    ->select([new Expression(1)])
    ->from('tree')
    ->where(['parent_id' => 1, 'id' => new Expression('tree.parent_id']));

(new Query())
    ->from('tree')
    ->where(['or', 'parent_id = 1', $subquery])
Upserts

Another big thing is upserts for all databases Yii database layer supports. Upsert is an atomic operation that inserts rows into a database table if they do not already exist (matching unique constraints), or update them if they do:

Yii::$app->db->createCommand()->upsert('pages', [
    'name' => 'Front page',
    'url' => 'http://example.com/', // URL is unique
    'visits' => 0,
], [
    'visits' => new \yii\db\Expression('visits + 1'),
], $params)->execute();

Will either insert a new page record or increment its visit counter atomically.

Schema builder and migrations

Schema builder now supports tiny integer and JSON so you can use the following in migrations:

$this->createTable('post', [
    'id' => $this->primaryKey(),
    'text' => $this->text(),
    'title' => $this->string()->notNull(),
    'attributes' => $this->json(),
    'status' => $this->tinyInteger(),
]);

Another enhancement about migrations is the ability to create and drop database views:

$this->createView(
    'top_10_posts',
    (new \yii\db\Query())
        ->from('post')
        ->orderBy(['rating' => SORT_DESC])
        ->limit(10)
);

$this->dropView('top_10_posts');
New query caching syntax

It was possible before to wrap DB calls with connection's cache method. Now there are handy shortcuts:

// at query level
(new Query())->cache(7200)->all();

// at AR level
User::find()->cache(7200)->all();
Active Record relations

Active Record now resets related models after corresponding attribute updates:

$item = Item::findOne(1);
echo $item->category_id; // 1
echo $item->category->name; // weapons

$item->category_id = 2;
echo $item->category->name; // toys

Error handling

Log targets now throw exception in case log can't be exported properly. Previously they were failing silently.

Another case where Yii is now throwing yii\web\HeadersAlreadySentException exception instead of being silent if headers were already sent before (thus, it's not possible to send more).

It is now possible to configure Yii error handler via setting $traceLine property to generate links in the exception code so these could be opened directly in IDE. Configuration is similar to debug toolbar:

'components' => [
    // ...
    'errorHandler' => [
        'errorAction' => 'site/error',
        'traceLine' => '<a href="ide://open?url={file}&line={line}">{html}</a>',
    ],
],

Using yii\web\ErrorAction::$layout property you can set layout from error action config conveniently:

class SiteController extends Controller
{
    // ...
    /**
     * @inheritdoc
     */
    public function actions()
    {
        return [
            'error' => [
                'class' => 'yii\web\ErrorAction',
                'layout' => 'error', // <-- HERE
        ],
    ];
}

Security

There are two vulnerabilities discovered and fixed in this release:

  • CVE-2018-6009. The switchIdentity() function in web/User.php did not regenerate the CSRF token upon a change of identity.
  • CVE-2018-6010. Remote attackers could obtain potentially sensitive information from exception messages printed by the error handler in non-debug mode.

PHP 7.2

This release brings full PHP 7.2 compatibility. We have adjusted yii\filters\HttpCache, FileHelper::getExtensionsByMimeType() and yii\web\Session to work well with all PHP versions we support.

Widgets, forms and clientside

Markup generated for <script> tag doesn't have type attribute anymore. Additionally to better looking, it makes HTML5 markup validator happy.

In form active fields (for both Active Form and Html helper) you can now automatically include placeholder that matches field's attribute:

<?=  Html::activeTextInput($post, 'title', ['placeholder' => true]) ?>

Another thing added to ActiveForm is an ability to choose which HTML element receives validation state classes:

<?php $form = ActiveForm::begin([
    'validationStateOn' => ActiveForm::VALIDATION_STATE_ON_INPUT,
]) ?>

That possibly allows Yii bootstrap extension to adopt Bootstrap 4.

It's now possible to register JavaScript variables via PHP code:

class SiteController extends Controller
{
    public function actionIndex()
    {
        $this->view->registerJsVar('username', 'SilverFire');
        return $this->render('index');
    }
}

While it is widely used method of passing data from PHP to JavaScript, before using it consider HTML5 data attributes.

Events

Paul Klimov added wildcard matching to events so it's now possible to subscribe to multiple objects or class events that match the pattern. That is very useful for logging and audit. Brand new section in the guide is full of examples using the feature.

APIs, serializers and filters

When configuring JsonResponseFormatter you can now specify content type:

'components' => [
    'response' => [
        // ...
        'formatters' => [
            \yii\web\Response::FORMAT_JSON => [
                'class' => \yii\web\JsonResponseFormatter::className(),
                'contentType' => \yii\web\JsonResponseFormatter::CONTENT_TYPE_HAL_JSON,
            ],
        ],
    ],
]

Data filter can now handle lt,gt,lte and gte on yii\validators\DateValidator.

yii\base\ArrayableTrait::toArray() now allows recursive $fields and $expand. That means REST APIs queries expand could be specified now as extra1.extra2 and that would expand extra1 in the original data set and then extra2 in extra1 data set i.e. queries like http://localhost/comments?expand=post.author are possible.

In case you need to convert model validation errors into JSON you may use \yii\helpers\Json::errorSummary() now.

Custom authentication headers are now easier to set up thanks to added yii\filters\auth\HttpHeaderAuth.

Console

How many times you wished there was a built-in method to print model validation errors into console instead of doing foreach? Now there is one:

if (!$model->validate()) {
    echo "Model is not valid:\n";
    echo \yii\helpers\Console::errorSummary($model);
    return ExitCode::DATAERR;
}

bash and zsh command completion got better. Now it understands ./yii help.

When invoking a command options could now be specified as both camelCase and kebab-case i.e. --selfUpdate and --self-update. Moreover, in addition to --<option>=<value> console optios syntax, it's now possible to use --<option> <value> syntax.

Routing

Short verb syntax could now be used in URL rule groups:

'components' => [
    'urlManager' => [
        // ...
        'rules' => [
            new GroupUrlRule([
                'prefix' => 'file',
                'rules' => [
                    'POST document' => 'document/create',
                ],
            ]),
    ],
],

i18n

New yii\i18n\Locale component was added having getCurrencySymbol() method that is able to get currency symbol for a given locale.

Helpers

This release brings very interesting enhancements to Yii helpers.

yii\helpers\FileHelper got two new methods. findDirectories() returns the directories found under the specified directory and subdirectories. It is similar to existing findFiles() but works with directories. unlink() removes a file or symlink in a cross-platform way which proved to be tricky.

yii\helpers\StringHelper got a new matchWildcard() method that does the same as native fnmatch() but does it consistently among different OS. Native one proved to differ from system to system.

yii\helpers\IpHelper was added. It allows determining IP version by address, comparing address against a mask or range, and expanding IPv6. Usage is simple and convenient:

if (!IpHelper::inRange($ip, '192.168.1.0/24')) {
    // deny access
}

DI container

Container got an ability to reuse definitions as properties:

'container' => [
    'definitions' => [
        \console\models\TestService::class => [
            'class' => \console\models\TestService::class,
            'model' => Instance::of(\console\models\TestModel::class)
        ],
        \console\models\TestModel::class => [
            'class' => \console\models\TestModel::class,
            'property' => 20,
        ],
    ],
],

In the code above the model property of TestService will be set with an instance of TestModel class configured in the container.

Project templates

Additionally to minor adjustments basic project template got Docker and vagrant support.

Preparing for 2.1

Brandon Kelly proposed a very good idea to mark some methods and classes that were already removed in 2.1 as deprecated. That should make transition from 2.0 to 2.1 easier:

  • Deprecated yii\base\BaseObject::className() in favor of native PHP syntax ::class, which does not trigger autoloading (only works with PHP >=5.5).
  • Deprecated XCache and Zend data cache support as caching backends.
  • Deprecated yii\BaseYii::powered() method.
  • Added yii\base\InvalidArgumentException and deprecated yii\base\InvalidParamException.
  • Added yii\BaseYii::debug() and deprecated yii\BaseYii::trace().

Code using these methods would work as usual except that IDEs will mark it deprecated.

]]>
0
[news] Bootstrap extension version 2.0.8 released Fri, 16 Feb 2018 18:37:06 +0000 https://www.yiiframework.com/news/164/bootstrap-extension-version-2-0-8-released https://www.yiiframework.com/news/164/bootstrap-extension-version-2-0-8-released samdark samdark

We are very pleased to announce the release of Bootstrap extension version 2.0.8 which both fixes bugs and makes small enhancements.

See CHANGELOG for details.

]]>
0
[news] MongoDB extension 2.1.5 released Tue, 13 Feb 2018 16:05:45 +0000 https://www.yiiframework.com/news/163/mongodb-extension-2-1-5-released https://www.yiiframework.com/news/163/mongodb-extension-2-1-5-released samdark samdark

We are very pleased to announce the release of MongoDB extension version 2.1.6 which brings two bug fixes:

  • Fixed yii\mongodb\Command::aggregate() without 'cursor' option produces error on MongoDB Server 3.6
  • Fixed yii\mongodb\Collection::dropIndex() unable to drop index specified with sort via index plugin

See CHANGELOG for details.

]]>
0
[news] Sphinx extension 2.0.10 released Tue, 13 Feb 2018 16:05:52 +0000 https://www.yiiframework.com/news/162/sphinx-extension-2-0-10-released https://www.yiiframework.com/news/162/sphinx-extension-2-0-10-released samdark samdark

We are very pleased to announce the release of Sphinx extension version 2.0.10 which brings 4 enhancements and bug fixes:

  • Fixed yii\sphinx\Schema::findColumns() unable to merge field and attribute columns with same name
  • Fixed yii\sphinx\QueryBuilder::buildInCondition() incompatibility with PHP 7.2
  • yii\sphinx\QueryBuilder::callSnippets() now automatically casts snippet source to string
  • yii\sphinx\QueryBuilder now supports Traversable objects for use in in conditions

See CHANGELOG for details.

]]>
0
[news] Http Client extension 2.0.6 released Tue, 13 Feb 2018 16:06:00 +0000 https://www.yiiframework.com/news/161/http-client-extension-2-0-6-released https://www.yiiframework.com/news/161/http-client-extension-2-0-6-released samdark samdark

We are very pleased to announce the release of HTTP client extension version 2.0.6 which brings an enhancement and a bug fix:

  • Fixed Message::getHeaders() unable to parse HTTP status code in case reason phrase contains : character
  • Request::createFullUrl() now prevents appearance of multiple slashes while combining Client::$baseUrl and Request::$url

See CHANGELOG for details.

]]>
0
[news] Auth Client extension 2.1.5 released Wed, 07 Feb 2018 21:19:53 +0000 https://www.yiiframework.com/news/160/auth-client-extension-2-1-5-released https://www.yiiframework.com/news/160/auth-client-extension-2-1-5-released samdark samdark

We are very pleased to announce the release of Auth Client extension version 2.1.5 which brings 3 enhancements and bug fixes:

  • Updated endpoint URLs for LinkedIn.
  • AuthAction refactored to use yii\web\Application::$request for request data access.
  • Added yii\authclient\AuthAction::$cancelCallback allowing custom handling for authentication cancellation.

See the CHANGELOG for details.

]]>
0
[news] Portland Yii Framework Programmers Meetup Tue, 09 Jan 2018 07:44:01 +0000 https://www.yiiframework.com/news/159/portland-yii-framework-programmers-meetup https://www.yiiframework.com/news/159/portland-yii-framework-programmers-meetup samdark samdark

Jeff Reifman started Yii meetup in Portland, Oregon.

First one will take place Tuesday, January 16, 2018 6:30 PM to 8:30 PM at Palio 1996 SE Ladd Av.

If you're nearby, join it. Here's meetup page at meetup.com.

]]>
0
[news] Queue Extension 2.0.2 released Tue, 26 Dec 2017 17:34:43 +0000 https://www.yiiframework.com/news/158/queue-extension-2-0-2-released https://www.yiiframework.com/news/158/queue-extension-2-0-2-released samdark samdark

We have released version 2.0.2 of the Queue extension. This version is fixing bugs as well as adding some enhancements.

New AMQP Interop driver added. It allows you to seamlessly use many drivers queue interop project supports.

There are new events: cli\Queue::EVENT_WORKER_START and cli\Queue::EVENT_WORKER_STOP. These allow you to add handlers to worker start and stop.

It's now possible to redefine exit code that is useful for connecting workers with Supervisord or Systemd.

LoopInterface and its SignalLoop implementation were added in order to handle posix-signals. Out of the box SignalLoop provides an ability to exit the loop using a signal. Also it supports querying delays. Exit, pause and resume signals are configurable as well.

New events and LoopInterface are supported by all CLI drivers except AMQP and AMQP Interop.

]]>
0
[news] Gii extension version 2.0.6 released Fri, 22 Dec 2017 23:56:28 +0000 https://www.yiiframework.com/news/157/gii-extension-version-2-0-6-released https://www.yiiframework.com/news/157/gii-extension-version-2-0-6-released samdark samdark
  1. Overall
  2. CRUD generator
  3. Model generator

We are very pleased to announce the release of Gii extension version 2.0.6. In this release there are many bug fixes and, of course, some enhancements:

Overall

  • PHP 7.1 compatibility.
  • Aliases could now be used in generator's templates.
  • Added filename filter to generated files list preview.
  • Added meta tag to prevent indexing of debug by search engines in case it's exposed.

CRUD generator

There are changes in the code generated:

  • There are now @throws tags for 404 exceptions.
  • NotFoundHttpException message uses i18n.
  • Redundant else after return removed.
  • Removed space from commented out code so when uncommenting in IDEs there's no extra spacing.
  • Submit button label was changed from "Update" and "Create" to "Save".
  • Changed the way CRUD generator translates "Update X id". Now it's a whole string because of translation difficulties.

Model generator

"Use Table Prefix" and "Generate ActiveQuery" options are now sticky. Additionally, generation itself was improved:

  • PostgreSQL got default validator with null value for integers in the model and ilike operator in search model.
  • int and bool are used instead of integer and boolean.
  • FK detection can now recognize id_something additionally to existing something_id.
  • There's an option now to generate relations only for current schema. It's useful for Oracle and MSSQL where reading schema is slow.
  • Table comments could now be used for PHPdoc property description.
  • Unique validation rule is now generated for tables with multiple primary keys.

See CHANGELOG for details.

Thanks to all contributors who participated in this release.

]]>
0
[news] Yii 2.1 and Yii 2.0 feature freeze Sun, 17 Dec 2017 09:56:24 +0000 https://www.yiiframework.com/news/156/yii-2-1-and-yii-2-0-feature-freeze https://www.yiiframework.com/news/156/yii-2-1-and-yii-2-0-feature-freeze samdark samdark

We have good news for you. We are going to work more on Yii 2.1. Yii 2.0.14 release, that should happen in first months of 2018, will be last release that adds features and enhancements to 2.0 branch.

After 2.0.14 release:

  1. We are not accepting any features or enhancements in 2.0 branch.
  2. We are merging 2.0 into 2.1 once and not merging it again.
  3. Bug-fixes are accepted.
]]>
0
[wiki] Yii2 RESTful API with OAuth 2.0 Sun, 25 Mar 2018 02:00:49 +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://yii2-rest.dockerboxes.us

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

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 resize an image proportionally Wed, 14 Jun 2017 18:30:28 +0000 https://www.yiiframework.com/wiki/859/how-to-resize-an-image-proportionally https://www.yiiframework.com/wiki/859/how-to-resize-an-image-proportionally androidelp androidelp

Using the imagine extension is very simple Create this in your component:

/**     * @author André Luiz Pereira
     * @param string $ pathtoimage image the relative path: to/path/image.jpg
     * @param int $width – max width to resize 
     * @param int $height – max height to resize
     * @param int $quality – Image quality default 80
     * @return void
     */
    public function ImageProporcional($pathtoimage, $width, $height, $quality = 80) {
        $pathConstruct = \yii\helpers\Url::to('@webroot/' . $pathtoimage);
        $imagem = \yii\imagine\Image::getImagine();
        $getimg = $imagem->open($pathConstruct);
        $size = new \Imagine\Image\Box($width, $height);
      // We created the thumbnail with the data defined in the box
        $resizeimg = $getimg->thumbnail($size, \Imagine\Image\ImageInterface::THUMBNAIL_INSET);
       // Get real size
        $sizeR = $resizeimg->getSize();
        $widthR = $sizeR->getWidth();
        $heightR = $sizeR->getHeight();
        $preserve = $imagem->create($size);

        $startX = $startY = 0;
if ($widthR < $width) {
            $startX = ( $width - $widthR ) / 2;
        }

        if ($heightR < $height) {
            $startY = ( $height - $heightR ) / 2;
        }
        $preserve->paste($resizeimg, new \Imagine\Image\Point($startX, $startY))->save($pathConstruct, ['quality' => $quality]);

    }

This simple code resizes and modifies image quality in the $pathtoimage variable, $width and $ height being the maximum values, resizing is only applied if the actual image size is larger than the size defined in the method "ImageProportional"

Follow the example criação de sites.

Seguir Facebook.

]]>
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
[wiki] Working with relational removals by yii2 Mon, 05 Jun 2017 03:57:13 +0000 https://www.yiiframework.com/wiki/856/working-with-relational-removals-by-yii2 https://www.yiiframework.com/wiki/856/working-with-relational-removals-by-yii2 androidelp androidelp

This tutorial shows you how to safely remove records between relationships.

First we create three tables using a Many to Many relationship.

Imagem da relacao

Important: Apply cascade to foreign key constraints for update and delete.

The cascade feature will allow you to remove the foreign keys along with the line you want to delete and helps keep your code to a minimum.

Script SQL the ralation has.

CREATE TABLE `tests_has_games` (
   `tests_id` int(11) NOT NULL,
   `games_id` int(11) NOT NULL,
   PRIMARY KEY (`tests_id`,`games_id`),
   KEY `fk_tests_has_games_games1_idx` (`games_id`),
   KEY `fk_tests_has_games_tests_idx` (`tests_id`),
   CONSTRAINT `fk_tests_has_games_games1` FOREIGN KEY (`games_id`) REFERENCES `games` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
   CONSTRAINT `fk_tests_has_games_tests` FOREIGN KEY (`tests_id`) REFERENCES `tests` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

Step 2: Create models: (to use generator gii, this system create model with relations of the table). ModelGames:

public function getTestsHasGames()
    {
        return $this->hasMany(TestsHasGames::className(), ['games_id' => 'id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getTests()
    {
        return $this->hasMany(Tests::className(), ['id' => 'tests_id'])->viaTable('{{%tests_has_games}}', ['games_id' => 'id']);
    }

Model Tests:

public function getTestsHasGames()
    {
        return $this->hasMany(TestsHasGames::className(), ['tests_id' => 'id']);
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getGames()
    {
        return $this->hasMany(Games::className(), ['id' => 'games_id'])->viaTable('{{%tests_has_games}}', ['tests_id' => 'id']);
    }

Step 3: Simple Removal Functions in controllers:

public function actionDeletarTest($id)
  {

    $session = \Yii::$app->session;

    $testes = Tests::findOne($id);

    if($testes->delete())
    {
      $session->addFlash('resposta', [
        'type'=>'success',
        'msg'=>'Teste deletado com sucesso.'
      ]);
    }else{
      $session->addFlash('resposta', [
        'type'=>'danger',
        'msg'=>'Erro encontrado favor resolver.'
      ]);
    }

    return $this->redirect(['site/delete-relations']);

  }

Other Methods

public function actionDeleteListGames()
  {
    $array_id = [1,2,3,4];

    $games = Games::find()->where(['in','id',$array_id])->all();

    foreach($games as $k => $game)
    {
      $game->delete();
    }

  }
     // deletando de vinculo
     public function actionDeleteTestAll()
     {
       $game = Games::findOne(1);
       foreach($game->tests as $test)
       {
          $test->delete();
       }
     }


public function actionDeleteTheRelation($id)
  {


    $game = Games::find()->joinWith(['tests'=>function($q){
      return $q->where(['like','nome','proccess'])
    }])->where(['id'=>$id])->one();

    foreach($games->tests as $k => $test)
    {
      $test->delete();
    }

  }

Get All code in Your text to link here...

]]>
0
[wiki] Interactive mode command-line command for Yii1 Mon, 21 Nov 2016 12:41:10 +0000 https://www.yiiframework.com/wiki/854/interactive-mode-command-line-command-for-yii1 https://www.yiiframework.com/wiki/854/interactive-mode-command-line-command-for-yii1 trejder trejder

For one of my projects I needed an interactive console command in Yii 1, i.e. the one that is gathering all information from user in an interactive mode (a serie of questions and answers displayed directly in the console), ignoring command-line arguments at all.

This is an example (or rather a bare foundation, as this actually is doing nothing) of such solution. It has some console text formatting methods (borders, text alignment) plus simple method for gathering user response.

The code

Here is an implementation for Yii 1 of mentioned solution.

class ImportCommand extends CConsoleCommand
{
    const BORDER_WIDTH = 80;

    public function actionIndex($args)
    {
        $message = $this->alignText('This text is aligned to the right border...', 'right')."\n";
        $message .= "\n";
        $message .= $this->alignText('...this one is centered...', 'center')."\n";
        $message .= "\n";
        $message .= $this->alignText('...and this is left as is, so aligned to the left border!', 'left')."\n";
        $message .= "\n\n";
        $message .= $this->alignText('Finally we have a really long text, no matter, how aligned, that is going to be cut right there, where it should');

        $this->drawBorder($message);

        $this->readStdin();

        echo 'You selected: '.$this->readStdin('Enter any alphabet letter, please...');
        
        $this->clearStdin();
    }

    /**
     * Aligns text to given margin.
     * 
     * @param  string $text       Text to be aligned.
     * @param  string $align      Align method: 'right', 'center' or 'left' (default == empty string).
     * @param  integer $lineWidth Maximim line width. If not specified, class' constant will be used instead.
     * 
     * @return string             Aligned text, pad with trailing and following spaces.
     */
    public function alignText($text, $align = 'left', $lineWidth = null)
    {
        $lineWidth = is_null($lineWidth) ? self::BORDER_WIDTH : $lineWidth;
        $lineWidth = $lineWidth - 4;

        $text = strlen($text) > $lineWidth ? substr($text, 0, $lineWidth) : $text;

        if($align === 'right')
        {
            return str_repeat(' ', $lineWidth - strlen($text)).$text;
        }

        if($align === 'center')
        {
            $margin = floor($lineWidth  / 2) - floor(strlen($text) / 2);

            return str_repeat(' ', $margin).str_pad($text, $margin , ' ');
        }
        else return $text;
    }

    /**
     * Draws console-like (DOS-like?) text border around passed text.
     * 
     * @param  string $text       Text to be outlined in a fancy-like text border.
     * @param  integer $lineWidth Maximim width of each border line. See above for details.
     */
    public function drawBorder($text, $lineWidth = null)
    {
        $lineWidth = is_null($lineWidth) ? self::BORDER_WIDTH : $lineWidth;
        $lineWidth = $lineWidth > 80 ? 80 : $lineWidth;

        $nl = $lineWidth === 80 ? '' : "\n";

        echo str_repeat('*', $lineWidth).$nl;

        echo '*'.str_repeat(' ', $lineWidth - 2).'*'.$nl;

        foreach(explode("\n", $text) as $line) echo '* '.str_pad($line, $lineWidth - 4, ' ').' *'.$nl;

        echo '*'.str_repeat(' ', $lineWidth - 2).'*'.$nl;

        echo str_repeat('*', $lineWidth).$nl;
    }

    /**
     * Get user entry / decision.
     * 
     * @param  string $message Information to be displayed, when requiring user to enter something.
     * 
     * @return string          User entry.
     */
    public function readStdin($message = 'Continue [Y/N]?')
    {
        echo $message;

        $handle = fopen("php://stdin","r");
        $line = fgets($handle);

        return trim($line);
    }
    
    /**
     * Clears console window.
     *
     * The implementation used here can't be anymore ugly, but it is the only one,
     * that is working, when using GitBash. All other methods fails:
     *
     * http://stackoverflow.com/a/24327758/1469208
     * http://stackoverflow.com/a/29193143/1469208
     */
    public function clearStdin()
    {
        for ($i = 0; $i < 50; $i++) echo "rn";
    }
}

Execution

To get this thing working, put all the above code in a separate .php file and save it to protected/commands path under ImportCommand.php name.

Then open console window, navigate to protected folder in your application and execute:

yiic import

Of course, rename both file and class name, if you want to use this command under different name.

Also make sure that you have set correctly everything around running console commands.

]]>
0
[wiki] REST API and null values in XML Fri, 11 Nov 2016 00:26:44 +0000 https://www.yiiframework.com/wiki/853/rest-api-and-null-values-in-xml https://www.yiiframework.com/wiki/853/rest-api-and-null-values-in-xml marko60 marko60

I have been working on a REST API using the excellent tools provided by Yii2. My problem was that I have to differentiate between empty values and null values. In other words, <elem></elem> is different from null as it represents an empty string. Also, although some use <elem/> to represent a null value it should still be interpreted as an empty string. In other cases, the absence of the element is taken to represent a null value, but this may create problem with some parsers.

After some research, it appears that the correct way of describing a null value is <elem xsi:nil="true"/>.

However this is not supported by the current implementation of XmlResponseFormatter because values are always appended as DOMText. This means that, even is I pass a PHP null value, I get <elem></elem>.

Therefore, I have extended XmlResponse Formatter as follows.

Firstly, the function format() must be modified because creating $root as DOMElement makes it immutable while I need to attach the xsi: namespace definition. Therefore I use:

...
$dom = new DOMDocument($this->version, $charset);
// A writeable element is created and the namespace added
$root = $dom->createElement($this->rootTag);
$root->setAttributeNS('http://www.w3.org/2000/xmlns/' ,'xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
$dom->appendChild($root);
...

Then I have modified the buildXml function as follows:

protected function buildXml($element, $data){
  if (is_array($data) ||
    ($data instanceof \Traversable && $this->useTraversableAsArray && !$data instanceof Arrayable)
  ) {
    foreach ($data as $name => $value) {
      if (is_int($name) && is_object($value)) {
        $this->buildXml($element, $value);
      } elseif (is_array($value) || is_object($value)) {
        $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
        $element->appendChild($child);
        $this->buildXml($child, $value);
      } else {
        $child = new DOMElement(is_int($name) ? $this->itemTag : $name);
        $element->appendChild($child);
        // Checks if the value is null and creates a null MXL element
        if ($value === null) {
          $child->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance','xsi:nil','true');
        } else {
          $child->appendChild(new DOMText((string) $value));
        }
      }
    }
  } elseif (is_object($data)) {
    $child = new DOMElement(StringHelper::basename(get_class($data)));
    $element->appendChild($child);
    if ($data instanceof Arrayable) {
      $this->buildXml($child, $data->toArray());
    } else {
      $array = [];
      foreach ($data as $name => $value) {
        $array[$name] = $value;
      }
      $this->buildXml($child, $array);
    }
  } else {
    // Checks if $data is null and adds xsi:nil to $element
    if ($data === null) {
      $element->setAttributeNS('http://www.w3.org/2001/XMLSchema-instance','xsi:nil','true');
    } else {
      $element->appendChild(new DOMText((string) $data));
    }
  }
}

This way, if the value of the XML element is null, I get <element xsi:nil="true"/> which is more correct while, if the value is an empty string, I get <element></element> as expected.

I hope this would be useful to somebody and maybe the Yii2 could consider this improvement in a future release.

]]>
0
[wiki] Optimize Scenarios for yii2 Thu, 12 Apr 2018 13:24:16 +0000 https://www.yiiframework.com/wiki/852/optimize-scenarios-for-yii2 https://www.yiiframework.com/wiki/852/optimize-scenarios-for-yii2 androidelp androidelp

Working with scenarios, with models that can receive many modifications in their rules or structures as development evolves, can create disruptions in the rescue process.

One way to avoid this disorder is to encapsulate the information defined for the scenarios and to have a single point of customization.

For this we need to create constants for each scenario, note: once you define a scenario, you will need to use scenarios for any database edition that uses this model.

In model

class MyModel extends \yii\db\ActiveRecord
{

  const SCENARIOCRIATE = 'scenariocriate';
  const SCENARIOUPDATE = 'scenarioupdate';

    // scenarios encapsulated
    public function getCustomScenarios()
    {
      
      return [
          self::SCENARIOCRIATE      =>  ['user_id', 'name', 'desc', 'published','date_create'],
          self::SCENARIOUPDATE      =>  ['user_id', 'name', 'desc', 'date_update'],
      ];
    }
    // get scenarios
    public function scenarios()
    {
        $scenarios = $this->getCustomScenarios();
        return $scenarios;
    }

    // modify itens required for rules
    public function ModifyRequired()
    {

      $allscenarios = $this->getCustomScenarios();
      // published not required
      $allscenarios[self::SCENARIOCRIATE] = array_diff($allscenarios[self::SCENARIOCRIATE], ['published']);
      return $allscenarios;

    }

    public function rules()
    {
      // get scenarios
      $allscenarios = $this->ModifyRequired();
        return [
            [$allscenarios[self::SCENARIOCRIATE], 'required', 'on' => self::SCENARIOCRIATE],
            [$allscenarios[self::SCENARIOUPDATE], 'required', 'on' => self::SCENARIOUPDATE],
            [['user_id'], 'integer'],
            [['name','desc'], 'string', 'max' => 70],
            [['date_create', 'date_update'], 'date', 'format' => 'php:Y-m-d H:i:s'],
        ];
    }

GetCustomScenarios will be used for when you need to make column modifications.

The ModifyRequired is used to remove from the required, because at this point will be used getCustomScenarios for the save.

In Controller

public function actionIndex()
{

    $model = new MyModel;
    $model->scenario = 'scenariocriate';

    if ($model->load(\Yii::$app->request->post())){

        // force my columns
        if($model->save()){
          //return true
        } 
    }
}

It may seem redundant, but constructing the controller in this way, avoids having problems with maintenance of database tables, the adjustments will be made only in the model, since there is no reference of communes in the controller.

]]>
0
[wiki] Yii2 GridView Sorting and Searching with a Junction Table Column(Many to Many Relationship) Tue, 08 Nov 2016 02:34:38 +0000 https://www.yiiframework.com/wiki/851/yii2-gridview-sorting-and-searching-with-a-junction-table-columnmany-to-many-relationship https://www.yiiframework.com/wiki/851/yii2-gridview-sorting-and-searching-with-a-junction-table-columnmany-to-many-relationship Amjad Khan Amjad Khan
  1. tblgroups
  2. tblcontacts
  3. tblcontactsgroups(junction table)

Following is the table structure

tblgroups

CREATE TABLE IF NOT EXISTS `tblgroups` (
  `id` int(11) NOT NULL,
  `groupname` varchar(150) NOT NULL,
  `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Acitve,2=Inactive',
  `date` datetime NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

tblcontacts

CREATE TABLE IF NOT EXISTS `tblcontacts` (
  `id` int(11) NOT NULL,
  `firstname` varchar(100) NOT NULL,
  `lastname` varchar(100) NOT NULL,
  `company` varchar(100) NOT NULL,
  `address` text NOT NULL,
  `phone` varchar(50) NOT NULL,
  `mobile` varchar(50) NOT NULL,
  `fax` varchar(50) NOT NULL,
  `pemail` varchar(100) NOT NULL,
  `semail` varchar(100) NOT NULL,
  `country` varchar(55) NOT NULL,
  `websiteurl` varchar(100) NOT NULL,
  `gender` tinyint(4) NOT NULL COMMENT '1=male,2=female,3=shemale',
  `birthday` varchar(10) NOT NULL,
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1=Active,2=Inactive',
  `sentstatus` tinyint(4) NOT NULL DEFAULT '1' COMMENT '1=sent,2=not sent',
  `addeddate` datetime NOT NULL,
  `updateddate` datetime NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

tblcontactsgroups(junction table)

CREATE TABLE IF NOT EXISTS `tblcontactsgroups` (
  `id` int(11) NOT NULL,
  `contact_id` int(11) NOT NULL,
  `group_id` int(11) NOT NULL,
  `dateadded` datetime NOT NULL
) ENGINE=MyISAM AUTO_INCREMENT=20085 DEFAULT CHARSET=latin1;

First of all with the help of gii crud generators we will create the crud for all these tables including models and controllers,tblcontactsgroups is the table having many to many relation between tblcontacts and tblgroups. In the Contacts Model generated from tblcontacts we will use the hasMany relationship as follows

public function getGroups() {
        return $this->hasMany(Groups::className(), ['id' => 'group_id'])->viaTable('tblcontactsgroups', ['contact_id' => 'id']);
    }

In Groups model we will insert the following code

public function getContacts() {
        return $this->hasMany(Contacts::className(), ['id' => 'contact_id'])->viaTable('tblcontactsgroups', ['group_id' => 'id']);
    }

The most important model is the ContactsSearch Model we will make the following changes in it first of all we declare the groupname(related groups table attribute) public property in ContactsSearch Model

class ContactsSearch extends Contacts {

    /**
     * @inheritdoc
     */
    // public group_id;
    public $groupname;
............................

we will also include groupname in the rules

public function rules() {
        return [
            [['id', 'gender', 'status', 'sentstatus'], 'integer'],
            [['firstname', 'lastname', 'company', 'address','groupname', 'phone', 'mobile', 'fax', 'pemail', 'semail', 'country', 'websiteurl', 'birthday', 'addeddate', 'updateddate'], 'safe'],
        ];
    }

and then we will manipulate the search method in ContactsSearch Model like this

public function search($params) {
        $query = Contacts::find()->innerJoinWith('groups', true);
        $dataProvider = new ActiveDataProvider([
            'query' => $query,
            'sort' => ['attributes' => ['firstname', 'lastname', 'groupname', 'email', 'pemail']]
        ]);

        $this->load($params);
        if (!$this->validate()) {
            // uncomment the following line if you do not want to return any records when validation fails
            // $query->where('0=1');
            return $dataProvider;
        }

        // grid filtering conditions
        $query->andFilterWhere([
            'id' => $this->id,
            'gender' => $this->gender,
            'status' => $this->status,
            'sentstatus' => $this->sentstatus,
            'addeddate' => $this->addeddate,
            'updateddate' => $this->updateddate,
        ]);

        $query->andFilterWhere(['like', 'firstname', $this->firstname])
                ->andFilterWhere(['like', 'lastname', $this->lastname])
                ->andFilterWhere(['like', 'company', $this->company])
                ->andFilterWhere(['like', 'address', $this->address])
                ->andFilterWhere(['like', 'phone', $this->phone])
                ->andFilterWhere(['like', 'mobile', $this->mobile])
                ->andFilterWhere(['like', 'fax', $this->fax])
                ->andFilterWhere(['like', 'pemail', $this->pemail])
                ->andFilterWhere(['like', 'semail', $this->semail])
                ->andFilterWhere(['like', 'country', $this->country])
                ->andFilterWhere(['like', 'websiteurl', $this->websiteurl])
                ->andFilterWhere(['like', 'birthday', $this->birthday])
                ->andFilterWhere(['like', 'groupname', $this->groupname]);

        return $dataProvider;
    }

Following is the code for the ContactsController no change just gii generated code

public function actionIndex()
    {
        $searchModel = new ContactsSearch();
      
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    
        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

Following is the code for the gridview

GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],
            [
                'label' => 'First Name',
                'attribute' => 'firstname',
            ],
            [
                'label' => 'Last Name',
                'attribute' => 'lastname',
            ],
            //  'company',
            // 'address:ntext',
            // 'phone',
            // 'mobile',
            // 'fax',
    //Following is the related column from the groups table
            [
                'label' => 'Groups',
                'format' => 'ntext',
                'attribute'=>'groupname',
                'value' => function($model) {
                    foreach ($model->groups as $group) {
                        $groupNames[] = $group->groupname;
                    }
                    return implode("\n", $groupNames);
                },
            ],
            [
                'label' => 'Primary Email',
                'attribute' => 'pemail',
            ],
            // 'semail:email',
            // 'country',
            // 'websiteurl:url',
            // 'gender',
            // 'birthday',
            // 'status',
            // 'sentstatus',
            // 'addeddate',
            // 'updateddate',
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]);
    ?>

In this way you can show the related groupname in the contacts model with sorting and searching facility.

Thanks

]]>
0
[wiki] How to customize your grid columns visible and order by user themselves Fri, 14 Oct 2016 10:17:54 +0000 https://www.yiiframework.com/wiki/850/how-to-customize-your-grid-columns-visible-and-order-by-user-themselves https://www.yiiframework.com/wiki/850/how-to-customize-your-grid-columns-visible-and-order-by-user-themselves Scott_Huang Scott_Huang
  1. Goal
  2. Sample Picture
  3. Add code in controller
  4. Add code in model
  5. Adjust your view code
  6. a.Register JS
  7. b.Show Config Columns link
  8. c.Add partial render code in your view file
  9. d.That partial render real file
  10. Some Help Functions

Goal

Cusomized your grid columns by user themselves, allow user to hide/show columns or re-order the columns sequences.

Sample Picture

The final result look like below, you can hide/show any columns. You can type the order to re-sort the columns after save the config. You can input -1 to put it in first columns. After save, the index will reorder from 1 to the max.

The export to excel function will affected by the final resorted columns in case you use my export grid to excel extends hzlexportgrid too, Since that export extention just depends on the grid columns configs, and that columns been customized by user themselves just now.

Sample Picture

Add code in controller

Below code will help you save user configs or reset it and redirect to the destination

Some helper function list details in last session, you can deep dive HzlUtil::xxxFunction later

//your other controller code
if (isset($_POST['columnsVisibleConfigArr'])) {
            HzlUtil::saveConfigColumns(NPIPartRegion::BuyerViewColumnSetting, $_POST['columnsVisibleConfigArr']);
            //we need save to user config
        }
        if (isset($_POST['resetColumnsVisibleConfigArr'])) {
//            HzlUtil::dump($_POST['resetColumnsVisibleConfigArr']);
            HzlUtil::deleteConfigColumns(NPIPartRegion::BuyerViewColumnSetting);
            $this->redirect(array("NPIPartRegion/searchNPI"));//you can set to your index file
        }

Add code in model

I assume your grid column get from your model. such as $model->yourGridColumn() instead input in your view file directly.

public function BuyerColumns($specificId)
    {
//you can ignore/remove $specificId parameter, it just use in my own code:)
        $columnsByRole =  array(
//'id',
//'Part_Id',
            'id',
//            'Is_Primary',
            array(
                'name' => 'Is_Primary',
                'header' => 'Is_Primary',
                'value' => '$data->Is_Primary==1?"Yes":"No"',
                'filter' => NPIPart::itemAlias('Yes_No'),
                'cssClassExpression' => '$data->Is_Primary==1?"green":"grey"'
            ),
//... many other arrays
'Note',
            'Platform_GSM_Note',
//    'Update_At',
            array('name' => 'Create_At', 'header' => 'Region_Create_At')
        );

//Need read columns settings
//This is the key codes, it try to get existing configs, and try to merge into current grid columns
        $settings = Yii::app()->settings;
        $userId = "User" . yii::app()->user->id;
        $configColumns = $settings->get($userId, NPIPartRegion::BuyerViewColumnSetting);
        //and adjust default grid columns by the saved customized columns settings.
        $columnsByRole = HzlUtil::mergeConfigColumns($columnsByRole, $configColumns);
        return $columnsByRole;
}

Adjust your view code

So, you complete adjust your controller, and model, not it is the time to adjust your view code.

It is quite similar as search funtion, you click the "Config Column" link, it will expand the columns for user to setting, click the save config button, will adjust grid immediately

a.Register JS

Add below code into view file, it try to register the JS. Note, the #npipart-region-grid id need change to your own grid id. You can paste below code right after your old JS code in your view file

Yii::app()->clientScript->registerScript('config-columns', "
$('.config-columns-button').click(function(){
	$('.config-columns').toggle();
	return false;
});
$('.config-columns form').submit(function(){
	$('#npipart-region-grid').yiiGridView('update', {
		data: $(this).serialize()
	});
        $('.config-columns').toggle();
        //return false;
});
");

$columnsByRole = $model->BuyerColumns($specificId);

$columnsByRole will use in your grid. The parameter $specificID you can ignore or remove. $model->BuyerColumns($specificId) defined before, you can replace by your own get columns function:) just need to do some special handles in that function. It state before, let me highlight again below:

//your get column function need add below at the end
        $settings = Yii::app()->settings;
        $userId = "User" . yii::app()->user->id;
        $configColumns = $settings->get($userId, NPIPartRegion::BuyerViewColumnSetting);
        //and adjust default grid columns by the saved customized columns settings.
        $columnsByRole = HzlUtil::mergeConfigColumns($columnsByRole, $configColumns);
        return $columnsByRole;

b.Show Config Columns link

Add below code under the search link, it try to show the "Config Columns" link. You can adjust style by yourself, just need keep that 'class' => 'config-columns-button'

<?php echo str_repeat("&nbsp",10).CHtml::link('<b><font color = "red"> </font>Config Columns<font color = "red"> </font></b>', '#', array('class' => 'config-columns-button')); ?>

c.Add partial render code in your view file

Usually you have search code in your view file, please add below config columns code right after it. It try to partial render the _columnsVisibleConfig.php .

<div class="config-columns" style="display:none" >
    <!--<div class="search-form1" >-->
    <?php
    $this->renderPartial('_columnsVisibleConfig', array(
        'model' => $model,
        'columnsVisibleConfigArr'=>HzlUtil::getConfigColumns($columnsByRole),
        'gridLength' => 14  //you can adjust the number here, for example in case 54 columns, then the config will show as 4 grids, since 14*4=56 > 54.  Thanks.
    ));
    ?>
</div><!-- search-form -->


//other your codes
//your grid may be like below
$this->widget(
        'bootstrap.widgets.TbExtendedGridView', array(
    'id' => 'npipart-region-grid',
    'filter' => $model,
    'fixedHeader' => true,
    'type' => 'bordered hover',
    //'headerOffset' => 40,
    // 40px is the height of the main navigation at bootstrap
    'dataProvider' => $model->search(true, $specificId),
    'template' => "{pager}{summary}{items}{summary}{pager}",
    'enablePagination' => true,
    'columns' => $columnsByRole,  //note here, we use the columns which been handled in advance.
    'pager' => array(
        'class' => 'bootstrap.widgets.TbPager',
        'displayFirstAndLast' => true,
    ),
        )
);


d.That partial render real file

Usually it put in your view folder, name as _columnsVisibleConfig.php And then you can partial render this file in your view file.

<?php
$tempGridLength = $gridLength; 
?>

<div class="form">
    <div class="span18" style="font-size:83%">
        <?php
        echo CHtml::beginForm();
        $tempJ = 0;
        foreach ($columnsVisibleConfigArr as $tempI => $tempItem):
            if ($tempJ % $tempGridLength == 0) { //echo grid head
                echo '
                <div class="span3">
                <div class="grid-view">
                <table class="items" >
                <tr>
                    <th style="width:20%">Order#</th>
                    <th>Column Name</th>
                    <th>Hide</th>
                </tr>';
            }
            if ($tempJ % 2 == 0)
        {echo '<tr class = "even" style = "height:80%" > ';}
            else
        {echo '<tr class = "odd" style = "height:80%">';}
            ?>
            <td ><?php echo CHtml::textField("columnsVisibleConfigArr[$tempI][order]", $tempItem["order"], ['min' => 1, 'max' => 100, 'style'=>"width:30%;font-size:83%"]); ?></td>
            <td ><?php echo CHtml::textField("columnsVisibleConfigArr[$tempI][name]",$tempItem["name"],['readonly'=>'readonly','style'=>"width:80%;font-size:83%" ]); ?></td>
            <td><?php echo CHtml::checkBox("columnsVisibleConfigArr[$tempI][hide]",$tempItem["hide"],[]) ?></td>
            </tr>
            <?php
            $tempJ += 1;
            if ($tempJ == $tempGridLength) {
            echo '
                </table>
                </div>'.
                                CHtml::submitButton('Save Column Config',['style'=>"width:50%;font-size:83%"]).'
                </div> ';
                $tempJ = 0;
          }
        endforeach;
        if ($tempJ <> $tempGridLength) {
            echo '
                </table>
                </div>' .
                CHtml::submitButton('Save Column Config',['style'=>"width:50%;font-size:83%"]) . '
                </div> ';
        }
        ?>
        <?php

        echo str_repeat("&nbsp",10)."<font color = 'red'>Reset to Default Columns Config?! </font>".CHtml::checkBox("resetColumnsVisibleConfigArr",false,[]);
        echo CHtml::endForm(); ?>
    </div>
</div>

Some Help Functions

You can put it in your public component file or other file which you can access later. In my example, I put into components/HzlUtil.php file

// get columns name form gived grid columns
    public static function getConfigColumns($columns = [])
    {
        if (!is_array($columns)) {
            return [];
        }
        $columnsVisibleConfigArr = [];
        foreach ($columns as $i => $item) {
            $thisColumn = [];
            if (is_array($item)) {
                if (isset($item['header'])) {
                    $thisColumn['name'] = str_replace("&nbsp", "", $item['header']);
                } elseif (isset($item['name'])) {
                    $thisColumn['name'] = $item['name'];
                }
                if (isset($item['visible'])) {
                    $thisColumn['hide'] = !$item['visible'];
                } else {
                    $thisColumn['hide'] = false;
                }
            } else {
                $thisColumn['name'] = $item;
                $thisColumn['hide'] = false;
            }
            $thisColumn['order'] = $i + 1;

            $columnsVisibleConfigArr[] = $thisColumn;
        }
        return $columnsVisibleConfigArr;
    }


//we leverage CmsSettings extension to save configs to DB.  Detail info like below, you can search from Yii forum to install in your yii1.0 system in advance. Thanks.
//Actually, I just copy that file in components folder
/**
 * CmsSettings
 * 
 * @package OneTwist CMS  
 * @author twisted1919 (cristian.serban@onetwist.com)
 * @copyright OneTwist CMS (www.onetwist.com)
 * @version 1.2
 * @since 1.0
 * @access public
 *
 * 1.1e - Special thanks to Gustavo (http://www.yiiframework.com/forum/index.php?/user/6112-gustavo/)
 */

    public static function saveConfigColumns($gridCategory = '', $gridConfig = [])
    {
        usort($gridConfig, function ($a, $b) {
            $al = intval($a["order"]);
            $bl = intval($b["order"]);
            return $al == $bl ? 0 : ($al > $bl ? 1 : -1);
        });
        foreach ($gridConfig as $i => $item) {
            $gridConfig[$i]["order"] = $i + 1;
            if (!isset($item["hide"])) {
                $gridConfig[$i]["hide"] = false;
            } else if ($item["hide"]) {
                $gridConfig[$i]["hide"] = true;
            }
        }
//we leverage the CmsSettings extention here
        $settings = Yii::app()->settings;
        $userId = "User" . yii::app()->user->id;
        $settings->set($userId, $gridCategory, $gridConfig);
    }

    public static function deleteConfigColumns($gridCategory = ''){
        $settings = Yii::app()->settings;
        $userId = "User" . yii::app()->user->id;
        $settings->delete($userId, $gridCategory);
        HzlUtil::setMsg("Success Delete Config","Success delete the columns config.");
    }

    //  configColumns: each item contain order,name,hid fields
    public static function mergeConfigColumns($defaultColumns, $configColumns)
    {
        if (empty($configColumns)) {
            return $defaultColumns;
        } else {
            $FinalColumnsByRole = [];
            foreach ($configColumns as $i => $item) {
                foreach ($defaultColumns as $j => $defaultItem) {
                    $thisDefaultItemName = 'NotExistingN/A';
                    if (is_array($defaultItem)) {
                        if (isset($defaultItem['header'])) {
                            $thisDefaultItemName = str_replace("&nbsp", "", $defaultItem['header']);
                        } elseif (isset($defaultItem['name'])) {
                            $thisDefaultItemName = $defaultItem['name'];
                        }
                    } else {
                        $thisDefaultItemName = $defaultItem;
                    }
                    if ($thisDefaultItemName == $item['name']) {//find that column
                        if ($item['hide']) {
                            if (is_array($defaultItem)) {
                                $defaultItem['visible'] = false;
                                $FinalColumnsByRole[] = $defaultItem;
                            } else {
                                $newDefaultItem = [];
                                $newDefaultItem['name'] = $defaultItem;
                                $newDefaultItem['visible'] = false;
                                $FinalColumnsByRole[] = $newDefaultItem;
                            }
                        } else {
                            $FinalColumnsByRole[] = $defaultItem;
                        }
                        unset($defaultColumns[$j]);//this is important
                        break;
                    }
                }
            }
            //need append left default to final columns
            foreach ($defaultColumns as $j => $defaultItem) {
                $FinalColumnsByRole[] = $defaultItem;
            }
            return $FinalColumnsByRole;
        }
    }

]]>
0
[wiki] How to make bootstrap tabs remain active/selected after navigating to different web pages. Fri, 07 Oct 2016 15:36:28 +0000 https://www.yiiframework.com/wiki/849/how-to-make-bootstrap-tabs-remain-activeselected-after-navigating-to-different-web-pages https://www.yiiframework.com/wiki/849/how-to-make-bootstrap-tabs-remain-activeselected-after-navigating-to-different-web-pages emrald_gem emrald_gem

Bootstrap tabs gets unselected/inactive when user navigates to other page and comes back. How to make bootstrap tabs remain active/selected after navigating to different web pages.

Steps :> 1: Add class dashboard_tabs_cl to <ul>.

<!-- Nav tabs -->
<ul class="nav nav-tabs dashboard_tabs_cl" role="tablist">

2: Add javascript to the page.

<?php $this->registerJs(
'$("document").ready(function(){
	if (typeof(Storage) !== "undefined") {
				
		var dash_localVar = localStorage.getItem("dash_activ_tab"+getUrlPath());
		if(dash_localVar){

			$(".dashboard_tabs_cl > li").removeClass("active");
			$(".tab-content > div").removeClass("active");

			var hrefAttr = "a[href=\'"+dash_localVar+"\']";
			if( $(hrefAttr).parent() ){
				$(hrefAttr).parent().addClass("active");
				$(""+dash_localVar+"").addClass("active");
			}
				
		}

		$(".dashboard_tabs_cl a").click(function (e) {
			//alert(window.location.pathname);					
			e.preventDefault();
			localStorage.setItem("dash_activ_tab"+getUrlPath(), $( this ).attr( "href" ));
		});
		function getUrlPath(){
			var returnVar = "_indexpg";
			var splitStr = window.location.href;
			var asdf = splitStr.split("?r=");
			if(asdf[1]){
				var furthrSplt = asdf[1].split("&");
				if(furthrSplt[0]){
					returnVar = furthrSplt[0];
				}else{
					returnVar = asdf[1];
				}
			}
			return returnVar;
		}
	}
	});'
); ?>

Done!.

]]>
0
[wiki] Installation guide: Yii-2 advanced template with RBAC system Mon, 22 Aug 2016 07:04:06 +0000 https://www.yiiframework.com/wiki/848/installation-guide-yii-2-advanced-template-with-rbac-system https://www.yiiframework.com/wiki/848/installation-guide-yii-2-advanced-template-with-rbac-system sherin_jose_yii sherin_jose_yii

Welcome, all of you !

Here I am giving the steps for an easy installation of yii2-advanced template with an RBAC(Role Based Access Control) system.

Installtion : Yii2 - advanced template

Here we are going to install yii2-advanced template using composer. So if you don't have composer in your machine, please download and install the latest version of it. After installing composer please check whether it is accessible from the CMD by running the command composer like:

C:\>composer

If the above command gives a +ve response, then it's okay. Now we can start.

Open a new CMD window and locate to your server root directory. I am using wamp server so myself would be like:

C:\>cd wamp\www
C:\wamp\www>

Then run the command composer create-project --prefer-dist yiisoft/yii2-app-advanced yii2-app for creating a new application named as yii2-app like:

C:\wamp\www>composer create-project --prefer-dist yiisoft/yii2-app-advanced yii2-app

The template will be downloaded from git repository. After the template is installed, locate to the newly created application directory C:\wamp\www\yii2-app in CMD like:

C:\wamp\www>cd yii2-app
C:\wamp\www\yii2-app>

Then you should initialize the application by running php init in CMD. The initialization will generate the entry scripts and config files for your application. Run the command like:

C:\wamp\www\yii2-app>php init

You can select the environment type from the given options:

Which environment do you want the application to be initialized in?

  [0] Development
  [1] Production

  Your choice [0-1, or "q" to quit]

Now the installation of yii2-advanced template is completed, but still there is no database. So we want to create and use a database too. First of all we should install an RBAC module. Here I am using yii2-admin for RBAC. Take a look at the following steps:

Installation: RBAC system into your application

From the CMD window run the command composer require mdmsoft/yii2-admin "~2.0" for installing yii2-admin into your newly created application like:

C:\wamp\www\yii2-app>composer require mdmsoft/yii2-admin "~2.0"

It will be downloaded from git. After installation, the package (yii2-admin) will be located in the yii2-app/vendor/mdmsoft directory.

Then you should add some parameters to the configuration file yii2-app/common/config/main.php to access the yii2-admin and authManager as:

'modules' => [
    'admin' => [
        'class' => 'mdm\admin\Module',
        ...
    ]
    ...
],
...
'components' => [
    ...
    'authManager' => [
        'class' => 'yii\rbac\PhpManager', // or use 'yii\rbac\DbManager'
    ]
],

Create a database in MySql and configure your yii2-app/common/config/main-local.php file by adding the database credentials. Currently, there is no user table in your database. So you need to create user table for user management. For this yii2 provides an option for database migration. Run the command yii migrate --migrationPath=@mdm/admin/migrations in CMD for creating a proper user table for the user management. In CMD,

C:\wamp\www\yii2-app>yii migrate --migrationPath=@mdm/admin/migrations

The above command will create user and menu tables for your application.

Then change the user component properties in config file yii2-app/common/config/main.php as:

'components' => [
    ...
    'user' => [
        'identityClass' => 'mdm\admin\models\User',
        'loginUrl' => ['admin/user/login'],
    ]
]

Populate the user table by adding users. Use this link to register users to your application:
http://localhost/yii2-app/backend/web/index.php?r=admin/user/signup

You can use authManager class 'yii\rbac\DbManager' to authorize users using database. For that you should execute a database migration using the command yii migrate --migrationPath=@yii/rbac/migrations. Before that add 'class' => 'mdm\admin\models\User' and change the authManager class in the config file yii2-app/common/config/main.php like :

'components' => [
    ...
    'authManager' => [
        'class' => 'yii\rbac\DbManager', // or use 'yii\rbac\PhpManager'
    ],
    'user' => [
        'class' => 'mdm\admin\models\User',
        'identityClass' => 'mdm\admin\models\User',
        'loginUrl' => ['admin/user/login'],
    ]
]

and remove 'class' => 'mdm\admin\models\User' from the config file after migration. Execute the migration as:

C:\wamp\www\yii2-app>yii migrate --migrationPath=@yii/rbac/migrations

Don't forget to remove 'class' => 'mdm\admin\models\User' from the config file yii2-app/common/config/main.php.

You can use the following RBAC URLs to create and manage permissions/roles to the users:

http://localhost/yii2-app/backend/web/index.php?r=admin
http://localhost/yii2-app/backend/web/index.php?r=admin/route
http://localhost/yii2-app/backend/web/index.php?r=admin/permission
http://localhost/yii2-app/backend/web/index.php?r=admin/menu
http://localhost/yii2-app/backend/web/index.php?r=admin/role
http://localhost/yii2-app/backend/web/index.php?r=admin/assignment
http://localhost/yii2-app/backend/web/index.php?r=admin/user

Then you can create and manage routes/permissions/roles and assign them to the existing users using this interface. After setting the routes/permissions/roles, for checking whether a user has access to a particular action in a controller you need to add access control configuration parameters to the yii2-app/common/config/main.php file.

return [
    'modules' => [
        ....
    ],
    ....
    'as access' => [
        'class' => 'mdm\admin\components\AccessControl',
        'allowActions' => [
            'site/*',
            'admin/*',
        ]
    ]
]

You can add the public actions in allowActions array. The other actions will be checked by the AccessControl class for authorization.

Use the following github links for more instructions about yii2-advanced and yii2-admin:
https://github.com/yiisoft/yii2-app-advanced
https://github.com/mdmsoft/yii2-admin

Hope this article will help you to install yii2 and RBAC easily. Thanks for reading.

Happy coding :)

]]>
0
[wiki] A universal model attribute for its synthetic representation Sat, 20 Aug 2016 07:20:22 +0000 https://www.yiiframework.com/wiki/847/a-universal-model-attribute-for-its-synthetic-representation https://www.yiiframework.com/wiki/847/a-universal-model-attribute-for-its-synthetic-representation arodichevski arodichevski
  1. Example
  2. General considerations

It is convenient to use the same identification attribute, say info, in all of the active records of your application. It should be a virtual read-only attribute defined by a getter method, its label being the model name.

One can easily use the info attribute in breadcrumbs, detail views, grid views and other places. It will be $model->info instead of $model->id, $model->name or $model->name . ' ' . $model->lastname.

Example

Let us consider a hypothetical application treating states and cities having one-to-many relation.

Models
class State extends ActiveRecord
{
    // ...

    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => 'State name',
            // ...
            'info' => 'State',
        ];
    }

    public function getInfo()
    {
        return $this->name;
    }
}

class City extends ActiveRecord
{
    // ...

    public function getInfo()
    {
        return $this->name;
    }

    public function getState()
    {
        return $this->hasOne(State::className(), ['id' => 'state_id']);
    }
}

The info attribute can be used throughout the application.

Title and breadcrumbs

This is the fragment of the city update view:

$this->title = 'Update ' . $model->info;
$this->params['breadcrumbs'][] = ['label' => 'States', 'url' => ['state/index']];
$this->params['breadcrumbs'][] = ['label' => $model->state->info, 'url' => ['state/view', 'id' => $model->state_id]];
$this->params['breadcrumbs'][] = ['label' => $model->info, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Update';

The page title "Update Seattle" is more informative then "Update City: 123" generated by the standard Gii template.

Cancel button

A cancel button in the state or the city view:

<?= Html::a(
    'Delete',
    ['delete', 'id' => $model->id],
    [
        'class' => 'btn btn-danger',
        'data' => [
            'confirm' => "Deleting {$model->info}. Are you sure?",
            'method' => 'post',
        ],
    ]
) ?>

This button, when pressed, asks: "Deleting Seattle. Are you sure?" instead of the standard "Are you sure you want to delete this item?".

DetailView attribute

A hyperlink in the detail view:

<?= DetailView::widget([
    'model' => $model,
    'attributes' => [
        // ...
        [
            'attribute' => 'state_id',
            'format' => 'raw',
            'value' => Html::a($model->state->info, ['state/view', 'id' => $model->state_id]),
        ],
    ],
]) ?>
GridView column

A column in a cities grid view:

<?= GridView::widget([
    'dataProvider' => $dataProvider,
    'columns' => [
        // ...
        'state.info',
    ],
]); ?>

In this case the 'state.info' column label will be 'State', according to the City model definition.

The dropDownList

In the drop down list of the city's form:

<?= $form->field($model, 'state_id')
    ->dropDownList(
        ArrayHelper::map(State::find()->all(), 'id', 'info'),
        ['prompt' => 'Select one']
    )
?>

General considerations

Universality

The universal info attribute simplifies the application design because the developer should not remember the attribute names for every model used. Also, the info attribute label is always the model name, so the 'father.grandfather.info' column specification in the detail or grid views do not require the implicit label specification, like 'father.grandfather.info:text:My label'.

The info attribute is similar to the __toString() method used to convert any PHP object to the string.

The info attribute does not guarantee the unambiguous identification string, but gives a rapid information on the model in question.

Custom ActiveRecord class

If most of your models have the name attribute or similar data useful for identification, it is helpful to define you own ActiveRecord class:

class ActiveRecord extends \yii\db\ActiveRecord
{
    // ...

    /**
     * @return string Instantiated model name
     */
    public function getCalledClassName()
    {
        $reflectionClass = new \ReflectionClass(get_called_class());
        return $reflectionClass->getShortName();
    }

    /**
     * @return string Short description of the model
     */
    public function getInfo()
    {
        // Take the model name
        $m = $this->getCalledClassName();

        // Compound info in different cases
        if ($this->isNewRecord)
            $i = 'New ' . $m;
        elseif ($this->hasAttribute ('name') and trim($this->name))
            $i = trim($this->name);
        // ... other cases specific to your application
        else
            $i = $m . ' ' . $this->id;

        // Return the result
        return $i;
    }
}
Override getInfo()

In some models you can override the default getInfo() method defined in your ActiveRecord class. For example, the active record of a person can be identified by the first and the last name:

class Person extends ActiveRecord
{
    // ...

    public function attributeLabels()
    {
        return [
            // ...
            'info' => 'Person',
        ];
    }

    public function getInfo()
    {
        // The first and the last names combined
        $i = trim(trim($this->name) . ' ' . trim($this->lastname)]);

        // If empty, take the default value
        if (! $i)
            $i = parent::getInfo();

        // Return the result
        return $i;
    }
}

The info value is never empty. Some possible examples of its values:

  1. Jane Doe
  2. Jane
  3. Doe
  4. Person 123
  5. New Person

The case 1 is when there are both the first and the last names evaluated. The cases 2 and 3 are when there is only the first or only the last name evaluated, respectively. The case 4 is when the first and the last names are both empty. The last case is for a new record not yet saved to the database.

Search ActiveRecord class

The info attribute should be defined as not searchable in the search class:

class PersonSearch extends Person
{
    // ...
    public function rules()
    {
        return [
            // ...
            [['!info'], 'safe', 'on' => '*']
        ];
    }
}
Gii templates

One can include the above code examples in the customized Gii model and CRUD templates.

]]>
0
[wiki] Yii2: How to create/develop a new extension using Composer locally without version control or Git Fri, 12 Aug 2016 21:59:41 +0000 https://www.yiiframework.com/wiki/846/yii2-how-to-createdevelop-a-new-extension-using-composer-locally-without-version-control-or-git https://www.yiiframework.com/wiki/846/yii2-how-to-createdevelop-a-new-extension-using-composer-locally-without-version-control-or-git wadeshuler wadeshuler

Using a version control system, like Git, is nice. However, when building an extension from scratch and loading it via Composer, it adds a lot of pain in the butt steps. You have to commit your changes, update composer to pull them over, then notice there is an error, fix, commit, update. repeat.. I don't want all my baby steps under Git. Sure, I could edit my commit history, but c'mon. Just let me code! I will put it under version control once I get a baseline created. This guide will show you how to setup your composer.json to load a local directory (everything inside, live). You make a change, save the file, refresh the page, boom.

What about after you have a release of your extension, but you want to work on it to add a new feature or fix a bug? It needs to be useable in Yii2 while you work on it. So again, we don't need all the extra steps. Using the instructions in this guide, you will be able to edit your composer.json to load the files live via a symbolic link. You won't have to commit or update to see your changes in your Yii app!

This is the best way to develop new extensions for Yii! It is also the best way to work on your already existing extensions to fix bugs or add new features!

First, lets create a directory for our new extension. I am on a Mac and use XAMPP, so your paths may vary. I don't want to put my extension inside my Yii2 app because it is separate, meant to be pushed to Git and Packagist, and shared with the world, and used later. It is independent, I am just using my Yii2 app as a testing ground to build it, even if I am planning on using it inside the app for real.

cd /Applications/XAMPP/xamppfiles/htdocs
mkdir yii2-myextension
cd yii2-myextension
composer init

Follow the interactive wizard. I use Atom, and I would open a new Atom editor window, then "File > Add Project Folder" and select "yii2-myextension" to open the whole directory to work in. Now, we will only have "composer.json" in here so far. Open it.

You will notice that "init" automatically created a basic composer file. Here is mine, excluding keywords, description, etc. because those don't really matter.

{
    "name": "wadeshuler/yii2-myextension",
    "type": "yii2-extension",
    "minimum-stability": "dev",
    "autoload": {
        "psr-4": {
            "wadeshuler\\myextension\\": ""
        }
    }
}

Name: The name is /yii2-. I use my GitHub username (WadeShuler), all lowercase and no spaces (wadeshuler). It would help if you create a GitHub account first, and also create a Packagist account. Packagist uses your GitHub username :) Keep those 3 in sync and you will reduce issues. You should also prefix your extensions with "yii2-". It is a Yii standard practice, helps others know it is for Yii2 and not Yii1.

Type: You must use "yii2-extension" for the type, this tells Yii to load it into your extensions file for internal use. Click here to read more.

Min Stability: it is important to use "dev" here during testing. We have no version control (yet) and we will force our main Yii2 composer.json to accept a "dev" dependency even though Yii2 requires stable, by using "@dev" for the repo (shown later).

Autoload: I use PSR-4 and you probably should too. Most Yii2 packages I have encountered are PRS4. I feel it is better an easier, I don't just follow suit to be a sheep :P Notice how it has my vendor name, "wadeshuler" then double backslashes. These are important. If you don't know about the double backslashes, then read here. It then has the name of my extension. However, there is no "yii2" in it. This is actually the namespace we are going to use, we can call it whatever we want, so we can omit the "yii2-" to be cleaner and easier to write later. This is the namespace that defines where your extension is located. Here in Composer, we are saying "wadeshuler/whateveriwant" is going to be our namespace, and it is located "" <-- root dir of the loaded extension. You could do "wadeshuler\myextension\": "/src" <-- in your extensions src directory if you want to put everything in a "src" dir and just have your "README", "LICENSE" and "composer.json" in your extensions root dir.

Ok, so here, your Yii2 extension is ready for use in Composer. We will add files later. Right now, there is nothing but "composer.json" in our directory.

We need to load our extension into our Yii2 app. Open your Yii2 app's "composer.json" file, lets add our extension.

    "require-dev": {
        "wadeshuler/yii2-myextension": "@dev"
    },
    "repositories": [
        {
            "type": "path",
            "url": "/Applications/XAMPP/xamppfiles/htdocs/yii2-myextension"
        }
    ],

You probably don't have a "repositories" section, so add it. Notice we use "path" for the type, this does not require any version control :) For the url, I use the full path to the extension I am currently working on. This will actually create a symbolic link to the directory, which is key for live editing! I added my extension to the "require-dev" section, because it is development. Just in case this was pushed to the server, I don't want to break anything. When it's all done and on Packagist, I would put it where it belongs and remove the entry in "repositories" so it loads from Packagist and not my local computer.

Now we are ready to run: ~~~ composer update ~~~

If everything is correct, you should see Composer load your library when watching your terminal output. Open your Yii2 app in your editor and view the "vendor" directory, look for your namespace dir (wadeshuler for me), then under it you should see a directory for your extension. Now, it is empty. If it loaded fine, you are ready to start building your extension. All changes are live in your main Yii app so you can test while coding! No committing, no updating. Just edit, save, refresh!!!

When you are done and your extension is perfect, you can then put it under version control, push it to GitHub and Packagist. Then you remove the "repositories" section so it no longer links to your local directory, and edit the "require-dev" just like adding anything else from Packagist. How to add your Packagist package is beyond the scope of this tutorial. However, the gist is, you must make a "release" in GitHub in order for Packagist to work.

Ok, so now your extension is great, however there is a bug you need to fix and you want to add a new feature.. Here is what I would do.

We don't need to commit or update for this either. Revert your "composer.json" back to how I showed above, so you are "live editing" again. If you lost your project, you could "git clone" it back into your "htdocs". You can combine live editing and with your GitHub workflow. You can create a branch, live edit your files, and commit when ready. This is possible because when you switch the branch, the files are actually swapped instantly. So the file has your code, even if you haven't committed it yet! We aren't relying on any VCS, just the files like the good ole days.

Once you fixed your repo and have committed the changes, push it back to GitHub.

]]>
0