質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.34%

CakePHP3でbelongsToManyの実装について

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,331

score 12

CakePHP3.6でbelongsToManyの実装を行っています。
端的にいうと更新(insert, update)されなくて困っております。

またこれに関しては下記のチュートリアルを元に行っております。
https://book.cakephp.org/3.0/ja/tutorials-and-examples/cms/tags-and-users.html

以下の設定などに抜けなどがあれば教えてくださいませ

DBの構造

## 製品テーブル
CREATE TABLE `products` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
)
## 情報タグテーブル
CREATE TABLE `tags` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
)
## joinテーブル
CREATE TABLE `products_tags` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `product_id` int(11) NOT NULL,
    `tag_id` int(11) NOT NULL,
    PRIMARY KEY (`id`)
)

modelの設定

ProductsTable.php(Table)

    $this->belongsToMany('Tags', [
        'foreignKey' => 'product_id',
        'targetForeignKey' => 'tag_id',
        'joinTable' => 'products_tags'
    ]);

TagsTable.php(Table)

    $this->belongsToMany('Products', [
        'foreignKey' => 'tag_id',
        'targetForeignKey' => 'product_id',
        'joinTable' => 'products_tags'
    ]);

Product.php(Entity)

    protected $_accessible = [
        'name' => true,
        'tags' => true
    ];

Tag.php(Entity)

    protected $_accessible = [
        'name' => true,
        'products' => true
    ];

該当部分の更新部分のソースコード

ProductsController.php

    public function edit($id = null)
    {

        $product = $this->Products->get($id, ['contain' => ['Tags']]);
        if ($this->request->is(['patch', 'post', 'put'])) {
            $product = $this->Products->patchEntity($product, $this->request->getData());
            if ($this->Products->save($product)) {
                $this->Flash->success(__('更新しました'));
                return $this->redirect(['action' => 'view', $product->id]);
            }
            $this->Flash->error(__('更新失敗'));
        }
        $tags = $this->Products->Tags->find('list');
        $this->set(compact('product', 'tags'));
    }

edit.ctp

<?=  $this->Form->control('tag._ids', ['options'=>$tags, 'multiple' => true]); ?>

試したこと

save時、patchEntity時に下記の項目の追加をしてみましたが

$this->Products->patchEntity($product, $this->request->getData(), ['associated'=>['Tags']])
$this->Products->save($product, ['associated'=>['Tags']])
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • gano

    2018/12/12 10:34

    こんにちは。 「端的にいうと更新(insert, update)されなくて」とありますが、どのような形で不具合が起きておりますでしょうか? 同じコードを書いてみたところ、選択したタグが該当のProductに紐付いているようでした。

    キャンセル

  • hsymdhsymd

    2018/12/12 10:46

    gano様 この実装に関しての認識がズレがないとしたらProductにTagが紐付けを行う際にjoinテーブルにその紐付けのレコードが作成されるもしくは更新されると思っていたので今回の質問に至ったわけです

    キャンセル

  • gano

    2018/12/12 10:53

    joinテーブルにも正しく紐付け用のレコードが追加されました。少し変えた部分がありましたので、その点コメントいたしますね。

    キャンセル

  • hsymdhsymd

    2018/12/12 11:10

    Entityに関してはgano様にご指摘いただいた部分はProductsとTagsを間違えて記載しておりました。

    キャンセル

回答 2

+1

$_accessible の記載方法を間違えていたようでした。
modelを順序通りbakeしていれば特段気にすることはないのかもしれませんが
Entityの$_accessibleの記述方法はbelongsToManyの場合もmodelの記載は複数形を使うようです。
※その他のアソシーエーションについては確認していません

protected $_accessible = [
        'name' => true,
        'tags' => true // 対象のmodelは複数形のようです
        'tag' => true // こちらはだめでした。
    ];

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

以下に変更した状態ではいかがでしょうか?
それぞれ配列の2要素目のkeyが変わっております。

Product.php(Entity)

    protected $_accessible = [
        'name' => true,
        'tags' => true
    ];

Tag.php(Entity)

    protected $_accessible = [
        'name' => true,
        'products' => true
    ];

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/12 11:07

    gano様 こちら間違えて記載していました。本文を直します。

    キャンセル

  • 2018/12/12 11:33 編集

    hsymdhsymd 様

    私の環境では特に問題ありませんでした。試したことは以下の通りです(普通の設定です)
    1. cakephp3 をcomposer でinstall
    2. composer update
    3. app.phpの設定(データベース接続)
    4. bin/cake bake all products 並びに tags
    5. 上記質問文のコードをコピペ(試したことはやっておりません)

    これでできてしまったので、何か他の要因で悪さをしているように思います。
    データベース接続は問題ないのですよね、、、他の要因考えてみます、、、

    キャンセル

  • 2018/12/13 09:55

    gano様

    確認いただきありがとうございます。
    ほぼチュートリアル通りの実装ですので環境依存の部分がありそうですね、とりあえずは環境面の確認を行ってみます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る