From 5b8cf206b96ffb4aad2c2e7a26ee84a94b9679cc Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Tue, 29 Apr 2014 13:18:50 -0400 Subject: [PATCH] guide wip [skip ci] --- docs/guide/README.md | 50 +++-- docs/guide/basic-aliases.md | 25 +++ docs/guide/basic-autoloading.md | 19 ++ docs/guide/basic-configs.md | 44 ++++ docs/guide/basic-di-container.md | 245 ++++++++++++++++++++ docs/guide/basic-properties.md | 146 ++++-------- docs/guide/basic-service-locator.md | 250 +-------------------- docs/guide/bootstrap-widgets.md | 4 +- docs/guide/caching-overview.md | 2 + docs/guide/db-active-record.md | 2 + docs/guide/db-dao.md | 2 + docs/guide/db-migrations.md | 2 + docs/guide/db-query-builder.md | 2 + docs/guide/extend-creating-extensions.md | 3 + docs/guide/extend-customizing-core.md | 2 + docs/guide/extend-using-composer.md | 2 + docs/guide/extend-using-libs.md | 2 + docs/guide/helper-overview.md | 27 +++ docs/guide/input-forms.md | 2 + docs/guide/input-validation.md | 2 + docs/guide/output-assets.md | 2 + docs/guide/output-data-providers.md | 2 + docs/guide/output-data-widgets.md | 2 + docs/guide/rest-quick-start.md | 2 + docs/guide/runtime-url-handling.md | 2 + docs/guide/security-authentication.md | 2 + docs/guide/security-authorization.md | 2 + docs/guide/security-passwords.md | 2 + docs/guide/start-advanced.md | 2 + docs/guide/start-basic.md | 2 + docs/guide/start-scratch.md | 2 + docs/guide/structure-controllers.md | 2 + docs/guide/structure-models.md | 2 + docs/guide/structure-mvc.md | 4 +- docs/guide/structure-views.md | 2 + docs/guide/test-fixtures.md | 2 + docs/guide/tool-debugger.md | 2 + docs/guide/tool-gii.md | 2 + docs/guide/tutorial-configuring-servers.md | 2 + docs/guide/tutorial-console.md | 2 + docs/guide/tutorial-handling-errors.md | 2 + docs/guide/tutorial-i18n.md | 2 + docs/guide/tutorial-logging.md | 2 + docs/guide/tutorial-performance-tuning.md | 2 + docs/guide/tutorial-template-engines.md | 2 + docs/guide/tutorial-theming.md | 2 + 46 files changed, 515 insertions(+), 372 deletions(-) create mode 100644 docs/guide/basic-aliases.md create mode 100644 docs/guide/basic-autoloading.md create mode 100644 docs/guide/basic-di-container.md create mode 100644 docs/guide/helper-overview.md diff --git a/docs/guide/README.md b/docs/guide/README.md index ec1473400fc..1e0a827cb95 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -23,6 +23,7 @@ Getting Started * [Starting with Advanced App](start-advanced.md) - Best for developing an enterprise application by a team * [Starting from Scratch](start-scratch.md) - Learning more in-depth details of creating a Yii application step-by-step + Basic Concepts -------------- @@ -30,11 +31,11 @@ Basic Concepts * [Events](basic-events.md) * [Behaviors](basic-behaviors.md) * [Object Configurations](basic-configs.md) -* **TBD** [Class Autoloading](basic-autoloading.md) -* **TBD** [Path Aliases](basic-alias.md) +* [Class Autoloading](basic-autoloading.md) +* [Path Aliases](basic-alias.md) * **TBD** [Extensions](basic-extensions.md) * [Service Locator](basic-service-locator.md) -* **TBD** [Dependency Injection Container](basic-di-container.md) +* [Dependency Injection Container](basic-di-container.md) Basic Structure @@ -63,6 +64,19 @@ Handling Requests * **TBD** [Filtering](runtime-filtering.md) +Working with Databases +---------------------- + +* [Data Access Objects](db-dao.md) - Connecting to a database, basic queries, transactions and schema manipulation +* [Query Builder](db-query-builder.md) - Querying the database using a simple abstraction layer +* [Active Record](db-active-record.md) - The active record ORM, retrieving and manipulating records and defining relations +* [Migrations](db-migrations.md) - Version control your databases in a team development environment +* **TBD** [Sphinx](db-sphinx.md) +* **TBD** [Redis](db-redis.md) +* **TBD** [MongoDB](db-mongodb.md) +* **TBD** [ElasticSearch](db-elastic-search.md) + + Collecting Inputs ----------------- @@ -83,19 +97,6 @@ Presenting Data * [Managing Assets](output-assets.md) -Working with Database ---------------------- - -* [Data Access Objects](db-dao.md) - Connecting to a database, basic queries, transactions and schema manipulation -* [Query Builder](db-query-builder.md) - Querying the database using a simple abstraction layer -* [Active Record](db-active-record.md) - The active record ORM, retrieving and manipulating records and defining relations -* [Migrations](db-migrations.md) -* **TBD** [Sphinx](db-sphinx.md) -* **TBD** [Redis](db-redis.md) -* **TBD** [MongoDB](db-mongodb.md) -* **TBD** [ElasticSearch](db-elastic-search.md) - - Security -------- @@ -130,6 +131,14 @@ RESTful Web Services * **TBD** [Testing](rest-testing.md) +Development Tools +----------------- + +* [Debug Toolbar and Debugger](tool-debugger.md) +* [Generating Code using Gii](tool-gii.md) +* **TBD** [Generating API Documentation](tool-api-doc.md) + + Testing ------- @@ -151,14 +160,6 @@ Extending Yii * [Using Composer](extend-using-composer.md) -Development Tools ------------------ - -* [Debug Toolbar and Debugger](tool-debugger.md) -* [Generating Code using Gii](tool-gii.md) -* **TBD** [Generating API Documentation](tool-api-doc.md) - - Special Topics -------------- @@ -192,6 +193,7 @@ Widgets Helpers ------- +* [Overview](helper-overview.md) * **TBD** [ArrayHelper](helper-array.md) * **TBD** [Html](helper-html.md) * **TBD** [Url](helper-url.md) diff --git a/docs/guide/basic-aliases.md b/docs/guide/basic-aliases.md new file mode 100644 index 00000000000..1da0ce28fab --- /dev/null +++ b/docs/guide/basic-aliases.md @@ -0,0 +1,25 @@ +Path Aliases +============ + +> Note: This chapter is under development. + +Yii 2.0 expands the usage of path aliases to both file/directory paths and URLs. An alias +must start with an `@` symbol so that it can be differentiated from file/directory paths and URLs. +For example, the alias `@yii` refers to the Yii installation directory while `@web` contains the base URL for the currently running web application. Path aliases are supported in most places in the Yii core code. For example, `FileCache::cachePath` can accept both a path alias and a normal directory path. + +Path aliases are also closely related to class namespaces. It is recommended that a path +alias should be defined for each root namespace so that Yii's class autoloader can be used without +any further configuration. For example, because `@yii` refers to the Yii installation directory, +a class like `yii\web\Request` can be autoloaded by Yii. If you use a third party library +such as Zend Framework, you may define a path alias `@Zend` which refers to its installation +directory and Yii will be able to autoload any class in this library. + +The following aliases are predefined by the core framework: + +- `@yii` - framework directory. +- `@app` - base path of currently running application. +- `@runtime` - runtime directory. +- `@vendor` - Composer vendor directory. +- `@webroot` - web root directory of currently running web application. +- `@web` - base URL of currently running web application. + diff --git a/docs/guide/basic-autoloading.md b/docs/guide/basic-autoloading.md new file mode 100644 index 00000000000..12a981c0327 --- /dev/null +++ b/docs/guide/basic-autoloading.md @@ -0,0 +1,19 @@ +Autoloading +=========== + +> Note: This chapter is under development. + +All classes, interfaces and traits are loaded automatically at the moment they are used. There's no need to use `include` or `require`. It is true for Composer-loaded packages as well as Yii extensions. + +Yii's autoloader works according to [PSR-4](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md). +That means namespaces, classes, interfaces and traits must correspond to file system paths and file names accordinly, except for root namespace paths that are defined by an alias. + +For example, if the standard alias `@app` refers to `/var/www/example.com/` then `\app\models\User` will be loaded from `/var/www/example.com/models/User.php`. + +Custom aliases may be added using the following code: + +```php +Yii::setAlias('@shared', realpath('~/src/shared')); +``` + +Additional autoloaders may be registered using PHP's standard `spl_autoload_register`. diff --git a/docs/guide/basic-configs.md b/docs/guide/basic-configs.md index 17ddf5c0fab..d4a849478fb 100644 --- a/docs/guide/basic-configs.md +++ b/docs/guide/basic-configs.md @@ -1,6 +1,50 @@ Configuration ============= +> Note: This chapter is under development. + +Object Configuration +-------------------- + +The [[yii\base\Object|Object]] class introduces a uniform way of configuring objects. Any descendant class +of [[yii\base\Object|Object]] should declare its constructor (if needed) in the following way so that +it can be properly configured: + +```php +class MyClass extends \yii\base\Object +{ + public function __construct($param1, $param2, $config = []) + { + // ... initialization before configuration is applied + + parent::__construct($config); + } + + public function init() + { + parent::init(); + + // ... initialization after configuration is applied + } +} +``` + +In the above example, the last parameter of the constructor must take a configuration array +which contains name-value pairs that will be used to initialize the object's properties at the end of the constructor. +You can override the `init()` method to do initialization work after the configuration is applied. + +By following this convention, you will be able to create and configure new objects +using a configuration array like the following: + +```php +$object = Yii::createObject([ + 'class' => 'MyClass', + 'property1' => 'abc', + 'property2' => 'cde', +], [$param1, $param2]); +``` + + Yii applications rely upon components to perform most of the common tasks, such as connecting to a database, routing browser requests, and handling sessions. How these stock components behave can be adjusted by *configuring* your Yii application. The majority of components have sensible default settings, so it's unlikely that you'll do a lot of configuration. Still, there are some mandatory configuration settings that you will have to establish, such as the database connection. diff --git a/docs/guide/basic-di-container.md b/docs/guide/basic-di-container.md new file mode 100644 index 00000000000..b175f5f4c19 --- /dev/null +++ b/docs/guide/basic-di-container.md @@ -0,0 +1,245 @@ +Dependency Injection Container +============================== + +Both service locator and dependency injection are popular design patterns that allow building software +in a loosely-coupled fashion. Yii uses service locator and dependency injection extensively, +even though you may not be aware of them. In this tutorial, we will explore their implementation +and support to help you write code more consciously. We also highly recommend you to read +[Martin's article](http://martinfowler.com/articles/injection.html) to get a deeper understanding of +service locator and dependency injection. + +A dependency injection (DI) container is an object that knows how to instantiate and configure objects and +all their dependent objects. [Martin's article](http://martinfowler.com/articles/injection.html) has well +explained why DI container is useful. Here we will mainly explain the usage of the DI container provided by Yii. + +Yii provides the DI container feature through the class [[yii\di\Container]]. It supports the following kinds of +dependency injection: + +* Constructor injection; +* Setter injection; +* PHP callable injection. + + +### Registering Dependencies + +You can use [[yii\di\Container::set()]] to register dependencies. The registration requires a dependency name +as well as a dependency definition. The name can be a class name, an interface name, or an alias name; +and the definition can be a class name, a configuration array, or a PHP callable. + +```php +$container = new \yii\di\Container; + +// register a class name as is. This can be skipped. +$container->set('yii\db\Connection'); + +// register an interface +// When a class depends on the interface, the corresponding class +// will be instantiated as the dependent object +$container->set('yii\mail\MailInterface', 'yii\swiftmailer\Mailer'); + +// register an alias name. You can use $container->get('foo') +// to create an instance of Connection +$container->set('foo', 'yii\db\Connection'); + +// register a class with configuration. The configuration +// will be applied when the class is instantiated by get() +$container->set('yii\db\Connection', [ + 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', +]); + +// register an alias name with class configuration +// In this case, a "class" element is required to specify the class +$container->set('db', [ + 'class' => 'yii\db\Connection', + 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', +]); + +// register a PHP callable +// The callable will be executed when $container->get('db') is called +$container->set('db', function ($container, $params, $config) { + return new \yii\db\Connection($config); +}); +``` + +> Tip: If a dependency name is the same as the corresponding dependency definition, you do not + need to register it with the DI container. + +A dependency registered via `set()` will generate an instance each time the dependency is needed. +You can use [[yii\di\Container::setSingleton()]] to register a dependency that only generates +a single instance: + +```php +$container->setSingleton('yii\db\Connection', [ + 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', + 'username' => 'root', + 'password' => '', + 'charset' => 'utf8', +]); +``` + + +### Resolving Dependencies + +Once you have registered dependencies, you can use the DI container to create new objects, +and the container will automatically resolve dependencies by instantiating them and injecting +them into the newly created objects. The dependency resolution is recursive, meaning that +if a dependency has other dependencies, those dependencies will also be resolved automatically. + +You use [[yii\di\Container::get()]] to create new objects. The method takes a class name or +a dependency name (class name, interface name or alias name) that you previously registered +via `set()` or `setSingleton()`. You may optionally provide a list of class constructor parameters +and a list of name-value pairs to configure the newly created object. For example, + +```php +// equivalent to: $map = new \app\components\GoogleMap($apiKey); +$map = $container->get('app\components\GoogleMap', [$apiKey]); + +// "db" is a previously registered alias name +$db = $container->get('db'); +``` + +Behind the scene, the DI container does much more work than just creating a new object. +The container will inspect the class constructor to find out dependent class or interface names +and then automatically resolve those dependencies recursively. + +The following code shows a more sophisticated example. The `UserLister` class depends on an object implementing +the `UserFinderInterface` interface; the `UserFinder` class implements this interface and depends on +a `Connection` object. All these dependencies are declared through type hinting of the class constructor parameters. +With property dependency registration, the DI container is able to resolve these dependencies automatically +and creates a new `UserLister` instance with a simple call of `get('userLister')`. + + +```php +namespace app\models; + +use yii\base\Object; +use yii\db\Connection; +use yii\di\Container; + +interface UserFinderInterface +{ + function findUser(); +} + +class UserFinder extends Object implements UserFinderInterface +{ + public $db; + + public function __construct(Connection $db, $config = []) + { + $this->db = $db; + parent::__construct($config); + } + + public function findUser() + { + } +} + +class UserLister extends Object +{ + public $finder; + + public function __construct(UserFinderInterface $finder, $config = []) + { + $this->finder = $finder; + parent::__construct($config); + } +} + +$container = new Container; +$container->set('yii\db\Connection', [ + 'dsn' => '...', +]); +$container->set('app\models\UserFinderInterface', [ + 'class' => 'app\models\UserFinder', +]); +$container->set('userLister', 'app\models\UserLister'); + +$lister = $container->get('userLister'); + +// which is equivalent to: + +$db = new \yii\db\Connection(['dsn' => '...']); +$finder = new UserFinder($db); +$lister = new UserLister($finder); +``` + + +### Practical Usage + +Yii creates a DI container when you include the `yii.php` file in your application's entry script. +The DI container is accessible via [[Yii::$container]]. When you call [[Yii::createObject()]], the method +will actually call the container's [[yii\di\Container::get()|get()]] method to create a new object. +As aforementioned, the DI container will automatically resolve the dependencies (if any) and inject them +into the newly created object. Because Yii uses [[Yii::createObject()]] in most of its core code to create +new objects, this means you can customize the objects globally by dealing with [[Yii::$container]]. + +For example, you can customize globally the default number of pagination buttons of [[yii\widgets\LinkPager]]: + +```php +\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]); +``` + +Now if you use the widget in a view with the following code, the `maxButtonCount` property will be initialized +as 5 instead of 10 as defined in the class. + +```php +echo \yii\widgets\LinkPager::widget(); +``` + +You can still override the value set via DI container: + +```php +echo \yii\widgets\LinkPager::widget(['maxButtonCount' => 20]); +``` + +Another example is to take advantage of the automatic constructor injection of the DI container. +Assume your controller class depends on some other objects, such as a hotel booking service. You +can declare the dependency through a constructor parameter and let the DI container to resolve it for you. + +```php +namespace app\controllers; + +use yii\web\Controller; +use app\components\BookingInterface; + +class HotelController extends Controller +{ + protected $bookingService; + + public function __construct($id, $module, BookingInterface $bookingService, $config = []) + { + $this->bookingService = $bookingService; + parent::__construct($id, $module, $config); + } +} +``` + +If you access this controller from browser, you will see an error complaining the `BookingInterface` +cannot be instantiated. This is because you need to tell the DI container how to deal with this dependency: + +```php +\Yii::$container->set('app\components\BookingInterface', 'app\components\BookingService'); +``` + +Now if you access the controller again, an instance of `app\components\BookingService` will be +created and injected as the 3rd parameter to the controller's constructor. + + +### When to Register Dependencies + +Because dependencies are needed when new objects are being created, their registration should be done +as early as possible. The followings are the recommended practices: + +* If you are the developer of an application, you can register dependencies in your + application's entry script or in a script that is included by the entry script. +* If you are the developer of a redistributable extension, you can register dependencies + in the bootstrap class of the extension. + diff --git a/docs/guide/basic-properties.md b/docs/guide/basic-properties.md index e613d1b940f..cfd165b1c7d 100644 --- a/docs/guide/basic-properties.md +++ b/docs/guide/basic-properties.md @@ -1,126 +1,72 @@ -Basic concepts of Yii -===================== +Object Properties +================= +In PHP, class member variables are also called *properties*. They are part of a class definition and are used +to represent the state of a class instance. In practice, you may often want to do some special handling when +a property is being read or modified. For example, you may want to trim a string when it is being assigned +to a `label` property. You could use the following code to achieve this task: -Component and Object --------------------- - -Classes of the Yii framework usually extend from one of the two base classes [[yii\base\Object]] or [[yii\base\Component]]. -These classes provide useful features that are added automatically to all classes extending from them. +```php +$object->label = trim($label); +``` -The [[yii\base\Object|Object]] class provides the [configuration and property feature](../api/base/Object.md). -The [[yii\base\Component|Component]] class extends from [[yii\base\Object|Object]] and adds -[event handling](events.md) and [behaviors](behaviors.md). +The drawback of the above code is that you have to call `trim()` everywhere whenever you modify the `label` +property. And if in future, the `label` property has a new requirement, such as the first letter must be turned +into upper case, you would have to modify all those places - a practice you want to avoid as much as possible. -[[yii\base\Object|Object]] is usually used for classes that represent basic data structures while -[[yii\base\Component|Component]] is used for application components and other classes that implement higher logic. +To solve this problem, Yii introduces the support for defining properties based on *getter* and *setter* class methods. +**A class must extend from [[yii\base\Object]] or its child class if it wants to get this support.** +A getter method is a method whose name starts with the word `get`, while 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: -Object Configuration --------------------- +```php +namespace app\components; -The [[yii\base\Object|Object]] class introduces a uniform way of configuring objects. Any descendant class -of [[yii\base\Object|Object]] should declare its constructor (if needed) in the following way so that -it can be properly configured: +use yii\base\Object; -```php -class MyClass extends \yii\base\Object +class Foo extend Object { - public function __construct($param1, $param2, $config = []) - { - // ... initialization before configuration is applied + private $_label; - parent::__construct($config); + public function getLabel() + { + return $this->_label; } - public function init() + public function setLabel($value) { - parent::init(); - - // ... initialization after configuration is applied + $this->_label = trim($value); } } ``` -In the above example, the last parameter of the constructor must take a configuration array -which contains name-value pairs that will be used to initialize the object's properties at the end of the constructor. -You can override the `init()` method to do initialization work after the configuration is applied. - -By following this convention, you will be able to create and configure new objects -using a configuration array like the following: +Properties defined by getters/setters can be used like class member variables. The main difference is that +when such a property is being read, the corresponding getter method will be called; and when the property is +being assigned, the corresponding setter method will be called. For example, ```php -$object = Yii::createObject([ - 'class' => 'MyClass', - 'property1' => 'abc', - 'property2' => 'cde', -], [$param1, $param2]); -``` - - -Path Aliases ------------- +// equivalent to $label = $object->getLabel(); +$label = $object->label; -Yii 2.0 expands the usage of path aliases to both file/directory paths and URLs. An alias -must start with an `@` symbol so that it can be differentiated from file/directory paths and URLs. -For example, the alias `@yii` refers to the Yii installation directory while `@web` contains the base URL for the currently running web application. Path aliases are supported in most places in the Yii core code. For example, `FileCache::cachePath` can accept both a path alias and a normal directory path. - -Path aliases are also closely related to class namespaces. It is recommended that a path -alias should be defined for each root namespace so that Yii's class autoloader can be used without -any further configuration. For example, because `@yii` refers to the Yii installation directory, -a class like `yii\web\Request` can be autoloaded by Yii. If you use a third party library -such as Zend Framework, you may define a path alias `@Zend` which refers to its installation -directory and Yii will be able to autoload any class in this library. - -The following aliases are predefined by the core framework: - -- `@yii` - framework directory. -- `@app` - base path of currently running application. -- `@runtime` - runtime directory. -- `@vendor` - Composer vendor directory. -- `@webroot` - web root directory of currently running web application. -- `@web` - base URL of currently running web application. - -Autoloading ------------ - -All classes, interfaces and traits are loaded automatically at the moment they are used. There's no need to use `include` or `require`. It is true for Composer-loaded packages as well as Yii extensions. - -Yii's autoloader works according to [PSR-4](https://github.com/php-fig/fig-standards/blob/master/proposed/psr-4-autoloader/psr-4-autoloader.md). -That means namespaces, classes, interfaces and traits must correspond to file system paths and file names accordinly, except for root namespace paths that are defined by an alias. - -For example, if the standard alias `@app` refers to `/var/www/example.com/` then `\app\models\User` will be loaded from `/var/www/example.com/models/User.php`. - -Custom aliases may be added using the following code: - -```php -Yii::setAlias('@shared', realpath('~/src/shared')); +// equivalent to $object->setLabel('abc'); +$object->label = 'abc'; ``` -Additional autoloaders may be registered using PHP's standard `spl_autoload_register`. +A property defined by a getter without a setter is read only. Trying to assign a value to such a property will cause +an [[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. -Helper classes --------------- +Back to the problem we described at the beginning, the `trim()` function is now called within the setter `setLabel()`. +If a new requirement comes that the first letter of the label should be turned into upper case, we only need to +modify the `setLabel()` method without touching other code. -Helper classes typically contain static methods only and are used as follows: -```php -use \yii\helpers\Html; -echo Html::encode('Test > test'); -``` +There are some special rules or limitations of the properties defined based on getters and setters. +First, the names of such properties are *case-insensitive*. This is because PHP method names are case-insensitive. +Second, the properties do not support visibility. It makes no difference for the visibility of a property +if the defining getter or setter method is public, protected or private. Third, the properties can only +be defined by *non-static* getters and/or setters. Static methods do not count. -There are several classes provided by framework: - -- ArrayHelper -- Console -- FileHelper -- Html -- HtmlPurifier -- Image -- Inflector -- Json -- Markdown -- Security -- StringHelper -- Url -- VarDumper diff --git a/docs/guide/basic-service-locator.md b/docs/guide/basic-service-locator.md index 673ffe5864c..4350981acbe 100644 --- a/docs/guide/basic-service-locator.md +++ b/docs/guide/basic-service-locator.md @@ -1,5 +1,7 @@ -Service Locator and Dependency Injection -======================================== +Service Locator +=============== + +> Note: This chapter needs cleanup. Both service locator and dependency injection are popular design patterns that allow building software in a loosely-coupled fashion. Yii uses service locator and dependency injection extensively, @@ -8,10 +10,6 @@ and support to help you write code more consciously. We also highly recommend yo [Martin's article](http://martinfowler.com/articles/injection.html) to get a deeper understanding of service locator and dependency injection. - -Service Locator ---------------- - A service locator is an object that knows how to provide all sorts of services (or components) that an application might need. Within a service locator, each component has only a single instance which is uniquely identified by an ID. You use the ID to retrieve a component from the service locator. In Yii, a service locator is simply an instance @@ -87,243 +85,3 @@ return [ ], ]; ``` - - -Dependency Injection --------------------- - -A dependency injection (DI) container is an object that knows how to instantiate and configure objects and -all their dependent objects. [Martin's article](http://martinfowler.com/articles/injection.html) has well -explained why DI container is useful. Here we will mainly explain the usage of the DI container provided by Yii. - -Yii provides the DI container feature through the class [[yii\di\Container]]. It supports the following kinds of -dependency injection: - -* Constructor injection; -* Setter injection; -* PHP callable injection. - - -### Registering Dependencies - -You can use [[yii\di\Container::set()]] to register dependencies. The registration requires a dependency name -as well as a dependency definition. The name can be a class name, an interface name, or an alias name; -and the definition can be a class name, a configuration array, or a PHP callable. - -```php -$container = new \yii\di\Container; - -// register a class name as is. This can be skipped. -$container->set('yii\db\Connection'); - -// register an interface -// When a class depends on the interface, the corresponding class -// will be instantiated as the dependent object -$container->set('yii\mail\MailInterface', 'yii\swiftmailer\Mailer'); - -// register an alias name. You can use $container->get('foo') -// to create an instance of Connection -$container->set('foo', 'yii\db\Connection'); - -// register a class with configuration. The configuration -// will be applied when the class is instantiated by get() -$container->set('yii\db\Connection', [ - 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', - 'username' => 'root', - 'password' => '', - 'charset' => 'utf8', -]); - -// register an alias name with class configuration -// In this case, a "class" element is required to specify the class -$container->set('db', [ - 'class' => 'yii\db\Connection', - 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', - 'username' => 'root', - 'password' => '', - 'charset' => 'utf8', -]); - -// register a PHP callable -// The callable will be executed when $container->get('db') is called -$container->set('db', function ($container, $params, $config) { - return new \yii\db\Connection($config); -}); -``` - -> Tip: If a dependency name is the same as the corresponding dependency definition, you do not - need to register it with the DI container. - -A dependency registered via `set()` will generate an instance each time the dependency is needed. -You can use [[yii\di\Container::setSingleton()]] to register a dependency that only generates -a single instance: - -```php -$container->setSingleton('yii\db\Connection', [ - 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', - 'username' => 'root', - 'password' => '', - 'charset' => 'utf8', -]); -``` - - -### Resolving Dependencies - -Once you have registered dependencies, you can use the DI container to create new objects, -and the container will automatically resolve dependencies by instantiating them and injecting -them into the newly created objects. The dependency resolution is recursive, meaning that -if a dependency has other dependencies, those dependencies will also be resolved automatically. - -You use [[yii\di\Container::get()]] to create new objects. The method takes a class name or -a dependency name (class name, interface name or alias name) that you previously registered -via `set()` or `setSingleton()`. You may optionally provide a list of class constructor parameters -and a list of name-value pairs to configure the newly created object. For example, - -```php -// equivalent to: $map = new \app\components\GoogleMap($apiKey); -$map = $container->get('app\components\GoogleMap', [$apiKey]); - -// "db" is a previously registered alias name -$db = $container->get('db'); -``` - -Behind the scene, the DI container does much more work than just creating a new object. -The container will inspect the class constructor to find out dependent class or interface names -and then automatically resolve those dependencies recursively. - -The following code shows a more sophisticated example. The `UserLister` class depends on an object implementing -the `UserFinderInterface` interface; the `UserFinder` class implements this interface and depends on -a `Connection` object. All these dependencies are declared through type hinting of the class constructor parameters. -With property dependency registration, the DI container is able to resolve these dependencies automatically -and creates a new `UserLister` instance with a simple call of `get('userLister')`. - - -```php -namespace app\models; - -use yii\base\Object; -use yii\db\Connection; -use yii\di\Container; - -interface UserFinderInterface -{ - function findUser(); -} - -class UserFinder extends Object implements UserFinderInterface -{ - public $db; - - public function __construct(Connection $db, $config = []) - { - $this->db = $db; - parent::__construct($config); - } - - public function findUser() - { - } -} - -class UserLister extends Object -{ - public $finder; - - public function __construct(UserFinderInterface $finder, $config = []) - { - $this->finder = $finder; - parent::__construct($config); - } -} - -$container = new Container; -$container->set('yii\db\Connection', [ - 'dsn' => '...', -]); -$container->set('app\models\UserFinderInterface', [ - 'class' => 'app\models\UserFinder', -]); -$container->set('userLister', 'app\models\UserLister'); - -$lister = $container->get('userLister'); - -// which is equivalent to: - -$db = new \yii\db\Connection(['dsn' => '...']); -$finder = new UserFinder($db); -$lister = new UserLister($finder); -``` - - -### Practical Usage - -Yii creates a DI container when you include the `yii.php` file in your application's entry script. -The DI container is accessible via [[Yii::$container]]. When you call [[Yii::createObject()]], the method -will actually call the container's [[yii\di\Container::get()|get()]] method to create a new object. -As aforementioned, the DI container will automatically resolve the dependencies (if any) and inject them -into the newly created object. Because Yii uses [[Yii::createObject()]] in most of its core code to create -new objects, this means you can customize the objects globally by dealing with [[Yii::$container]]. - -For example, you can customize globally the default number of pagination buttons of [[yii\widgets\LinkPager]]: - -```php -\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]); -``` - -Now if you use the widget in a view with the following code, the `maxButtonCount` property will be initialized -as 5 instead of 10 as defined in the class. - -```php -echo \yii\widgets\LinkPager::widget(); -``` - -You can still override the value set via DI container: - -```php -echo \yii\widgets\LinkPager::widget(['maxButtonCount' => 20]); -``` - -Another example is to take advantage of the automatic constructor injection of the DI container. -Assume your controller class depends on some other objects, such as a hotel booking service. You -can declare the dependency through a constructor parameter and let the DI container to resolve it for you. - -```php -namespace app\controllers; - -use yii\web\Controller; -use app\components\BookingInterface; - -class HotelController extends Controller -{ - protected $bookingService; - - public function __construct($id, $module, BookingInterface $bookingService, $config = []) - { - $this->bookingService = $bookingService; - parent::__construct($id, $module, $config); - } -} -``` - -If you access this controller from browser, you will see an error complaining the `BookingInterface` -cannot be instantiated. This is because you need to tell the DI container how to deal with this dependency: - -```php -\Yii::$container->set('app\components\BookingInterface', 'app\components\BookingService'); -``` - -Now if you access the controller again, an instance of `app\components\BookingService` will be -created and injected as the 3rd parameter to the controller's constructor. - - -### When to Register Dependencies - -Because dependencies are needed when new objects are being created, their registration should be done -as early as possible. The followings are the recommended practices: - -* If you are the developer of an application, you can register dependencies in your - application's entry script or in a script that is included by the entry script. -* If you are the developer of a redistributable extension, you can register dependencies - in the bootstrap class of the extension. - diff --git a/docs/guide/bootstrap-widgets.md b/docs/guide/bootstrap-widgets.md index 9ee70aeec1e..6fc96ac2217 100644 --- a/docs/guide/bootstrap-widgets.md +++ b/docs/guide/bootstrap-widgets.md @@ -1,6 +1,8 @@ -Bootstrap widgets +Bootstrap Widgets ================= +> Note: This chapter is under development. + Out of the box, Yii includes support for the [Bootstrap 3](http://getbootstrap.com/) markup and components framework (also known as "Twitter Bootstrap"). Bootstrap is an excellent, responsive framework that can greatly speed up the client-side of your development process. The core of Bootstrap is represented by two parts: diff --git a/docs/guide/caching-overview.md b/docs/guide/caching-overview.md index a28da1aa64f..5fcee7d51e8 100644 --- a/docs/guide/caching-overview.md +++ b/docs/guide/caching-overview.md @@ -1,6 +1,8 @@ Caching ======= +> Note: This chapter is under development. + Caching is a cheap and effective way to improve the performance of a web application. By storing relatively static data in cache and serving it from cache when requested, the application saves the time required to generate the data from scratch. Caching is one of the best ways to improve the performance of your application, almost mandatory on any large-scale site. diff --git a/docs/guide/db-active-record.md b/docs/guide/db-active-record.md index d56957d80c1..19f9d13b145 100644 --- a/docs/guide/db-active-record.md +++ b/docs/guide/db-active-record.md @@ -1,6 +1,8 @@ Active Record ============= +> Note: This chapter is under development. + [Active Record](http://en.wikipedia.org/wiki/Active_record_pattern) provides an object-oriented interface for accessing data stored in a database. An Active Record class is associated with a database table, an Active Record instance corresponds to a row of that table, and an attribute of an Active Record diff --git a/docs/guide/db-dao.md b/docs/guide/db-dao.md index 4ecb803bb99..b7f1940367c 100644 --- a/docs/guide/db-dao.md +++ b/docs/guide/db-dao.md @@ -1,6 +1,8 @@ Database basics =============== +> Note: This chapter is under development. + Yii has a database access layer built on top of PHP's [PDO](http://www.php.net/manual/en/book.pdo.php). It provides uniform API and solves some inconsistencies between different DBMS. By default Yii supports the following DBMS: diff --git a/docs/guide/db-migrations.md b/docs/guide/db-migrations.md index f2169cb08f4..78f4bed007c 100644 --- a/docs/guide/db-migrations.md +++ b/docs/guide/db-migrations.md @@ -1,6 +1,8 @@ Database Migration ================== +> Note: This chapter is under development. + Like source code, the structure of a database evolves as a database-driven application is developed and maintained. For example, during development, a new table may be added; Or, after the application goes live, it may be discovered that an additional index is required. It is important to keep track of these structural database changes (called **migration**), just as changes to the source code is tracked using version control. If the source code and the database become out of sync, bugs will occur, or the whole application might break. For this reason, Yii provides a database migration tool that can keep track of database migration history, apply new migrations, or revert existing ones. diff --git a/docs/guide/db-query-builder.md b/docs/guide/db-query-builder.md index 0fd9e5344fb..a73613af084 100644 --- a/docs/guide/db-query-builder.md +++ b/docs/guide/db-query-builder.md @@ -1,6 +1,8 @@ Query Builder and Query ======================= +> Note: This chapter is under development. + Yii provides a basic database access layer as described in the [Database basics](database-basics.md) section. The database access layer provides a low-level way to interact with the database. While useful in some situations, it can be tedious and error-prone to write raw SQLs. An alternative approach is to use the Query Builder. diff --git a/docs/guide/extend-creating-extensions.md b/docs/guide/extend-creating-extensions.md index f4fb5b814c7..cb5e6ab3d0a 100644 --- a/docs/guide/extend-creating-extensions.md +++ b/docs/guide/extend-creating-extensions.md @@ -1,5 +1,8 @@ Extending Yii ============= + +> Note: This chapter is under development. + The Yii framework was designed to be easily extendable. Additional features can be added to your project and then reused, either by yourself on other projects or by sharing your work as a formal Yii extension. Code style diff --git a/docs/guide/extend-customizing-core.md b/docs/guide/extend-customizing-core.md index e8c19e3f4f5..ef05c915af7 100644 --- a/docs/guide/extend-customizing-core.md +++ b/docs/guide/extend-customizing-core.md @@ -1,6 +1,8 @@ Helper Classes ============== +> Note: This chapter is under development. + Yii provides many classes that help simplify common coding tasks, such as string or array manipulations, HTML code generation, and so forth. These helper classes are organized under the `yii\helpers` namespace and are all static classes (meaning they contain only static properties and methods and should not be instantiated). diff --git a/docs/guide/extend-using-composer.md b/docs/guide/extend-using-composer.md index 3471be23ff6..2da5bf96624 100644 --- a/docs/guide/extend-using-composer.md +++ b/docs/guide/extend-using-composer.md @@ -1,6 +1,8 @@ Composer ======== +> Note: This chapter is under development. + Yii2 uses Composer as its dependency management tool. Composer is a PHP utility that can automatically handle the installation of needed libraries and extensions, thereby keeping those third-party resources up to date while absolving you of the need to manually manage the project's dependencies. diff --git a/docs/guide/extend-using-libs.md b/docs/guide/extend-using-libs.md index 33dcde3e631..805ff47a627 100644 --- a/docs/guide/extend-using-libs.md +++ b/docs/guide/extend-using-libs.md @@ -1,6 +1,8 @@ Using 3rd-Party Libraries ========================= +> Note: This chapter is under development. + Yii is carefully designed so that third-party libraries can be easily integrated to further extend Yii's functionalities. diff --git a/docs/guide/helper-overview.md b/docs/guide/helper-overview.md new file mode 100644 index 00000000000..78a6d97832b --- /dev/null +++ b/docs/guide/helper-overview.md @@ -0,0 +1,27 @@ +Helpers +======= + +> Note: This chapter is under development. + +Helper classes typically contain static methods only and are used as follows: + +```php +use \yii\helpers\Html; +echo Html::encode('Test > test'); +``` + +There are several classes provided by framework: + +- ArrayHelper +- Console +- FileHelper +- Html +- HtmlPurifier +- Image +- Inflector +- Json +- Markdown +- Security +- StringHelper +- Url +- VarDumper diff --git a/docs/guide/input-forms.md b/docs/guide/input-forms.md index 6a305889d26..682db72c8b2 100644 --- a/docs/guide/input-forms.md +++ b/docs/guide/input-forms.md @@ -1,6 +1,8 @@ Working with forms ================== +> Note: This chapter is under development. + The primary way of using forms in Yii is through [[yii\widgets\ActiveForm]]. This approach should be preferred when the form is based upon a model. Additionally, there are some useful methods in [[yii\helpers\Html]] that are typically used for adding buttons and help text to any form. diff --git a/docs/guide/input-validation.md b/docs/guide/input-validation.md index 87f6f8a678d..9e775c68325 100644 --- a/docs/guide/input-validation.md +++ b/docs/guide/input-validation.md @@ -1,6 +1,8 @@ Model validation reference ========================== +> Note: This chapter is under development. + As a model both represents data and defines the business rules to which that data must adhere, comprehending data validation is key to using Yii. In order to learn model validation basics, please refer to [Model, Validation subsection](model.md#Validation). This guide describes all of Yii's validators and their parameters. diff --git a/docs/guide/output-assets.md b/docs/guide/output-assets.md index cb7da7d0557..74ce909f7d1 100644 --- a/docs/guide/output-assets.md +++ b/docs/guide/output-assets.md @@ -1,6 +1,8 @@ Managing assets =============== +> Note: This chapter is under development. + An asset in Yii is a file that is included into the page. It could be CSS, JavaScript or any other file. The framework provides many ways to work with assets from basics such as adding `