本投稿は、こちらの記事の復習といいますか、応用編です:
http://qiita.com/uedatakeshi/items/fd3de8e2b770798aacfc
(@uedatakeshi様、ありがとうございます)
仮に、postsというテーブルとpost_imagesというテーブルがあるとします。
postsにはブログの記事を、post_imagesには記事に関連する画像を格納するとします。
postgresで恐縮ですが、テーブルはこんな感じです:
\d posts
テーブル "public.posts"
列 | 型 | 修飾語
-------------+------------------------+----------------------------------------------------
id | integer | not null default nextval('posts_id_seq'::regclass)
title | character varying(255) | not null default 'title'::character varying
description | text | not null default 'no description'::text
\d post_images
テーブル "public.post_images"
列 | 型 | 修飾語
----------+------------------------+----------------------------------------------------------
id | integer | not null default nextval('post_images_id_seq'::regclass)
filename | character varying(255) | not null default 'name'::character varying
post_id | integer | not null
これをbakeします。Modelはこちらのように生成されます:
Model/Table/PostsTable.php
class PostsTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('posts');
$this->setDisplayField('title');
$this->setPrimaryKey('id');
$this->hasMany('PostImages', [
'foreignKey' => 'post_id'
]);
}
Model/Table/PostImagesTable.php
class PostImagesTable extends Table
{
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('post_images');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->belongsTo('Posts', [
'foreignKey' => 'post_id',
'joinType' => 'INNER'
]);
}
さて、ユーザがpostsをaddした際に画像をアップロードし、その画像のファイル名をpost_images.filenameに格納したいとします。
コントローラでは次のように書きます:
PostsController.php
public function add()
{
$post = $this->Posts->newEntity();
if ($this->request->is('post')) {
//$post = $this->Posts->patchEntity($post, $this->request->getData()); この行はbakeすると自動的にできる
$post = $this->Posts->patchEntity($post, $this->request->getData(), ['associated' => ['PostImages']]); // associatedの記述がキモ
//アップロードデータ
$tmp = $this->request->data['image']['tmp_name'];
//ファイル名
$filename = $this->request->data['post_images'][0]['filename'];
//エラー処理等、かなり端折ってますがファイルシステムの希望の場所に移動
if( is_uploaded_file($tmp) ) {
$dir = "/var/www/html/app/webroot/images";
move_uploaded_file($tmp, $dir . DS . $filename);
}
if ($this->Posts->save($post)) {
$this->Flash->success(__('The post has been saved.'));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The post could not be saved. Please, try again.'));
}
$this->set(compact('post'));
$this->set('_serialize', ['post']);
}
そしてビューでは次のように書きます:
Posts/add.ctp
<div class="posts form large-9 medium-8 columns content">
<?= $this->Form->create($post, ['type' => 'file']) ?>
<fieldset>
<legend><?= __('Add Post') ?></legend>
<?php
echo $this->Form->control('title');
echo $this->Form->control('description');
echo $this->Form->input('post_images.0.filename', ['label' => 'filename']);
echo $this->Form->file('image');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>