CakePHP3.1

# レスポンスコード304を返す

```php:SomeController.php
public function someControllerMethod()
{
    $this->response->statusCode(304);
    return $this->response;
}
```
# input radioのレンダリングをcakephp1系風にする

```php:SomeTemplate.ctp
echo $this->Form->input(
    'field_name',
    [
        'type' => 'radio',
        'options' => $list_items_array,
        'label' => false,
        'hiddenField' => false,
        'templates' => [
            'nestingLabel' => '{{hidden}}{{input}}<label{{attrs}}>{{text}}</label>',
            //'radioWrapper' => '{{label}}<br>'
        ]
    ]
);
```
# update

```php:SomeTemplate.ctp
$this->Posts->patchEntity($post, $this->request->data());
```

# トランザクション
https://qiita.com/SRsawaguchi/items/89394b907b1eac4fe101
https://qiita.com/matsuyoro/items/99670b546f5f5cbd914d

# ヘルパーをコントローラで使う

```php:SomeController.php
use App\View\Helper\MyFormHelper;

class SomeController extends AppController {
    public function someAction() {
        $this->MyForm = new MyFormHelper(new \Cake\View\View());
        echo $this->MyForm->my_form_method();
    }
}
```
# セッション

本体ソースの320行目あたり
ヘッダが送出済みだとsession_start()が呼ばれないので、
debug文字列やnotice、warningが出てる作りかけのページにredirectしてセッションチェックしても無駄。

```php:Session.php
if (ini_get('session.use_cookies') && headers_sent($file, $line)) {
    return;
}

if (!session_start()) {
    throw new RuntimeException('Could not start the session');
}
```
#ページネーション
https://qiita.com/satthi/items/af24c10d083e21f49906

# Request パラメータ

### cakephp1.2

```php:*.php

Array // $this->params
(
    [pass] => Array
        (
            [0] => <pass> /* /controller/action/<pass> */
        )

    [named] => Array
        (
            [<name>] => <value> /* /controller/action/<name>:<value> */
        )

    [controller] => controller
    [action] => action
    [plugin] => 
    [form] => Array
        (
        )

    [url] => Array
        (
            [<name>] => <value> /* /controller/action?<name>=<value> */
            [url] => posts/index/<pass>/<name>:<value>/
        )

)	
```

### cakephp3.1

```php:*.php
Object // $this->request
(
    [params] => Array
        (
            [plugin] => 
            [controller] => Controller
            [action] => action
            [_ext] => 
            [pass] => Array
                (
                    [0] => <pass> /* /controller/action/<pass> */
                )
            [named] => Array
                (
                    [<name>] => <value> /* /controller/action/<name>:<value> */
                     /* [required] Router::parseNamedParams($this->request); */
                )
        )

    [data] => Array
        (
        )

    [query] => Array
        (
            [<name>] => <value> /* /controller/action?<name>=<value> */
        )

    [url] => posts/index/<pass>/<name>:<value>/
    [base] => /index.php
    [webroot] => /
    [here] => /index.php/posts/index/<pass>/<name>:<value>/
    [trustProxy] => 
)
```
# バリデーション
既存の自前バリデーションコードを生かす
http://hard-boiled.me/archive/1017

# 例外
http://absg.hatenablog.com/entry/2016/05/03/195237

# カスタム例外
本番環境（Debug false）だと、あらゆる例外が400と500に集約されてメッセージもテンプレートも自由が効かないので。

```php:config/app.php
    'Error' => [
        'errorLevel' => E_ALL & ~E_DEPRECATED,
        //'exceptionRenderer' => 'Cake\Error\ExceptionRenderer',
        'exceptionRenderer' => 'App\Error\AppExceptionRenderer',
        'skipLog' => [],
        'log' => true,
        'trace' => true,
    ],
```
```php:Error/MyAppException.php
namespace App\Error;

use Cake\Core\Exception\Exception;

class MyAppException extends Exception
{
    public function __construct($type, $message = null)
    {
        $this->_attributes = ['type' => $type];
        $code = $type == 'xxx'? 404 : 500;

        parent::__construct($message, $code);
    }
}
```
```php:Error/AppExceptionRenderer.php
namespace App\Error;

use Exception;
//use Cake\Error\Debugger;
use Cake\Error\ExceptionRenderer;

class AppExceptionRenderer extends ExceptionRenderer
{
    public function render()
    {
        $exception = $this->error;

        if ($exception instanceof MyAppException)
        {
            $message = $exception->getMessage();
            $code = $exception->getCode();

            $viewVars = [
                'message' => $message,
                'code' => $code,
            ];
            $this->controller->set($viewVars);

            //セッションにもアクセスできるし
            $session = $this->controller->request->session();

            //独自の例外クラスから受け取った値を利用したり
            $type = $exception->getAttributes()['type'];
            $template = $type . '_error';

            //ビューにも渡せる
            $this->controller->set('type', $type);

            //jsonを返す場合（未検証）
            if($this->controller->request->is('ajax'))
            {
                $json = json_encode(<array>);

                $this->controller->response->type('json');
                return $this->controller->response->body($json);
            }
            return $this->_outputMessage($template);
        }
        return parent::render();
    }
}
```

# Formの日付をとりあえずオブジェクトに
```php:SomeController.php
use Cake\I18n\Time;

class SomeController extends AppController {
    public function someAction() {
        if($this->request->data) {
            $date = $this->request->data['datetime'];

            if(count(array_filter($date)) == 5) {
                $datetime = Time::create(
                    $date['year'],
                    $date['month'],
                    $date['day'],
                    $date['hour'],
                    $date['minute']
                );
            }else {
                $datetime = null;
            }
        }
    }
}
```