Skip to content

Instantly share code, notes, and snippets.

@yano3nora
Last active August 14, 2018 12:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yano3nora/d9ab300d9d00215a87d5c1f8bdfa4baf to your computer and use it in GitHub Desktop.
Save yano3nora/d9ab300d9d00215a87d5c1f8bdfa4baf to your computer and use it in GitHub Desktop.
[cakephp: View] View / Template class on CakePHP3. #php #cakephp

OVERVIEW

Load Helpers

// in AppView
public function initialize() {
  $this->loadHelper('Html');
  $this->loadHelper('Form');
  $this->loadHelper('Flash');
  $this->loadHelper('Paginator');
}

HtmlHelper

// link
$this->Html->link(__'リンク', [
  'action' => 'add',
  '?' => ['id' => $user->id],
]);

// disuse escape for fontawesome
$this->Html->link(
  "<i class='fa fa-edit'></i>",
  ['action' => 'edit', $user->id],
  ['escape' => false]
);

FormHelper - basic

$this->Form->input() について 3.4 から Form::input() から Form::control() に名称変更されてます。今のところどっちも同じ挙動ぽいけどさっさと変えたほうがいいのかしら。
また control() input() は常に <div> で WRAP され date()text() は WRAP されない。もっと細かいカスタマイズをする場合は ウィジェットテンプレート なるものをカスタマイズする必要がある。だるい。参考 - CakePHP3 のFormHelperが生成するHTMLをカスタマイズしたい

echo $this->Form->create($user /* ← ここに Entity オブジェクトぶちこむ、なければ null を */ ,[
  'type'=>'post',
  'url'=>['controller'=>'Users', 'action'=>'index'],
  'onsubmit' => 'return confirm(\'実行しますか?\');'
]);

echo $this->Form->hidden('id',['default'=>$id]);
echo $this->Form->input('name'); //スキーマからインプットタイプをよしなに
echo $this->Form->input('password',['label'=>'パスワード','type'='password');

// テンプレート編集しないでできるのはこんくらい
echo $this->Form->input('birthday', [
  'label'      => '誕生日',
  'type'       => 'date',
  'dateFormat' => 'YMD',
  'monthNames' => false,
  'maxYear'    => date('Y')+1,
  'minYear'    => date('Y')-100,
  'empty'      => ['year' => '年', 'month' => '月', 'day' => '日'],
  // 'default'    => date('Y-m-d'),
]);

// Date 日本対応
echo $this->Form->templates([
  'dateWidget' => '<ul class="list-inline"><li class="year">{{year}} 年</li><li class="month"> {{month}} 月 </li><li class="day"> {{day}} 日 </li><li class="hour"> {{hour}} 時 </li><li class="minute"> {{minute}} 分 </li></ul>'
]);

echo $this->Form->input('start_datetime', array(
  'type' => 'datetime',
  'label' => '開始日時',
  'dateFormat' => 'YMD',
  'monthNames' => false,
  'minYear' => date('Y'),
  'maxYear' => date('Y')+1,
  'default' => date('Y-m-d')
));

// その他
$this->Form->input('open', [
  'type'=>'time', //日付なし
  'format' => 24, //24h表記
  'interval'=>15 //15分刻み
]);

$this->Form->text('class',[
  'default'=>$default,
  'readonly'=>'readonly'  // text や textarea は readonly とかも可能
]);

select の option に背景色いれたいよ

<?php
/**
 * @see Using material design lite.
 */

// In Controller
$colors = [
	'red' => 'レッド',
    'blue' => 'ブルー',
];
$colorOptions = [];
foreach ($COLORS as $key => $value) {
  $colorOptions += [
    'text'  => $value,
    'value' => $key,
    'class' => 'mdl-color-text--white mdl-color--'.$key,
  ];
}
$this->set(compact('colorOptions'));

// In view.
<?php echo $this->Form->input('color', [
  'options' => $colorOptions ?? [],
  'empty'   => '選択してください',
]) ?>

FormHelper - association

FormHelper でうまいこと POST データ練り上げて newEntity() patchEntity() なりに $this->request->getData() を渡してあげると エンティティの関連データ (アソシエーション) を一括で save() できる のでとっても便利。

/**
 * Example Associations.
 *
 * - articles
 *     - belongsTo: authors
 *         - hasOne: profiles
 *     - hasMany: comments
 *     - belongsToMany: tags
 */
 
$this->Form->create($article);
 
// Article
echo $this->Form->hidden('id', ['value' => $article->id])
echo $this->Form->control('title');
 
// Article > Author (belongsTo)
echo $this->Form->control('author.id');
echo $this->Form->control('author.first_name');
echo $this->Form->control('author.last_name');
 
// Article > Author > Profile (belongsTo > hasOne)
echo $this->Form->control('author.profile.id');
echo $this->Form->control('author.profile.username');
 
// Article > Comments (hasMany)
echo $this->Form->control('comments.0.id');
echo $this->Form->control('comments.0.comment');
echo $this->Form->control('comments.1.id');
echo $this->Form->control('comments.1.comment');


// Article > Tags (belongsToMany) -- input-pattern
echo $this->Form->control('tags.0.id');
echo $this->Form->control('tags.0.name');
echo $this->Form->control('tags.1.id');
echo $this->Form->control('tags.1.name');
 
// Article > Tags (belongsToMany) -- select-pattern
echo $this->Form->control('tags._ids', [
    'type' => 'select',
    'multiple' => true,
    'options' => $tagList,
]);

// Article > ArticleTags (belongsToMany, ['joinTable' => 'articles_tags'])
echo $this->Form->control('tags.0._joinData.starred');
echo $this->Form->control('tags.1._joinData.starred');

FormHelper - postLink()

// in view
<?php echo $this->Form->postLink(
  '<i class="tiny material-icons md-18">delete</i> 削除',
  [
    'action' => 'delete',
    $event->id,
  ],
  [
    'confirm' => '削除しますか?',
    'method' => 'delete',
    'escape' => false,
    'class' => 'btn waves-effect waves-light red accent-4',
    'tabindex' => -1 // タブで選択しないようにするやつ
  ]
) ?>

// in controller
public function delete(int $id=null) {
  $this->request->allowMethod(['delete']);
  $event = $this->Events->get($id);
  if ($this->Events->delete($event)) {
    $this->Flash->success(MSG_DELETE_SUCCESS);
  } else {
    $this->Flash->error(MSG_DELETE_ERROR);
  }
  return $this->redirect(['action' => 'index']);
}

postLink() を Form 内にネストしたい

通常 Form タグネストはできないが Form ヘルパーで作った Form 内で postLink()['block' => true] で生成し Form の外で $this->fetch() でバッファリングする手段で実装できちゃう。ごいすー!

<?= $this->Form->create($hoge, ['type' => 'file']) ?>
<?= $this->Form->postLink(__('画像を削除'),
  ['controller' => 'Hoges', 'action' => 'deleteImage', $hoge->id],
  ['block' => true, 'confirm' => __('画像を削除しますか?')]
  )
?>
<?= $this->Form->button(__('保存')) ?>
<?= $this->Form->end() ?>
<?= $this->fetch('postLink') ?>

FormHelper - image/file

// In View.
echo $this->Form->create($Users, [
  'url'     => ['action' => 'confirm'],
  'type'    => 'post',
  'enctype' => 'multipart/form-data',  // 'type' => 'file' でもよいケドこっちのが安定している気がする...
]);
echo $this->Form->input('img_data',['type'=>'file']);
echo $this->Form->hidden('img_user',['value'=>$user['id']]);
echo $this->Form->button('登録', ['class' => 'c-btn']);
echo $this->Form->end();


// In Controller
try {
  $fileName = $this->request->data('file.name');
  $fileTmp  = $this->request->data('file.tmp_name');
  $fileSize = $this->request->data('file.size');
  $FileApi  = new File($fileTmp);
  $fileExt  = pathinfo($fileName, PATHINFO_EXTENSION);
  $filePath = $fileName.'.'.$fileExt;
  $fileDest = FILE_DEST.'/'.$filePath;
  // Verify it that allowed extension.
  if (!in_array($fileExt, ALLOW_EXTENSIONS)) throw new \Exception('Denied file extensions.');
  // Validation of file size.
  if ($fileSize > UPLOAD_FILE_SIZE_MAX) throw new \Exception('Denied over file size.');
  $FileApi->copy($fileDest);
  $FileApi->close();
  $this->Flash->success('Upload was success.');
} catch (\Exception $e) {
  if (!empty($FileApi)) $FileApi->close();
  $this->Flash->error($e->getMessage());
}
return $this->redirect($this->referer());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment