Yii2 dev digest #3 Dec'13 > stdout.in Ievgen Kuzminov IT blog

Yii2 dev digest #3 Dec'13

Dec 19, 2013, 1:47:02 PM

Official CHANGELOG appeared so my digests could be not so useful now
but in any case I will keep going :)

Discussions

that could be interesting to participate in

Take a look into and share your view on these questions Implement Transaction strategy for database cleanup (start transaction for connection and then rollback) Implement Reset strategy for database cleanup (tables truncate) Implement Drop/Create strategy for database cleanup (drop tables then create them <->)

What's new

Namespace and package names Extension MUST use the type yii2-extension in composer.json file. Extension MUST NOT use yii or yii2 in the composer package name or in the namespaces used in the package. Extension SHOULD use namespaces in this format vendor-name\package (all lowercase). Extension MAY use a yii2- prefix in the composer vendor name (URL). Extension MAY use a yii2- prefix in the repository name (URL). etc...

Acceptance tests integration and examples Functional tests integration and examples Unit tests integration and examples

@cebe : I think we can close this issue now. I am done with all the system I know and can support as I am going to work with them on a regular basis. Others should be provided as extensions or by other core developers. If someone wants to start working on an implementation of an AR feel free to contact me, I can help with that.

Extensions for Yii2

Yii2 Tips & Hints

CAPTCHA and AJAX

@qiangxue : Note that once CAPTCHA validation succeeds, a new CAPTCHA will be generated automatically. As a result, CAPTCHA validation should not be used in AJAX validation mode because it may fail the validation even if a user enters the same code as shown in the CAPTCHA image which is actually different from the latest CAPTCHA code.

How to exclude some type of errors from logging ?

with ` 'except' => ['yii\web\HttpException\404'] `

This is the configuration in the app's params:

        'components.log' => [
                'traceLevel' => 0,
                'targets' => [
                        'file' => [
                                'class' => 'yii\log\FileTarget',
                                'levels' => ['error', 'warning'],
                        ],
                        'email' => [
                                'class' => 'yii\log\EmailTarget',
                                'except' => ['yii\web\HttpException\404'],
                                'levels' => ['error', 'warning'],
                                'message' => ['from' => 'webmaster@mydomain.com', 'to' => 'webmaster@mydomain.com'],
                        ],
                ],
        ]

Dropdown with related values

@omnilight :

class Author extends ActiveRecord
{
    public function getBooks()
    {
        return $this->hasMany(Book::className(), 'author_id' => 'id');
    }

    public function setBooks(array $books)
    {
        Book::updateAll(['author_id' => 0], 'author_id = :author', [':author' => $this->id]);
        foreach($books as $id) {
            $this->link('books', Book::find($id));
        }
    }
}
...
<?= $form->field($book, 'books')->dropDownList(ArrayHelper::map(Books::find()->all(), 'id', 'title'); ?>
...

ActiveRecord::afterFind() not called with asArray() ?

@qiangxue : Since you are returning array instead of AR object, there's no afterFind() that can be called upon. This is expected behavior.

Custom inline validation

@cebe : This is not how it works. Inline validator is something different.
In rules you need:
['languages', 'validateSomething']
And then you add a method to the model:

public function validateSomething($attribute) {
    $value = $this->$attribute;
    if($value <= 10) {
         $this->addError($attribute, 'value must be >10');
    }
}

Dynamically add rules to Urlmanager

asofter :

  Yii::$app->urlManager->rules[] = Yii::createObject(
            [
                'class' => 'app\modules\pages\components\PagesUrlRule',
                'pattern' => '[0-9a-zA-Z_\-]+>',
                'route' => '<module:(pages)>/<controller>/<action>'
            ]
        );

Execute additional SQL queries right after establishing a connection

@samdark : Tip: if you need to execute additional SQL queries right after establishing a connection you can add the following to your application configuration file:

 return [
   // ...
   'components' => [
     // ...
     'db' => [
       'class' => 'yii\db\Connection',
       // ...
       'on afterOpen' => function($event) {
         $event->sender->createCommand("SET time_zone = 'UTC'")->execute();
       }
     ],
   ],
   // ...
 ];

UrlValidator note

@qiangxue : Note that this validator only checks if the URL scheme and host part are correct. It does not check the rest part of a URL.

To use action names in CamelCase like actionContactUs

@ : In request and urlManagerYou should use dash-separated notation like contact-us

GII code notice

@cebe : Note: The code generated by gii is only a template that has to be adjusted to your needs. It is there to help you create new things quickly but it is not something that creates ready to use code. We often see people using the models generated by gii without change and just extend them to adjust some parts of it. This is not how it is ment to be used. Code generated by gii may be incomplete or incorrect and has to be changed to fit your needs before you can use it.

Default scope

@cebe : You may also define default conditions that should apply to all queries unless overridden: Note that all queries should use Query::andWhere() and Query::orWhere() to keep the default

 public static function createQuery()
 {
 return parent::createQuery()->where(['deleted' => false]);
 }

Filtering / sorting for calculated data

@cebe : to allow sorting and filtering your value has to be calculated in the database. if your model calculates it in afterFind() or similar way you are not able to filter or sort by that field anymore. You can add values to the select query like this: $query->select[] = 'SUM(price) AS subtotal';
You also need to declare a property in your AR class to hold the value after find.

Read previous digests

comments powered by Disqus
Ievgen
Kuzminov "iJackUA"
Web Team Lead
at MobiDev (Kharkiv, Ukraine)
Code in Ruby and Elixir, but still love PHP. Explore ES6 and Vue.js. Explore databases, use Ubuntu and MacOS, think about IT people and management

Notes


Nightly blog update was not perfectly seamless. It's a pity I have no time for auto-tests yet, so let's consider it as "normal". If you got any bugs - feel free to write about it in comments ;)