From 223e259ba7f018635d41529a4e046e53368f0532 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Wed, 3 Jul 2013 22:28:27 +0400 Subject: [PATCH 1/5] prioritized quoting using special syntax instead of doing it manually --- docs/guide/database-basics.md | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/guide/database-basics.md b/docs/guide/database-basics.md index 56dc61f..cfb33c4 100644 --- a/docs/guide/database-basics.md +++ b/docs/guide/database-basics.md @@ -133,17 +133,7 @@ $connection->createCommand()->delete('tbl_user', 'status = 0')->execute(); Quoting table and column names ------------------------------ -If you are building query string dynamically make sure you're properly quoting table and column names using -[[\yii\db\Connection::quoteTableName()]] and [[\yii\db\Connection::quoteColumnName()]]: - -```php -$column = $connection->quoteColumnName($column); -$table = $connection->quoteTableName($table); -$sql = "SELECT COUNT($column) FROM $table"; -$rowCount = $connection->createCommand($sql)->queryScalar(); -``` - -Alternatively you can use special syntax when writing SQL: +Most of the time you would use the following syntax for quoting table and column names: ```php $sql = "SELECT COUNT({{$column}}) FROM [[$table]]"; @@ -153,6 +143,15 @@ $rowCount = $connection->createCommand($sql)->queryScalar(); In the code above `{{X}}` will be converted to properly quoted column name while `[[Y]]` will be converted to properly quoted table name. +The alternative is to quote table and column names manually using [[\yii\db\Connection::quoteTableName()]] and +[[\yii\db\Connection::quoteColumnName()]]: + +```php +$column = $connection->quoteColumnName($column); +$table = $connection->quoteTableName($table); +$sql = "SELECT COUNT($column) FROM $table"; +$rowCount = $connection->createCommand($sql)->queryScalar(); +``` Prepared statements ------------------- From ab27d16efd065c14b7832172e635e1f08ea9d344 Mon Sep 17 00:00:00 2001 From: Sw3rtas Date: Wed, 3 Jul 2013 23:02:32 +0300 Subject: [PATCH 2/5] * Fixed Model::loadMultiple() when populating from formName() * Documentation corrections for data population and quoting names in SQL query --- docs/guide/database-basics.md | 4 ++-- docs/guide/upgrade-from-v1.md | 32 ++++++++++++++++++++------------ framework/yii/base/Model.php | 2 +- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/docs/guide/database-basics.md b/docs/guide/database-basics.md index cfb33c4..ade5968 100644 --- a/docs/guide/database-basics.md +++ b/docs/guide/database-basics.md @@ -136,11 +136,11 @@ Quoting table and column names Most of the time you would use the following syntax for quoting table and column names: ```php -$sql = "SELECT COUNT({{$column}}) FROM [[$table]]"; +$sql = "SELECT COUNT([[$column]]) FROM {{$table}}"; $rowCount = $connection->createCommand($sql)->queryScalar(); ``` -In the code above `{{X}}` will be converted to properly quoted column name while `[[Y]]` will be converted to properly +In the code above `[[X]]` will be converted to properly quoted column name while `{{Y}}` will be converted to properly quoted table name. The alternative is to quote table and column names manually using [[\yii\db\Connection::quoteTableName()]] and diff --git a/docs/guide/upgrade-from-v1.md b/docs/guide/upgrade-from-v1.md index 5f1cf72..c3cbf31 100644 --- a/docs/guide/upgrade-from-v1.md +++ b/docs/guide/upgrade-from-v1.md @@ -163,6 +163,26 @@ A model is now associated with a form name returned by its `formName()` method. mainly used when using HTML forms to collect user inputs for a model. Previously in 1.1, this is usually hardcoded as the class name of the model. +A new methods called `load()` and `Model::loadMultiple()` is introduced to simplify the data population from user inputs +to a model. For example, + +```php +$model = new Post; +if ($model->load($_POST)) {...} +// which is equivalent to: +if (isset($_POST['Post'])) { + $model->attributes = $_POST['Post']; +} + +$model->save(); + +$postTags = array(); +$tagsCount = count($_POST['PostTag']); +while($tagsCount-- > 0){ + $postTags[] = new PostTag(array('post_id' => $model->id)); +} +Model::loadMultiple($postTags, $_POST); +``` Yii 2.0 introduces a new method called `scenarios()` to declare which attributes require validation under which scenario. Child classes should overwrite `scenarios()` to return @@ -196,18 +216,6 @@ Controllers The `render()` and `renderPartial()` methods now return the rendering results instead of directly sending them out. You have to `echo` them explicitly, e.g., `echo $this->render(...);`. -A new method called `populate()` is introduced to simplify the data population from user inputs -to a model. For example, - -```php -$model = new Post; -if ($model->load($_POST)) {...} -// which is equivalent to: -if (isset($_POST['Post'])) { - $model->attributes = $_POST['Post']; -} -``` - Widgets ------- diff --git a/framework/yii/base/Model.php b/framework/yii/base/Model.php index 8b0d455..d2c8aa5 100644 --- a/framework/yii/base/Model.php +++ b/framework/yii/base/Model.php @@ -694,7 +694,7 @@ class Model extends Component implements \IteratorAggregate, \ArrayAccess $success = true; } } elseif (isset($data[$scope][$i])) { - $model->setAttributes($data[$scope[$i]]); + $model->setAttributes($data[$scope][$i]); $success = true; } } From a08d8a245b321fe077a62993326c3830ed6736f5 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 4 Jul 2013 02:00:12 +0400 Subject: [PATCH 3/5] started controller docs --- docs/guide/controller.md | 188 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/docs/guide/controller.md b/docs/guide/controller.md index e69de29..60ba680 100644 --- a/docs/guide/controller.md +++ b/docs/guide/controller.md @@ -0,0 +1,188 @@ +Controller +========== + +Controller is one of the key parts of the application. It determines how to handle incoming request and creates a response. + +Most often a controller takes HTTP request data and returns HTML, JSON or XML as a response. + +Basics +------ + +Controller resides in application's `controllers` directory is is named like `SiteController.php` where `Site` +part could be anything describing a set of actions it contains. + +The basic web controller is a class that extends [[\yii\web\Controller]] and could be very simple: + +```php +namespace app\controllers; + +use yii\web\Controller; + +class SiteController extends Controller +{ + public function actionIndex() + { + // will render view from "views/site/index.php" + return $this->render('index'); + } + + public function actionTest() + { + // will just print "test" to the browser + return 'test'; + } +} +``` + +As you can see, typical controller contains actions that are public class methods named as `actionSomething`. + +Routes +------ + +Each controller action has a corresponding internal route. In our example above `actionIndex` has `site/index` route +and `actionTest` has `site/test` route. In this route `site` is referred to as controller ID while `test` is referred to +as action ID. + +By default you can access specific controller and action using the `http://example.com/?r=controller/action` URL. This +behavior is fully customizable. For details refer to [URL Management](url.md). + +If controller is located inside a module its action internal route will be `module/controller/action`. + +In case module, controller or action specified isn't found Yii will return "not found" page and HTTP status code 404. + +### Defaults + +If user isn't specifying any route i.e. using URL like `http://example.com/`, Yii assumes that default route should be +used. It is determined by [[\yii\web\Application::defaultRoute]] method and is `site` by default meaning that `SiteController` +will be loaded. + +A controller has a default action. When the user request does not specify which action to execute by usign an URL such as +`http://example.com/?r=site`, the default action will be executed. By default, the default action is named as `index`. +It can be changed by setting the [[\yii\base\Controller::defaultAction]] property. + +Action parameters +----------------- + +It was already mentioned that a simple action is just a public method named as `actionSomething`. Now we'll review +ways that an action can get parameters from HTTP. + +### Action parameters + +You can define named arguments for an action and these will be automatically populated from corresponding values from +`$_GET`. This is very convenient both because of the short syntax and an ability to specify defaults: + +```php +namespace app\controllers; + +use yii\web\Controller; + +class BlogController extends Controller +{ + public function actionView($id, $version = null) + { + $post = Post::find($id); + $text = $post->text; + + if($version) { + $text = $post->getHistory($version); + } + + return $this->render('view', array( + 'post' => $post, + 'text' => $text, + )); + } +} +``` + +The action above can be accessed using either `http://example.com/?r=blog/view&id=42` or +`http://example.com/?r=blog/view&id=42&version=3`. In the first case `version` isn't specified and default parameter +value is used instead. + +### Getting data from request + +If your action is working with data from HTTP POST or has too many GET parameters you can rely on request object that +is accessible via `\Yii::$app->request`: + +```php +namespace app\controllers; + +use yii\web\Controller; +use yii\web\HttpException; + +class BlogController extends Controller +{ + public function actionUpdate($id) + { + $post = Post::find($id); + if(!$post) { + throw new HttpException(404); + } + + $data = \Yii::$app->request->getPost('Post'); + if($data) { + $post->populate($data); + if($post->save()) { + $this->redirect(array('view', 'id' => $post->id)); + } + } + + return $this->render('update', array( + 'post' => $post, + )); + } +} +``` + +Standalone actions +------------------ + +If action is generic enough it makes sense to implement it in a separate class to be able to reuse it. +Create `actions/Page.php` + +```php +namespace \app\actions; + +class Page extends \yii\base\Action +{ + public $view = 'index'; + + public function run() + { + $this->controller->render($view); + } +} +``` + +The following code is too simple to implement as a separate action but gives an idea of how it works. Action implemented +can be used in your controller as following: + +```php +public SiteController extends \yii\web\Controller +{ + public function actions() + { + return array( + 'about' => array( + 'class' => '@app/actions/Page', + 'view' => 'about', + ), + ), + ); + } +} +``` + +After doing so you can access your action as `http://example.com/?r=site/about`. + +Filters +------- + +Catching all incoming requests +------------------------------ + + +See also +-------- + +- [Console](console.md) \ No newline at end of file From 0aa71986a337ed9e616f58ec2ba3579d2186da73 Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 4 Jul 2013 02:05:28 +0400 Subject: [PATCH 4/5] moved autoloader notes to internals --- docs/autoloader.md | 19 ------------------- docs/internals/autoloader.md | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 docs/autoloader.md create mode 100644 docs/internals/autoloader.md diff --git a/docs/autoloader.md b/docs/autoloader.md deleted file mode 100644 index b7696d7..0000000 --- a/docs/autoloader.md +++ /dev/null @@ -1,19 +0,0 @@ -Yii2 class loader -================= - -Yii 2 class loader is PSR-0 compliant. That means it can handle most of the PHP -libraries and frameworks out there. - -In order to autoload a library you need to set a root alias for it. - -PEAR-style libraries --------------------- - -```php -\Yii::setAlias('@Twig', '@app/vendors/Twig'); -``` - -References ----------- - -- YiiBase::autoload \ No newline at end of file diff --git a/docs/internals/autoloader.md b/docs/internals/autoloader.md new file mode 100644 index 0000000..b7696d7 --- /dev/null +++ b/docs/internals/autoloader.md @@ -0,0 +1,19 @@ +Yii2 class loader +================= + +Yii 2 class loader is PSR-0 compliant. That means it can handle most of the PHP +libraries and frameworks out there. + +In order to autoload a library you need to set a root alias for it. + +PEAR-style libraries +-------------------- + +```php +\Yii::setAlias('@Twig', '@app/vendors/Twig'); +``` + +References +---------- + +- YiiBase::autoload \ No newline at end of file From 279b274e5ad87f686b0b705f091e0802eb924f0f Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Thu, 4 Jul 2013 03:22:47 +0400 Subject: [PATCH 5/5] fixed controller example --- docs/guide/controller.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/guide/controller.md b/docs/guide/controller.md index 60ba680..c550b42 100644 --- a/docs/guide/controller.md +++ b/docs/guide/controller.md @@ -119,9 +119,8 @@ class BlogController extends Controller throw new HttpException(404); } - $data = \Yii::$app->request->getPost('Post'); - if($data) { - $post->populate($data); + if(\Yii::$app->request->isPost)) { + $post->load($_POST); if($post->save()) { $this->redirect(array('view', 'id' => $post->id)); }