• No results found

Performance Profiling

In document Yii2-Guide (New) (Page 160-165)

'db' => [

'class' => 'yii\log\DbTarget', ],

], ], ], ];

Creating a new log target class is very simple. You mainly need to implement the [[yii\log\Target::export()]] method sending the content of the [[yii\log\Target::messages]] array to a designated medium. You may call the

[[yii\log\Target::formatMessage()]] method to format each message. For more details, you may refer to any of the log target classes included in the Yii release.

Performance profiling is a special type of message logging that is used to measure the time taken by certain code blocks and find out what are the performance bottlenecks. For example, the [[yii\db\Command]] class uses performance profiling to find out the time taken by each DB query.

To use performance profiling, first identify the code blocks that need to be profiled. Then enclose each code block like the following:

\Yii::beginProfile('myBenchmark');

...code block being profiled...

\Yii::endProfile('myBenchmark');

where myBenchmark stands for a unique token identifying a code block. Later when you examine the profiling result, you will use this token to locate the time spent by the corresponding code block.

It is important to make sure that the pairs of beginProfile and endProfile are properly nested. For example,

\Yii::beginProfile('block1');

// some code to be profiled

\Yii::beginProfile('block2');

// some other code to be profiled \Yii::endProfile('block2');

\Yii::endProfile('block1');

If you miss \Yii::endProfile('block1') or switch the order of \Yii::endProfile('block1') and

\Yii::endProfile('block2') , the performance profiling will not work.

For each code block being profiled, a log message with the severity level profile is recorded. You can configure a log target to collect such messages and export them. The Yii debugger has a built-in performance profiling panel showing the profiling results.

Creating New Targets

Performance Profiling

160 Logging

Components are the main building blocks of Yii applications. Components are instances of [[yii\base\Component]], or an extended class. The three main features that components provide to other classes are:

Properties Events Behaviors

Separately and combined, these features make Yii classes much more customizable and easier to use. For example, the included [[yii\jui\DatePicker|date picker widget]], a user interface component, can be used in a view to generate an interactive date picker:

use yii\jui\DatePicker;

echo DatePicker::widget([

'language' => 'ru', 'name' => 'country', 'clientOptions' => [

'dateFormat' => 'yy-mm-dd', ],

]);

The widget's properties are easily writable because the class extends [[yii\base\Component]].

While components are very powerful, they are a bit heavier than normal objects, due to the fact that it takes extra memory and CPU time to support event and behavior functionality in particular. If your components do not need these two features, you may consider extending your component class from [[yii\base\Object]] instead of [[yii\base\Component]]. Doing so will make your components as efficient as normal PHP objects, but with added support for properties.

When extending your class from [[yii\base\Component]] or [[yii\base\Object]], it is recommended that you follow these conventions:

If you override the constructor, specify a $config parameter as the constructor's last parameter, and then pass this parameter to the parent constructor.

Always call the parent constructor at the end of your overriding constructor.

If you override the [[yii\base\Object::init()]] method, make sure you call the parent implementation of init at the beginning of your init method.

For example:

<?php

namespace yii\components\MyClass;

use yii\base\Object;

class MyClass extends Object {

public $prop1;

public $prop2;

public function __construct($param1, $param2, $config = []) {

// ... initialization before configuration is applied

parent::__construct($config);

}

Components

161 Components

{

parent::init();

// ... initialization after configuration is applied }

}

Following these guidelines will make your components configurable when they are created. For example:

$component = new MyClass(1, 2, ['prop1' => 3, 'prop2' => 4]);

// alternatively

$component = \Yii::createObject([

'class' => MyClass::className(), 'prop1' => 3,

'prop2' => 4, ], [1, 2]);

Info: While the approach of calling [[Yii::createObject()]] looks more complicated, it is more powerful because it is implemented on top of a dependency injection container.

The [[yii\base\Object]] class enforces the following object lifecycle:

1. Pre-initialization within the constructor. You can set default property values here.

2. Object configuration via $config . The configuration may overwrite the default values set within the constructor.

3. Post-initialization within [[yii\base\Object::init()|init()]]. You may override this method to perform sanity checks and normalization of the properties.

4. Object method calls.

The first three steps all happen within the object's constructor. This means that once you get a class instance (i.e., an object), that object has already been initialized to a proper, reliable state.

162 Components

In PHP, class member variables are also called properties. These variables are part of the class definition, and are used to represent the state of a class instance (i.e., to differentiate one instance of the class from another). In practice, you may often want to handle the reading or writing of properties in special ways. For example, you may want to always trim a string when it is being assigned to a label property. You could use the following code to achieve this task:

$object->label = trim($label);

The drawback of the above code is that you would have to call trim() everywhere in your code where you might set the

label property. If, in the future, the label property gets a new requirement, such as the first letter must be capitalized, you would again have to modify every bit of code that assigns a value to label . The repetition of code leads to bugs, and is a practice you want to avoid as much as possible.

To solve this problem, Yii introduces a base class called [[yii\base\Object]] that supports defining properties based on getter and setter class methods. If a class needs that functionality, it should extend from [[yii\base\Object]], or from a child class.

Info: Nearly every core class in the Yii framework extends from [[yii\base\Object]] or a child class. This means that whenever you see a getter or setter in a core class, you can use it like a property.

A getter method is a method whose name starts with the word get ; a setter method starts with set . The name after the

get or set prefix defines the name of a property. For example, a getter getLabel() and/or a setter setLabel() defines a property named label , as shown in the following code:

namespace app\components;

use yii\base\Object;

class Foo extends Object {

private $_label;

public function getLabel() {

return $this->_label;

}

public function setLabel($value) {

$this->_label = trim($value);

} }

(To be clear, the getter and setter methods create the property label , which in this case internally refers to a private attribute named _label .)

Properties defined by getters and setters can be used like class member variables. The main difference is that when such property is being read, the corresponding getter method will be called; when the property is being assigned a value, the corresponding setter method will be called. For example:

// equivalent to $label = $object->getLabel();

$label = $object->label;

// equivalent to $object->setLabel('abc');

$object->label = 'abc';

Properties

163 Properties

[[yii\base\InvalidCallException|InvalidCallException]]. Similarly, a property defined by a setter without a getter is write only, and trying to read such a property will also cause an exception. It is not common to have write-only properties.

There are several special rules for, and limitations on, the properties defined via getters and setters:

The names of such properties are case-insensitive. For example, $object->label and $object->Label are the same.

This is because method names in PHP are case-insensitive.

If the name of such a property is the same as a class member variable, the latter will take precedence. For example, if the above Foo class has a member variable label , then the assignment $object->label = 'abc' will affect the member variable 'label'; that line would not call the setLabel() setter method.

These properties do not support visibility. It makes no difference to the defining getter or setter method if the property is public, protected or private.

The properties can only be defined by non-static getters and/or setters. Static methods will not be treated in the same manner.

Returning back to the problem described at the beginning of this guide, instead of calling trim() everywhere a label

value is assigned, trim() now only needs to be invoked within the setter setLabel() . And if a new requirement makes it necesary that the label be initially capitalized, the setLabel() method can quickly be modified without touching any other code. The one change will universally affect every assignment to label .

164 Properties

Events allow you to inject custom code into existing code at certain execution points. You can attach custom code to an event so that when the event is triggered, the code gets executed automatically. For example, a mailer object may trigger a

messageSent event when it successfully sends a message. If you want to keep track of the messages that are successfully sent, you could then simply attach the tracking code to the messageSent event.

Yii introduces a base class called [[yii\base\Component]] to support events. If a class needs to trigger events, it should extend from [[yii\base\Component]], or from a child class.

An event handler is a PHP callback that gets executed when the event it is attached to is triggered. You can use any of the following callbacks:

a global PHP function specified as a string (without parentheses), e.g., 'trim' ;

an object method specified as an array of an object and a method name as a string (without parentheses), e.g.,

[$object, 'methodName'] ;

a static class method specified as an array of a class name and a method name as a string (without parentheses), e.g.,

['ClassName', 'methodName'] ;

an anonymous function, e.g., function ($event) { ... } .

The signature of an event handler is:

function ($event) {

// $event is an object of yii\base\Event or a child class }

Through the $event parameter, an event handler may get the following information about the event that occurred:

[[yii\base\Event::name|event name]]

[[yii\base\Event::sender|event sender]]: the object whose trigger() method was called

[[yii\base\Event::data|custom data]]: the data that is provided when attaching the event handler (to be explained next)

You can attach a handler to an event by calling the [[yii\base\Component::on()]] method. For example:

$foo = new Foo;

// this handler is a global function

$foo->on(Foo::EVENT_HELLO, 'function_name');

// this handler is an object method

$foo->on(Foo::EVENT_HELLO, [$object, 'methodName']);

// this handler is a static class method

$foo->on(Foo::EVENT_HELLO, ['app\components\Bar', 'methodName']);

// this handler is an anonymous function

$foo->on(Foo::EVENT_HELLO, function ($event) { // event handling logic

});

In document Yii2-Guide (New) (Page 160-165)

Related documents