Live News for Yii Framework News, fresh extensions and wiki articles about Yii framework. Sat, 21 Apr 2018 23:38:11 +0000 Zend_Feed_Writer 2 (http://framework.zend.com) https://www.yiiframework.com/ [extension] chiliec/yii2-vote Sat, 21 Apr 2018 23:38:11 +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.1"

or add

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

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, 21 Apr 2018 23:38:11 +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, 21 Apr 2018 23:38:11 +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, 21 Apr 2018 23:38:11 +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
[extension] light/hashids Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/light/hashids https://www.yiiframework.com/extension/light/hashids lichunqiang lichunqiang

993323

Yii2 Hashids

  1. Installation
  2. Usage
  3. Test
  4. Lisence

Build Status version Download Issues

NOTE: The master branch for 2.0 version, that require mini php version is 5.6. You can require light/hashids:^1.0to use old version.

Installation

Install this package via Composer:

$ composer require light/hashids=^2.0

Usage

configurate is as a component

In your main.php or web.php (dependences your yii2 project constructor):

[
	'hahsids' => [
		'class' => 'light\hashids\Hashids',
		//'salt' => 'your salt',
		//'minHashLength' => 5,
		//'alphabet' => 'abcdefghigk'
	]
]

Also using this like this:

$hashids = Yii::createObject([
	'class' => 'light\hashids\Hashids'
]);

$id = $hashids->encode(1, 2, 3);
$numbers = $hashids->decode($id);
var_dump($id, $numbers);

Test

$ phpunit

Lisence

MIT

Bitdeli Badge

]]>
0
[extension] lavrentiev/yii2-toastr Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/lavrentiev/yii2-toastr https://www.yiiframework.com/extension/lavrentiev/yii2-toastr RyanTedder RyanTedder

Yii2 - Javascript Toast Notifications

  1. Установка
  2. Допустимые параметры
  3. Демонстрация
  4. Дополнительно

Simple javascript toast notifications - Javascript library for non-blocking notifications. jQuery is required. The goal is to create a simple core library that can be customized and extended.

Latest Stable Version Total Downloads Latest Unstable Version License

Установка

Расширение устанавливается с помощью Composer интсрукция по установке Composer

Установка расширения через Composer, выполнить следующую команду: composer require --prefer-dist lavrentiev/yii2-toastr или (master) composer require --prefer-dist lavrentiev/yii2-toastr "dev-master" или внести изменения в секцию require в composer.json и выполнить composer update "lavrentiev/yii2-toastr": "^2.0" или (master) "lavrentiev/yii2-toastr": "dev-master"

Уведомления Notification::widget()

alt text

use lavrentiev\widgets\toastr\Notification;

Notification::widget([
    'type' => 'info',
    'title' => 'Toast Notifications',
    'message' => 'Simple javascript toast notifications'
]);

Notification::widget([
    'type' => 'error',
    'title' => 'Toast Notifications',
    'message' => 'Simple javascript toast notifications'
]);

Notification::widget([
    'type' => 'success',
    'title' => 'Toast Notifications',
    'message' => 'Simple javascript toast notifications'
]);

Notification::widget([
    'type' => 'warning',
    'title' => 'Toast Notifications',
    'message' => 'Simple javascript toast notifications'
]);

Notification::widget([
    'type' => 'info',
    'message' => 'Simple javascript toast notifications'
]);

Notification::widget([
    'type' => 'error',
    'message' => 'Simple javascript toast notifications'
]);

Notification::widget([
    'type' => 'success',
    'message' => 'Simple javascript toast notifications'
]);

Notification::widget([
    'type' => 'warning',
    'message' => 'Simple javascript toast notifications'
]);

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

alt text`php Notification::widget([

'type' => Notification::TYPE_ERROR,
'title' => 'Toast Notifications',
'message' => 'Simple javascript toast notifications',
'options' => [
    "closeButton" => false,
    "debug" => false,
    "newestOnTop" => false,
    "progressBar" => false,
    "positionClass" => Notification::POSITION_TOP_RIGHT,
    "preventDuplicates" => false,
    "onclick" => null,
    "showDuration" => "300",
    "hideDuration" => "1000",
    "timeOut" => "5000",
    "extendedTimeOut" => "1000",
    "showEasing" => "swing",
    "hideEasing" => "linear",
    "showMethod" => "fadeIn",
    "hideMethod" => "fadeOut"
]

]); `

Уведомления NotificationFlash::widget()

Подключение осуществляеться глобально допустим в layouts проекта.

<?= \lavrentiev\widgets\toastr\NotificationFlash::widget() ?>

Также присутствует возможность настройки уведомлений, по параметрам предусмотренным разработчиками Toastr by CodeSeven

<?= \lavrentiev\widgets\toastr\NotificationFlash::widget([
    'options' => [
        "closeButton" => true,
        "debug" => false,
        "newestOnTop" => false,
        "progressBar" => false,
        "positionClass" => \lavrentiev\widgets\toastr\NotificationFlash::POSITION_TOP_RIGHT,
        "preventDuplicates" => false,
        "onclick" => null,
        "showDuration" => "300",
        "hideDuration" => "1000",
        "timeOut" => "5000",
        "extendedTimeOut" => "1000",
        "showEasing" => "swing",
        "hideEasing" => "linear",
        "showMethod" => "fadeIn",
        "hideMethod" => "fadeOut"
    ]
]) ?>

alt text

\Yii::$app->session->setFlash('error', 'This is the message');
\Yii::$app->session->setFlash('success', 'This is the message');
\Yii::$app->session->setFlash('info', 'This is the message');
\Yii::$app->session->setFlash('warning', 'This is the message');

alt text

\Yii::$app->session->setFlash('warning', ['Error 1', 'Error 2', 'Error 3']);
\Yii::$app->session->setFlash('success', ['Error 1', 'Error 2', 'Error 3']);

Допустимые параметры

ПараметрЗначение по умолчаниюДопустимые значенияОписание
typeinfoinfo, error, success, warningТип уведомления
title------Заголовок уведомления
messageSimple javascript toast notifications---Текст уведомления
options[]Подробней...Дополнительные опции

Допустимые константы типов: TYPE_INFO = 'info' TYPE_ERROR = 'error' TYPE_SUCCESS = 'success' TYPE_WARNING = 'warning'

Допустимые константы положения: ` POSITION_TOP_RIGHT = 'toast-top-right'; POSITION_TOP_LEFT = 'toast-top-left'; POSITION_TOP_CENTER = 'toast-top-center'; POSITION_TOP_FULL_WIDTH = 'toast-top-full-width';

POSITION_BOTTOM_RIGHT = 'toast-bottom-right'; POSITION_BOTTOM_LEFT = 'toast-bottom-left'; POSITION_BOTTOM_CENTER = 'toast-bottom-center'; POSITION_BOTTOM_FULL_WIDTH = 'toast-bottom-full-width'; `

Демонстрация

Дополнительно

]]>
0
[extension] arm0nd/jfullcalendar Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/arm0nd/jfullcalendar https://www.yiiframework.com/extension/arm0nd/jfullcalendar rmond rmond

JFullCallendar

]]>
0
[extension] rob006/yii2-simple-auth Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/rob006/yii2-simple-auth https://www.yiiframework.com/extension/rob006/yii2-simple-auth rob006 rob006

Simple authentication extension for Yii 2

  1. Installation
  2. Usage

Yii 2 extension that provides simple authentication based on a secret key.

The extension provides components for easy authenticate and validate the HTTP request. Each request gets its own unique token with the expiration time, so no passwords or keys are sent with the request - it should be safer than basic access authentication when you don't use https.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require rob006/yii2-simple-auth

or add

"rob006/yii2-simple-auth": "^1.0"

to the require section of your composer.json file.

Usage

Configuration

You can configure default secret key used by this extension by setting param in your config in config/web.php and/or in config/console.php:

return [
	...
	'params' => [
		...
		'simpleauth' => [
			'secret' => 'mysecretkey',
		],
	],
];

This is optional - you can always explicitly specify the key for authentication/validation.

Authentication (client side)
Authentication when using official yii2-httpclient extension

You can simply authenticate Request object from official Yii 2 httpclient by using yii2-simple-auth-yii-authenticator extension.

Authentication any request

You can use Authenticator to authenticate any request, even if you don't use yii2-httpclient package. For example, authentication cURL request by GET param:

use rob006\simpleauth\Authenticator;

$ch = curl_init();
$url = 'http://api.example.com/user/list/?ids=1,2,3,4';
$url .= '&' . Authenticator::PARAM_NAME . '=' . Authenticator::generateAuthToken($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);

Authentication cURL request by header: `php use rob006\simpleauth\Authenticator;

$ch = curl_init(); $url = 'http://api.example.com/user/list/?ids=1,2,3,4'; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HTTPHEADER, [

Authenticator::HEADER_NAME . ': ' . Authenticator::generateAuthToken($url),

]); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $response = curl_exec($ch); curl_close($ch); `

Validation (server side)

To check whether the request has a valid token simply add action filter to your controller:

use rob006\simpleauth\ActionFilter;

class MyController extends \yii\web\Controller {

	public function behaviors() {
		return [
			...
			'simpleauth' => [
				'class' => ActionFilter::className(),
			],
		];
	}

	...
}

You can also configure some settings for ActionFilter:

use rob006\simpleauth\ActionFilter;
use rob006\simpleauth\Authenticator;

class MyController extends \yii\web\Controller {

	public function behaviors() {
		return [
			...
			'simpleauth' => [
				'class' => ActionFilter::className(),
				// allow authentication only by header
				'allowedMethods' => [
					Authenticator::METHOD_HEADER,
				],
				// set token timeout to 1 hour (by default it is 5 minutes)
				'tokenDuration' => 3600,
				// override default header used for authentication
				'headerName' => 'X-My-Custom-Header',
				// override params names used for send authentication token
				'postParamName' => 'my_custom_token_param_name',
				'getParamName' => 'my_custom_token_param_name',
				// custom secret used for validate authentication
				'secret' => 'my-custom-secret-key',
			],
		];
	}

	...
}
Final comments

Make sure that you generate token for final URL and no redirections are performed for the request. Token is generated for the exact address, so tokens for:

  • http://example.com/user/list/
  • https://example.com/user/list/
  • http://www.example.com/user/list/
  • http://example.com/user/list

will be completely different.

Be careful when using POST request. Authenticator and ActionFilter takes into account only the URL, all POST data is ignored during the authentication and validation. This means that one token may be used many times for different requests with different POST data if refer to the same URL.

]]>
0
[extension] davidjeddy/yii2-rss-reader Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/davidjeddy/yii2-rss-reader https://www.yiiframework.com/extension/davidjeddy/yii2-rss-reader davidjeddy davidjeddy

Yii2 RSS Reader

  1. Badges
  2. Installation
  3. Usage

RSS reader widget for Yii2.

Badges

SensioLabsInsight Latest Stable Version Latest Unstable Version License Total Downloads Monthly Downloads Daily Downloads

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist davidjeddy/yii2-rss-reader "*"

or add

"davidjeddy/yii2-rss-reader": "*"

to the require section of your composer.json file.

Usage

Once the widget is installed, add it to a view script:

echo \davidjeddy\RssFeed\RssReader::widget([
    'channel'   => '{source_url}/feed.xml',
    'itemView'  => 'item',
    'pageSize'  => 5,
    'wrapClass' => 'rss-wrap',
    'wrapTag'   => 'div',
]);
]]>
0
[extension] davidjeddy/yii2-poll Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/davidjeddy/yii2-poll https://www.yiiframework.com/extension/davidjeddy/yii2-poll davidjeddy davidjeddy

yii2-poll

  1. Badges
  2. About

Badges

SensioLabsInsight Latest Stable Version Total Downloads Latest Unstable Version License Monthly Downloads Daily Downloads

About

Create a basic custom polls for Yii 2.x.

Installing

  1. Badges
  2. About
  • Run composer require davidjeddy/yii2-poll on the terminal in your {project root}
    • OR add "davidjeddy/yii2-poll": "~2" to your projects composer.json in the "required": [...] section then run composer update.
  • Run migration via Yii's migration command providing php ./console/yii migrate/up --migrationPath=./vendor/davidjeddy/yii2-poll/migrations

Usage

  1. Badges
  2. About

Basic: `PHP

echo \davidjeddy\poll\PollWidget::widget([
    'questionText'  => \Yii::t('poll', 'Do you like PHP?'),
    'answerOptions' => ['Yes', 'No'],
]);


Advanced:
```PHP
    echo \davidjeddy\poll\PollWidget::widget([
        'questionText'  => \Yii::t('poll', 'Do you like PHP?'),
        'answerOptions' => ['Yes', 'No'],
        'params'        => [
            'backgroundLinesColor' => '#DCDCDC',// html hex
            'linesColor'           => '#DC0079' // html hex
            'linesHeight'          => 20,       // in pixels
            'maxLineWidth'         => 200,      // in pixels
        ]
    ]);
]]>
0
[extension] davidjeddy/yii2-paypal Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/davidjeddy/yii2-paypal https://www.yiiframework.com/extension/davidjeddy/yii2-paypal davidjeddy davidjeddy

Badges

Latest Stable Version Total Downloads Latest Unstable Version License Monthly Downloads Daily Downloads

SensioLabsInsight

PayPal extension for the Yii2

PayPal payment module extension for Yii 2.x

Installation

Add the dependancy to your project via composer (recommended)

  • composer require --prefer-dist davidjeddy/yii2-paypal "*" OR
  • "davidjeddy/yii2-paypal": "dev-master" and run composer update

Configuration

'paypal'=> [
    'class'        => 'davidjeddy\Paypal',
    'clientId'     => 'you_client_id',
    'clientSecret' => 'you_client_secret',
    'isProduction' => false,
    // These properties would be found in the Paypal sdk_config.ini
    'config'       => [
        'http.ConnectionTimeOut' => 30,
        'http.Retry'             => 1,
        'mode'                   => \davidjeddy\Paypal::MODE_SANDBOX, // development (sandbox) or production (live) mode
        'log.LogEnabled'         => YII_DEBUG ? 1 : 0,
        'log.FileName'           => '@runtime/logs/paypal.log',
        'log.LogLevel'           => \davidjeddy\Paypal::LOG_LEVEL_FINE,
    ]
],

Usage

Class Someclass
{
    ...
    /**
     * [pay description]
     * 
     * @param  array  $paramData [description]
     * @return [type]            [description]
     */
    private function pay(array $paramData) {
        $paypalComponent = new Paypal();

        try {
            return $paypalComponent->execTransaction($paramData);
        } catch (Exception $ex) {
            echo PaypalError($e);
        }

        return flase;
    }
    ...
}
]]>
0
[extension] davidjeddy/yii2-leaflet-draw-plugin Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/davidjeddy/yii2-leaflet-draw-plugin https://www.yiiframework.com/extension/davidjeddy/yii2-leaflet-draw-plugin davidjeddy davidjeddy

Leaflet Draw Plugin

  1. Installation
  2. Usage
  3. Testing
  4. Todo
  5. Contributing
  6. Credits
  7. License
  8. Special Thanks

Yii 2 LeafletJs Plugin for the 2amigo Leaflet extension that adds the Leaflet Draw functionality.

This Plugin works in conjunction with LeafLet library for Yii 2 framework.

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require "davidjeddy/yii2-leaflet-draw-plugin" "*"

or add

"davidjeddy/yii2-leaflet-draw-plugin" : "*"

to the require section of your application's composer.json file.

Usage

    // first lets setup the center of our map
    $center = new \dosamigos\leaflet\types\LatLng(['lat' => 51.508, 'lng' => -0.11]);

    // now lets create a marker that we are going to place on our map
    $marker = new \dosamigos\leaflet\layers\Marker(['latLng' => $center, 'popupContent' => 'Hi!']);

    // The Tile Layer (very important)
    $tileLayer = new \dosamigos\leaflet\layers\TileLayer([
       'urlTemplate' => 'http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpeg',
        'clientOptions' => [
            'attribution' => 'Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">, Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>',
            'subdomains'  => '1234',
        ]
    ]);

    // now our component and we are going to configure it
    $leaflet = new \dosamigos\leaflet\LeafLet([
        'center' => $center, // set the center
    ]);

	// init the 2amigos leaflet plugin provided by the package
    $drawFeature = new \davidjeddy\leaflet\plugins\draw\Draw();
	// optional config array for leadlet.draw
    $drawFeature->options = [
        "position" => "topright",
        "draw" => [
            "polyline" => [
                "shapeOptions" => [
                    "color" => "#ff0000",
                    "weight" => 10
                ]
            ],
            "polygon" => [
                "allowIntersection" => false, // Restricts shapes to simple polygons
                "drawError" => [
                    "color" => "#e1e100", // Color the shape will turn when intersects
                    "message" => "<b>Oh snap!</b> you can't draw that!" // Message that will show when intersect
                ],
                "shapeOptions" => [
                    "color" => "#bada55"
                ]
            ],
            "circle" => true, // Turns off this drawing tool
            "rectangle" => [
                "shapeOptions" => [
                    "clickable" => false
                ]
            ]
        ]
    ];

    // Different layers can be added to our map using the `addLayer` function.
    $leaflet->addLayer($marker)             // add the marker
            ->addLayer($tileLayer)          // add the tile layer
            ->installPlugin($drawFeature);  // add draw plugin

    // we could also do
    echo $leaflet->widget(['options' => ['style' => 'min-height: 300px']]);

Testing

TODO

Todo

ADD edit menu ability ADD custom marker functionality

Contributing

Please see ./docs/CONTRIBUTING for details.

Credits

License

The BSD License (BSD). Please see ./docs/License File for more information.

Special Thanks

2amigOS!
Web development has never been so fun!
http://2amigos.us/

(http://http://sourcetoad.com/)
Sourcetoad is an award winning app development firm based in Tampa, FL. We are specialists in cross-platform web and mobile application development.
http://sourcetoad.com/

]]>
0
[extension] davidjeddy/yii2-freeradius-module Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/davidjeddy/yii2-freeradius-module https://www.yiiframework.com/extension/davidjeddy/yii2-freeradius-module davidjeddy davidjeddy

yii2-freeradius-module

Module to interface with a FreeRADIUS server

Badges

Latest Stable Version Total Downloads Latest Unstable Version License Monthly Downloads Daily Downloads composer.lock

SensioLabsInsight

REQUIREMENTS

PHP 7+

MySQL 5.5+

FreeRadius

Composer

Yii 2+ (advanced tempplate recommended)

INSTALLATION

  • cd {project root}
  • Run composer require davidjeddy/yii2-freeradius-module in terminal
    • OR add "davidjeddy/yii2-freeradius-module": "dev-master@dev" to your project's composer.json, then composer install.

USAGE

Add the module to the configuration

return [
    ...
    'modules' => [
        ...
        'free-radius' => [
            'class' => davidjeddy\freeradius\Module::class,
        ],
        ...
    ],
];

To add to a typical AdminLTE admin panel:

Edit ./backend/views/layouts/common.php and add the following inside Menu::widget([ ... ]) `

[
    'label'     => Yii::t('backend', 'Free Radius'),
    'icon'      => '<i class="fa fa-id-card-o"></i>',
    'url'       => ['/free-radius/default/index'],
    'visible'   => Yii::$app->user->can('administrator')
],

# TESTING
TODO

# Misc
If the server does not yet have a `RadCheck` table from FreeRadius, run

the modules migration from the project root:

`php ./console/yii migrate/up --migrationPath=./vendor/davidjeddy/yii2-freeradius-module/migration/`


]]>
0
[extension] davidjeddy/yii2-article-category Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/davidjeddy/yii2-article-category https://www.yiiframework.com/extension/davidjeddy/yii2-article-category davidjeddy davidjeddy ]]> 0 [extension] davidjeddy/codeception-hello-module Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/davidjeddy/codeception-hello-module https://www.yiiframework.com/extension/davidjeddy/codeception-hello-module davidjeddy davidjeddy ]]> 0 [extension] hoaaah/yii2-startbootstrap-agency Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/hoaaah/yii2-startbootstrap-agency https://www.yiiframework.com/extension/hoaaah/yii2-startbootstrap-agency hoAAah hoAAah

YII2 Startbootstrap-Agency Library

  1. Installation
  2. Usage
  3. Creator

This extensions is library for Startbootstrap Stylish-Portofolio Themes

Agency is a responsive, one page portfolio theme for Bootstrap created by Start Bootstrap. This theme features several content sections, a responsive portfolio grid with hover effects, full page portfolio item modals, a responsive timeline, and a working PHP contact form.

Start Bootstrap was created by and is maintained by David Miller, Owner of Blackrock Digital.

Start Bootstrap is based on the Bootstrap framework created by Mark Otto and Jacob Thorton.

Installation

The preferred way to install this extension is through composer.

Either run

composer require hoaaah/yii2-startbootstrap-agency:dev-master

or add

"hoaaah/yii2-startbootstrap-agency": "*"

to the require section of your composer.json file.

Usage

You can use an example views in views-example and copy it to your view.

Don't forget to use this in your view

use hoaaah\agency\AgencyAsset;

AgencyAsset::register($this);

and just in case you want to use vendor image, to call any content of vendor image you can use this

$image = hoaaah\agency\AgencyAsset::register($this);

<img src=<?= $agency->baseUrl.'/img/portfolio/startup-framework.png' ?> class="img-responsive" alt="">

it will call startup-framework.png from /vendor/hoaaah/yii2-startbootstrap-agency/assets/img/portofolio/startup-framework.png

Creator

This startbootstrap-agency library for Yii2 was created by and is maintained by Heru Arief Wijaya.

]]>
0
[extension] yiisoft/yii2-queue Mon, 09 Apr 2018 13:40:39 +0000 https://www.yiiframework.com/extension/yiisoft/yii2-queue https://www.yiiframework.com/extension/yiisoft/yii2-queue CeBe CeBe

993323

Yii2 Queue Extension

  1. Installation
  2. Basic Usage

An extension for running tasks asynchronously via queues.

It supports queues based on DB, Redis, RabbitMQ, AMQP, Beanstalk and Gearman.

Documentation is at docs/guide/README.md.

Latest Stable Version Total Downloads Build Status

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist yiisoft/yii2-queue

or add

"yiisoft/yii2-queue": "~2.0.0"

to the require section of your composer.json file.

Basic Usage

Each task which is sent to queue should be defined as a separate class. For example, if you need to download and save a file the class may look like the following:

class DownloadJob extends BaseObject implements \yii\queue\JobInterface
{
    public $url;
    public $file;
    
    public function execute($queue)
    {
        file_put_contents($this->file, file_get_contents($this->url));
    }
}

Here's how to send a task into the queue:

Yii::$app->queue->push(new DownloadJob([
    'url' => 'http://example.com/image.jpg',
    'file' => '/tmp/image.jpg',
]));

To push a job into the queue that should run after 5 minutes:

Yii::$app->queue->delay(5 * 60)->push(new DownloadJob([
    'url' => 'http://example.com/image.jpg',
    'file' => '/tmp/image.jpg',
]));

The exact way a task is executed depends on the used driver. Most drivers can be run using console commands, which the component automatically registers in your application.

This command obtains and executes tasks in a loop until the queue is empty:

yii queue/run

This command launches a daemon which infinitely queries the queue:

yii queue/listen

See the documentation for more details about driver specific console commands and their options.

The component also has the ability to track the status of a job which was pushed into queue.

// Push a job into the queue and get a message ID.
$id = Yii::$app->queue->push(new SomeJob());

// Check whether the job is waiting for execution.
Yii::$app->queue->isWaiting($id);

// Check whether a worker got the job from the queue and executes it.
Yii::$app->queue->isReserved($id);

// Check whether a worker has executed the job.
Yii::$app->queue->isDone($id);

For more details see the guide.

]]>
0
[extension] maks757/yii2-friendly-url Mon, 09 Apr 2018 08:39:59 +0000 https://www.yiiframework.com/extension/maks757/yii2-friendly-url https://www.yiiframework.com/extension/maks757/yii2-friendly-url maks757 maks757

Friendly url

  1. Installation
  2. Usage
  3. Model
  4. Configuration
  5. View
  6. Action from Product Controller

Friendly url for your library or module

Installation

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist maks757/yii2-friendly-url "*"

or add

"maks757/yii2-friendly-url": "*"

to the require section of your composer.json file.

Usage

Model

// implements IUrlRules !!!
class ProductModel extends \yii\db\ActiveRecord implements maks757\friendly\components\IUrlRules
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'products';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            //...
            // seo data
            [['seoUrl', 'seoTitle', 'seoDescription', 'seoKeywords'], 'string']
        ];
    }
    
    // Exemple: $key = 'my-first-product' -> return id
    /**
     * @param mixed $key
     * @return boolean|integer model id
     */
    public function fiendKey($key)
    {
        $model = ProductModel::findOne(['seoUrl' => $key]);
        return empty($model) ? false : $model->id;
    }

    // Exemple: $id = 10 -> return seoUrl
    /**
     * @param integer $id
     * @return string
     */
    public function seoUrl($id)
    {
        return ProductModel::findOne($id)->seoUrl;
    }
}

Configuration

'components' => [
    //...
    'urlManager' => [
        'enablePrettyUrl' => true,
        'showScriptName' => false,
        'rules' => [
            'news' => 'product/show',
            [
                    'class' => \maks757\friendly\UrlRules::className(),
                    'action' => 'product/show', // View 'product/show' or news
                    'controller_and_action' => 'product/show', // Action news show
                    //param: (action_key) - Action param get product id
                    //param: (url_key) - // View set product id
                    'routes' => [
                        ['model' => \common\models\ProductGroupModel::class, 'url_key' => 'group_id', 'action_key' => 'group',],
                        ['model' => \common\models\ProductModel::class, 'url_key' => 'product_id', 'action_key' => 'product',],
                    ]
                ],
        ],
    ],
    //...
],

View

<a href="Url::toRoute(['/product/show', 'group_id' => $group, 'product_id' => $product->id])">Go to product</a>

example url: https://tise/product/show/water/colla<br> water = group seo url
colla = product seo url

Action from Product Controller

public function actionShow($group, $product)
{
    //...
}
]]>
0
[extension] softark/creole Sat, 21 Apr 2018 23:38:11 +0000 https://www.yiiframework.com/extension/softark/creole https://www.yiiframework.com/extension/softark/creole softark softark

creole parser extended from cebe/markdown

  1. What is this?
  2. Installation
  3. Usage
  4. Acknowledgements
  5. FAQ
  6. Contact

Build Status Code Coverage Scrutinizer Code Quality

What is this?

This is a Creole Wiki parser for PHP built upon cebe/markdown parser for PHP.

Installation

PHP 5.4 or higher is required to use it. It will also run on facebook's hhvm.

Installation is recommended to be done via composer by running:

composer require softark/creole "~1.2"

Alternatively you can add the following to the require section in your composer.json manually:

"softark/creole": "~1.2"

Run composer update afterwards.

Note that the installation automatically includes the dependent packages, especially "cebe/markdown", to make the creole parser functional.

Usage

The usage of the creole parser is similar to that of cebe/markdown parser.

In your PHP project

To parse your wiki text you need only two lines of code. The first one is to create the creole parser instance:

$parser = new \softark\creole\Creole();

The next step is to call the parse()-method for parsing the text using the full wiki language or calling the parseParagraph()-method to parse only inline elements:

$parser = new \softark\creole\Creole();
$outputHtml = $parser->parse($wikiText);

// parse only inline elements (useful for one-line descriptions)
$parser = new \softark\creole\Creole();
$outputHtml = $parser->parseParagraph($wikiText);

You may optionally set the following option on the parser object:

  • $parser->html5 = true to enable HTML5 output instead of HTML4.

And you should set the following properties when you are using the wiki style links, i.e. link for an internal link and WikiName:link for an external link:

  • $parser->wikiUrl = 'http://www.example.com/wiki/' for the url of the current wiki.
  • $parser->externalWikis = ['Wiki-A' => 'http://www.wiki-a.com/', 'Wiki-B' => 'http://www.wiki-b.net/'] for the external wikis. It should be an array in which the keys are the name of the wiki and the value the urls of them.

It is recommended to use UTF-8 encoding for the input strings. Other encodings are currently not tested.

Using raw html blocks

In the version 1.2.0 and later, you may optionally include raw html blocks in the source wiki text, although this feature is disabled by default because it's not in the Creole 1.0 specification.

You can enable this feature by specifying the following option:

  • $parser->useRawHtml = true

A raw html block should start with a line that only contains <<< and end with a corresponding closing line which should be >>>, for example: <<< <p>This is a raw html block.</p> <ul> <li>You can do whatever you want.</li> <li>You have to be responsible for the consequence.</li> </ul> >>>

Note that the output of the raw html blocks SHOULD BE CLEANSED with $parser->rawHtmlFilter. A recommendation is to use HTML Purifier for the filter. For example:

$parser->rawHtmlFilter = function($input) {
    $config = \HTMLPurifier_Config::createDefault();
    $purifier = \HTMLPurifier::getInstance($config);
    return $purifier->purify($input);
};

// Or, if you are Yii 2 user
$parser->rawHtmlFilter = function($input) {
    return \yii\helpers\HtmlPurifier::process($input);
};

As you see in the example, the rawHtmlFilter should be a callable that accepts the possibly unclean html text string and output the sanitized version of it.

The command line script

You can use it to convert a wiki text to a html file:

bin/creole some.txt > some.html

Here is the full Help output you will see when running bin/creole --help:

PHP Creole to HTML converter
----------------------------

by Nobuo Kihara <softark@gmail.com>

Usage:
    bin/creole [--full] [file.txt]

    --full    ouput a full HTML page with head and body. If not given, only the parsed markdown will be output.

    --help    shows this usage information.

    If no file is specified input will be read from STDIN.

Examples:

    Render a file with original creole:

        bin/creole README.txt > README.html

Convert the original creole description to html using STDIN:

    curl http://www.wikicreole.org/attach/Creole1.0TestCases/creole1.0test.txt | $cmd > creole.html

Acknowledgements

I'd like to thank @cebe for creating cebe/markdown library on which this work depends.

As its name describes, cebe/markdown is a markdown parser, but is also a well designed general purpose markup language parser at the bottom on which you can implement parsers not only for different "flavors" of markdown but also for different markup languages, Creole for instance.

FAQ

Where do I report bugs or rendering issues?

Just open an issue on github, post your creole code and describe the problem. You may also attach screenshots of the rendered HTML result to describe your problem.

Am I free to use this?

This library is open source and licensed under the MIT License. This means that you can do whatever you want with it as long as you mention my name and include the license file. Check the license for details.

Contact

Feel free to contact me using email or twitter.

]]>
0
[wiki] Configuring PhpStorm IDE for Yii 2 Thu, 05 Apr 2018 13:35:42 +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 payed 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] Yii 2 MongoDB extension 2.1.7 released Fri, 30 Mar 2018 16:33:01 +0000 https://www.yiiframework.com/news/172/yii-2-mongodb-extension-2-1-7-released https://www.yiiframework.com/news/172/yii-2-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
[news] Redis extension 2.0.7 released Mon, 11 Dec 2017 21:18:36 +0000 https://www.yiiframework.com/news/155/redis-extension-2-0-7-released https://www.yiiframework.com/news/155/redis-extension-2-0-7-released CeBe CeBe

We are very pleased to announce the release of the redis extension version 2.0.7.

This release makes the extension compatible with PHP 7.2 by refering to BaseObject instead of the Object class in Yii.

It also adds simple ORDER BY support to the ActiveQuery so DataProvider functionaility is now fully supported.

Besides two bug fixes this release also greatly improves stablilty by being able to detect a lost connection to the redis server and Connection can now be configured to reconnect if desired.

See CHANGELOG for details.

Thanks to all community members who helped making this release possible!

]]>
0
[news] Debug extension version 2.0.13 released Tue, 05 Dec 2017 07:44:39 +0000 https://www.yiiframework.com/news/154/debug-extension-version-2-0-13-released https://www.yiiframework.com/news/154/debug-extension-version-2-0-13-released samdark samdark

We are very pleased to announce the release of Debug Toolbar extension version 2.0.13. In this release:

  • PHP 7.2 compatibility.
  • Bugfixes.
  • HTTP headers are now sent regardless if page is served via AJAX so panel could be referenced from single page apps.
  • DB panel got duplicated queries counts.
  • Request panel got "General Info" block.
  • User component is now configurable for UserSwitch and UserPanel.

See CHANGELOG for details.

]]>
0
[news] jQueryUI Extension 2.0.7 released Sat, 25 Nov 2017 15:37:58 +0000 https://www.yiiframework.com/news/153/jqueryui-extension-2-0-7-released https://www.yiiframework.com/news/153/jqueryui-extension-2-0-7-released samdark samdark

We've released version 2.0.7 of the jQueryUI extension. This version is fixing bugs and updates jQueryUI dependency so it works with latest Yii release.

]]>
0
[news] Queue Extension 2.0.1 released Mon, 13 Nov 2017 20:08:36 +0000 https://www.yiiframework.com/news/152/queue-extension-2-0-1-released https://www.yiiframework.com/news/152/queue-extension-2-0-1-released samdark samdark

We've released version 2.0.1 of the Queue extension. This version is fixing bugs as well as adding some enhancements we'll review below.

  • Added console commands for removing jobs and clearing whole queue. Both depend on the queue broker driver so details could be found in updated guide for particular driver.
  • Added support for Igbinary job serializer.
  • Allowed to change vhost setting for RabbitMQ.
  • Extension is now compatible with PHP 7.2.
  • Some classes and interfaces were marked as deprecated. See UPGRADE for details.
  • A benchmark measuring time to get the job to the worker was performed As expected, fastest implementations are Gearman, Beanstalk, Radis and RabbitMQ. Average time is 1-2 ms. Details could be found in this gist.
]]>
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
[wiki] A Single Page with a List and a Detail Sun, 10 Jul 2016 12:10:02 +0000 https://www.yiiframework.com/wiki/845/a-single-page-with-a-list-and-a-detail https://www.yiiframework.com/wiki/845/a-single-page-with-a-list-and-a-detail softark softark
  1. Original Index Page
  2. Sub View for Detail
  3. Modifying Index Action
  4. Ajax Action
  5. Ajax Updating
  6. Conclusion

The CRUD generator of Gii has done a wonderful job for you, and you already have a list of items in the "index" page and a detailed view of a specified item in the "view" page.

But you may want to show both the index and the view in a single page. That way you can click on an item in the grid to show its details without having to go to another page.

Is it possible with Yii? Yes, it is!

Let's start with a review of the current code.

Original Index Page

For example, assume that the following is an "index" page that Gii has generated for the Post model for you.

<?php

use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
/* @var $this yii\web\View */
/* @var $searchModel app\models\PostSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

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

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

    <p>
        <?= Html::a('Create Post', ['create'], ['class' => 'btn btn-success']) ?>
    </p>
<?php Pjax::begin(); ?>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],

            'id',
            'date',
            'title',
            // 'body',
            // 'created_at',
            // 'created_by',
            // 'updated_at',
            // 'updated_by',

            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
<?php Pjax::end(); ?>
</div>

As you see, this page lists the posts in a GridView. It shows only a few attributes of the post because of the limited space. You can see "date" and "title" in the grid, but you have to go to a "view" page to see other attributes like "body" and "created_by".

Now we want to show all the attributes of the selected post in the same page when you click on a row in the grid.

Sub View for Detail

The first thing we do is to create a sub-view that shows all the attributes of a post. We will call it "_view.php".

<?php

use yii\helpers\Html;
use yii\widgets\DetailView;

/* @var $this yii\web\View */
/* @var $model app\models\Post */

?>
<h2><?= Html::encode($model->date . ' : ' . $model->title) ?></h2>

<?= DetailView::widget([
    'model' => $model,
    'attributes' => [
        'id',
        'date',
        'title',
        'body',
        'created_at',
        'created_by',
        'updated_at',
        'updated_by',
    ],
]) ?>

It uses a DetailView to show all the attributes of a post. As you may notice, this is almost identical with "view.php", that Gii has generated for you. You can make it very easily with copy-and-pasting.

Now we include this sub-view in the "index.php" page.

...

/* @var $post app\models\Post */

...

<?php Pjax::begin(); ?>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],

            'id',
            'date',
            'title',

            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
<?php Pjax::end(); ?>

<div id="post-detail">
    <?php echo $this->render('_view', ['model' => $post]); ?>
</div>

The sub view is located after the grid. You may locate it before the grid if you prefer. But the important point is that the sub view should be outside of the Pjax area.

You may be aware that we have to supply an additional parameter called "post" to the index view, since the sub-view needs it to work as expected. We will modify the "index" action next.

Modifying Index Action

The original controller code looks like this:

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

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

We want to get a post instance that is to be passed to the view. For the moment, it's enough for us to have something like the following with a quick-and-dirty trick:

/**
 * Lists all Post models.
 * @return mixed
 */
public function actionIndex()
{
    $searchModel = new PostSearch();
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    $post = new Post();  /* create an empty post instance */
    // $post = Post::findOne(1); /* get a post with id = 1 */

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

Now your index page will start to show a post after the grid, although the post is fixed to an empty one(or one with its id being 1).

Ajax Action

We are now going to create an ajax action that renders the selected post as an ajax response:

/**
 * Displays a single Post model as an ajax response.
 * @param integer $id
 * @return mixed
 */
public function actionAjaxView($id)
{
    return $this->renderPartial('_view', [
        'model' => $this->findModel($id),
    ]);
}

It's almost the same as the existing actionView() method. It displays "_view.php" without the enclosing layout.

Ajax Updating

Now, here comes the magic of ajax updating. Insert the following lines in "index.php":

<?php
$ajax_url = yii\helpers\Url::to(['ajax-view']); // #1
$csrf_param = Yii::$app->request->csrfParam;  // #2
$csrf_token = Yii::$app->request->csrfToken;

$this->registerJs("
$('div.post-index').on('click', 'tr', function() { // #3
    var id = $(this).data('key'); // #4
    $.ajax({
		'type' : 'GET',
		'url' : '$ajax_url',
		'dataType' : 'html',
		'data' : {
			'$csrf_param' : '$csrf_token', // #2
			'id' : id
		},
		'success' : function(data){ // #5
			$('#post-detail').html(data);
		}
    });
});
");
?>

Here are some tips and hints.

  1. yii\helpers\Url::to() generates an url string that can be used in javascript.

  2. Because we need to have CSRF protection token sent in the ajax request, we get its parameter name and value from the Request application component.

  3. We have attached an 'click' event handler on the rows of the GridView table. You might think "$('tr').on('click', function(){ ..." may also work, but it would not. The event handler should be attached to an element that is outside of the Pjax area.

  4. The key attribute (usually 'id') of the row can be retrieved easily in this way.

  5. When the ajax call has been successful, the contents of "post-detail" div will be replaced by the ajax response that was rendered by "actionAjaxView" method.

Conclusion

That's all. There's nothing so complicated here.

You may want to do something more to improve your page. The first thing you may want to do might be supplying more appropriate initial display of the selected post. It's up to you.

Have fun!

]]>
0