Skip to content

Instantly share code, notes, and snippets.

@kanonji
Last active May 1, 2017 05:10
Show Gist options
  • Save kanonji/4223398 to your computer and use it in GitHub Desktop.
Save kanonji/4223398 to your computer and use it in GitHub Desktop.
My tiny doc for CakePHP2CakePHP

Model

find()

Result data format

find('first')
array(
    [ModelName] => array(
        [id] => 83
        [field] => value
    )
    [hasOneModel] => array(
        [id] => 33
        [field] => value
    )
    [hasManyModel] => array(
        [0] => array(
            [id] => 6
            [field] => value
        )
        [2] => array(
            [id] => 13
            [field] => value
        )
    )
)
find('all')
array(
    [0] => array(
        [ModelName] => array(
            [id] => 83
            [field] => value
        )
        [hasOneModel] => array(
            [id] => 33
            [field] => value
        )
        [hasManyModel] => array(
            [0] => array(
                [id] => 6
                [field] => value
            )
            [2] => array(
                [id] => 13
                [field] => value
            )
        )
    [1] => array(
        [ModelName] => array(
            [id] => 83
            [field] => value
[snip]
    )
)
no record from find('first'), find('all')
array()

find('first') had returned false before cakephp/cakephp#917 marged.

find() insted of paginate()

$option = array();
$this->paginate = $option;
$this->paginate();
$option = array();
$this->Foo->find('all', $option));

save(), saveAll(), saveMany(), saveAssociated()

saveAll()

If branches for saveMany() or saveAssociated()

saveAssociated()

UPDATE
array(
  'Foo' => array(
    'id' => 1,
  ),
  'Bar' => array(
    'id' => 1,
    'foo_id' => 1,
  ),
);

Even Foo hasOne Bar, Bar.id is needed to update with saveAssociated().

saveMany()

<?php
$data = array(
    array('title' => 'title 1'),
    array('title' => 'title 2'),
);
$this->Modal->save($data);
$data = array(
    array('Article' => array('title' => 'title 1')),
    array('Article' => array('title' => 'title 2')),
);
$this->Modal->save($data);
<?php
$data = array(
    array('Article' => array('title' => 'New article')), // This creates a new row
    array('Article' => array('id' => 2, 'title' => 'title 2')), // This updates an existing row
);
$this->Modal->save($data);

conditions

BETWEEN

'conditions' => [
    'Model.col_1 BETWEEN ? AND ?' => [2, 15],
]

Behavior

Association

http://www.cybergod.net/documents/relations.png

hasMany

hasOne

belongsTo

HABTM

HasMany through

Join

http://tipshare.info/view/50a47f6e4b2122a240000001

Datasource

$this->Model->getDataSource()->getLog(false, false);

Validation

Default setting

public $validate = array(
  'blog' => array(
    'url' => array(             // This key name is default value for 'message'
      'rule' => array('url'),
      //'message' => 'Your custom message here',
      //'allowEmpty' => false,
      //'required' => false,
      //'last' => false, // Stop validation after this rule
      //'on' => 'create', // Limit validation to 'create' or 'update' operations
    ),                         
  ),
);

allowEmpty, required, notEmpty

http://blog.ksweb-design.com/cakephp/308.html

   
required = false GET/POSTにblogが無ければバリデートしない。
allowEmpty = false blogの値が未入力(空文字列 '')ならバリデートエラー。GET/POSTにblogが無い場合はそもそも検証しない。
required = false, allowEmpty = true keyが無くても、keyがあって未入力でも通す。

whitelist

Custom validation rules

/**
 * $id is array('key' => 'value')
 */
public function newRule($id){
    $user_id = AuthComponent::user('id');
    $id = array_pop($id);
    return ($id === $user_id);
}

method name newRule is your validation rule name. Use it like 'rule' => array('newRule'),.

Controller

http://tipshare.info/view/50aa0f2a4b2122e042000000

Component

AuthComponent

App::uses('AuthComponent', 'Controller/Component');

class Foo extends AppModel{
  public function isValidId($value){
    $user_id = AuthComponent::user('id');
    return ($value === $user_id);
  }
}

AuthComponent::user() is static method. Able to call in a model or anywhare.

CakeRequest

CakeResponse

View

Helper

HtmlHelper

FormHelper

Single checkbox
$this->Form->input('foo', array('type'=>'checkbox'));
<div class="input checkbox">
  <input type="hidden" name="data[Model][foo]" id="ModelFoo_" value="0">
  <input type="checkbox" name="data[Model][foo]" value="1" id="ModelFoo">
  <label for="ModelFoo">Foo</label>
</div>
Multiple checkbox
$this->Form->input('foo', array('type'=>'select', 'multiple'=>'checkbox', 'options' => array(1=>'foo', 2=>'bar', 3=>'baz')));
//TODO
POST array
Type 1
<?php echo $this->Form->input('foo.0', array('type' => 'text')); ?>
<input type="text" name="data[Model][foo][0]" />
Type 2
<?php echo $this->Form->input('foo', array('type' => 'text', 'name'=>'data[Model][foo][]')); ?>
<input type="text" name="data[Model][foo][]" />
Type 3
<?php echo $this->Form->input('Model.0.field'); ?>
<?php echo $this->Form->input('Model.1.field'); ?>
<input type="text" id="Model0Field" name="data[Model][0][field]">
<input type="text" id="Model1Field" name="data[Model][1][field]">
input('foo_id')
$this->Form->input('foo_id'); // <select></select>
$this->Form->input('foo_id', array('type' => 'text')); // <input type="text">

Either assosiated Model is there or not.

Options

create()
array(
  'novalidate' => false, # true = prevent HTML5 required attribute. Since 2.3.x.
);
input()
array(
  'formnovalidate' => false, # true = prevent HTML5 required attribute. Since 2.3.x.
);

View Block

http://tipshare.info/view/4f5976717f8b9aaa3f000001

$this->View->assign(); //$this->View = null. コントローラーでは、アクション内・beforeRender()内でもViewはまだnullなので、コントローラーからViewを介してassign()は出来ないみたい。

View Block + HtmlHelper(従来の$scripts_for_layout)

$this->Html->script('foo', array('block' => 'script-head'));
$this->Html->css('foo', null, array('inline' => false));
<?php $this->fetch('meta');
$this->fetch('css');
$this->fetch('script-head'); ?>
</head>

//TODO: generated html

$this->Html->script('foo', array('inline' => false));
<?php $this->fetch('script'); ?>
</body>

//TODO: generated html

Tips

toggling badge, icon, any other images by Model data.

<?php if (`html` === Hash::get($badge, 'Badge.type')): ?>
<img src="path/to/html.gif">
<?php endif;?>

cake Console

cake bake

$ cake bake all Foo

Baking Model, View, Controller, Test, Fixture of foos table.

  • $validate stab will be generated for Model.
  • only normal CRUD .ctp files will be generated.
  • can not indicate prefix routing for Controller. Normal CRUD method only.
$ cake bake controller Foo --admin
You have more than one routing prefix configured
1. op
2. dev

generating Controller has prefixed methods only. There are no normal CRUD method.

cake schema

custom sub command

App::uses('AppShell', 'Console/Command');

class FooShell extends AppShell{
  public $tasks = array('Bar', 'Baz');
  public function startup(){
    parent::startup();
  }
}

cake foo is available if you put file like above to app/Console/Command/FooShell.php.

Debug

global function debug() Debugger::dump()

http://tipshare.info/view/50a0fa0c4b2122a240000000

CLI, JSON API

'debug($data, false)'

https://github.com/cakephp/cakephp/blob/2.2.3/lib/Cake/basics.php#L72

Debugger::outputAs('txt')

class AppController extends Controller {
  public function beforeFilter(){
    if('json' === Hash::get($this->request->params, 'prefix')){
      Debugger::outputAs('txt');
    }
  }
}

https://github.com/cakephp/cakephp/blob/2.2.3/lib/Cake/Utility/Debugger.php#L55

Log

http://tipshare.info/view/50a3c7884b21222964000000

App::uses()

App::uses('Foo', 'Lib');
App::uses('Foo', 'Plugin.Controller');
App::uses('Foo', 'Plugin.Controller/Component');
App::uses('Foo', 'Lib/Bar');

Hash

Retrieving

advanced : Hash::extract($data, 'Model.{n}.field')

Simple : Hash::get($data, 'Model.field')

Exists : Hash::check($data, 'Model.{n}.field') : the same path syntax as Hash::extract()

Remove : Hash::remove($data, 'Model.{n}.field') : {n}, {s} are avalable for the path

Cache

http://tipshare.info/view/50a0f3e94b21222d64000000 http://tipshare.info/view/509b57e84b2122bf78000000

http://1-byte.jp/2010/10/29/too_many_queries_on_cakephp/

CakeEvent

http://blog.candycane.jp/archives/1808

Configure

<?php
$config['bar'] = array(1, 2, 3);
$config['baz'] = array('baz1' => 1, 'baz2' => 1);
?>

app/Config/foo.php

Configure::load('foo');
$bar = Configure::read('bar');

Configure::load('foo') load app/Config/foo.php.

Router

Router::url(array('controller' => 'foo_bars')); // Best
Router::url(array('controller' => 'fooBars'));  // Bad (valid)
Router::url(array('controller' => 'FooBars'));  // Bad (valid)

Router::url() does not convert SnakeCaces to `snake_cases'.

Plugins

Setup

tips

http://tkyk.name/blog/2012/02/17/cakephp20-git-starter/ https://twitter.com/maeharin/statuses/186954986415071232 http://tipshare.info/view/4e8a77db4b21222b15000002 https://gist.github.com/72b1ee3be8311989774a

<?php
App::uses('ModelBehavior', 'Model');
class ExampleBehavior extends ModelBehavior{
/*
* @see doSomething()
*/
//public $mapMethods = array('/do(\w+)/' => 'doSomething');
public function setup(Model $Model, $settings = array()) {
if (!isset($this->settings[$Model->alias])) {
$this->settings[$Model->alias] = array(
//'option1' => 'default value',
//'option2' => 'default value',
//'option3' => 'default value',
);
}
$this->settings[$Model->alias] = array_merge($this->settings[$Model->alias], (array)$settings);
}
public function cleanup(Model $Model){
}
public function beforeValidate(Model $Model){
}
public function beforeFind(Model $Model, array $query){
}
public function afterFind(Model $Model, mixed $results, boolean $primary){
}
public function beforeSave(Model $Model){
}
public function afterSave(Model $Model, boolean $created){
}
public function beforeDelete(Model $Model, boolean $cascade = true){
}
public function afterDelete(Model $Model){
}
/*
* $Model->doReleaseTheHounds('homer', 'lenny');
* get 'ReleaseTheHounds', 'homer', 'lenny'
*
* @see $this->mapMethods
*/
//public function doSomething(Model $model, $method, $arg1, $arg2) {
// debug(func_get_args());
//}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment