Bonjour, je cherche a afficher une liste de produits associé à plusieurs catégories.
Actuellement :

CategoriesTable.php

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

ProdtuctsTable.php

    $this->belongsToMany('Categories', [
            'foreignKey' => 'product_id',
            'targetForeignKey' => 'category_id',
            'joinTable' => 'categories_products'
        ]);

Tables SQL
categories
categories_products
products

debug d'un produit

    (int) 0 => object(App\Model\Entity\Product) {

        'id' => (int) 15,
        'name' => 'Nom du Produit',
        'description' => 'Description du produit ',
        'price' => (float) 0,
        'ref' => '',
        'living_space' => null,
        'opening_space' => null,
        'nb_room' => null,
        'categories' => [
            (int) 0 => object(App\Model\Entity\Category) {

                'id' => (int) 30,
                'name' => 'catégorie 1',
                'description' => '',
                'order' => (int) 0,
                'parent_id' => null,
                'lft' => (int) 3,
                'rght' => (int) 4,
                '_joinData' => object(Cake\ORM\Entity) {

                    'category_id' => (int) 30,
                    'id' => (int) 43,
                    'product_id' => (int) 15,
                    '[new]' => false,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[repository]' => 'CategoriesProducts'

                },
                '[new]' => false,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [],
                '[original]' => [],
                '[virtual]' => [],
                '[errors]' => [],
                '[repository]' => 'Categories'

            },
            (int) 1 => object(App\Model\Entity\Category) {

                'id' => (int) 33,
                'name' => 'catégorie 2',
                'description' => '',
                'order' => (int) 1,
                'parent_id' => null,
                'lft' => (int) 7,
                'rght' => (int) 8,
                '_joinData' => object(Cake\ORM\Entity) {

                    'category_id' => (int) 33,
                    'id' => (int) 44,
                    'product_id' => (int) 15,
                    '[new]' => false,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[repository]' => 'CategoriesProducts'

                },
                '[new]' => false,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [],
                '[original]' => [],
                '[virtual]' => [],
                '[errors]' => [],
                '[repository]' => 'Categories'

            },
            (int) 2 => object(App\Model\Entity\Category) {

                'id' => (int) 37,
                'name' => 'catégorie 3',
                'description' => '',
                'order' => (int) 2,
                'parent_id' => null,
                'lft' => (int) 17,
                'rght' => (int) 18,
                '_joinData' => object(Cake\ORM\Entity) {

                    'category_id' => (int) 37,
                    'id' => (int) 45,
                    'product_id' => (int) 15,
                    '[new]' => false,
                    '[accessible]' => [
                        '*' => true
                    ],
                    '[dirty]' => [],
                    '[original]' => [],
                    '[virtual]' => [],
                    '[errors]' => [],
                    '[repository]' => 'CategoriesProducts'

                },
                '[new]' => false,
                '[accessible]' => [
                    '*' => true
                ],
                '[dirty]' => [],
                '[original]' => [],
                '[virtual]' => [],
                '[errors]' => [],
                '[repository]' => 'Categories'

            },
            [...]
        ],
        '[new]' => false,
        '[accessible]' => [
            '*' => true
        ],
        '[dirty]' => [],
        '[original]' => [],
        '[virtual]' => [],
        '[errors]' => [],
        '[repository]' => 'Products'

    },

(Le produit a bien N catégories)

Je ne sais pas comment effectuer une requête sur plusieurs categories_id

ex :

$products = $this->Products->find('all', [
                'contain' => [
                    'Categories' => [
                         'conditions' => [
                             'Categories.id' => $data[0]['category_id'].','.$data[1]['category_id'].','.$data[2]['category_id'].','.$data[3]['category_id'],
                         ]
                    ]
                ]
            ]);

Si vous avez une piste pour filter les produits avec en paramètre un nombre N de catégories je prend
Merci

10 réponses


Bed0sk!l
Auteur
Réponse acceptée

Salut, Xeta, merci pour ta réponse, cependant je n'arrive toujours pas a afficher uniquement les produits qui sont dans la sommes des 4 catégories , ma requête est probablement fausse :

    $category_ids = [
        $data[0]['category_id'],
        $data[1]['category_id'],
        $data[2]['category_id'],
        $data[3]['category_id']
    ];

    $products = $this->Products->find('all', [
        'contain' => [
            'Categories' => [
                'conditions' => [
                    'Categories.id IN' => $category_ids,
                ]
            ]
        ]
    ]);

As tu la possibilité de m'aiguiller pour faire proprement cette requête ?

Merci

Hello,
Il te faut une clause IN si tu veux le faire sur plusieurs catégories.
http://book.cakephp.org/3.0/en/orm/query-builder.html#automatically-creating-in-clauses

Tu es sûr que ceci $data[3]['category_id'] affiche bien l'id de la catégorie ? Car sa parait bizarre d'utiliser une typographie de type array alors que les résultats sont des entities.

Bed0sk!l
Auteur

Yep! :)

$data[3]['category_id'] c'est juste un tableau fait à la main pour les tests

    [...]
    FROM 
      `categories` `Categories` 
      INNER JOIN `categories_products` `CategoriesProducts` ON `Categories`.`id` = (
        `CategoriesProducts`.`category_id`
      ) 
    WHERE 
      (
        `Categories`.`id` in (29, 33, 35, 42) 
        AND `CategoriesProducts`.`product_id` in (
          '8', '9', '10', '11', '12', '13', '14', 
          '15', '16', '17', '18', '19', '20', 
          '21', '22', '23', '24', '25', '26', 
          '27', '28', '29'
        )
      )

Et ceci ?

$products = $this->Products
            ->find()
            ->contain([
                'Categories'
            ])
            ->where([
                'Categories.id IN' => $category_ids
            ]);
Bed0sk!l
Auteur

Nop!
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'Categories.id' in 'where clause'

Config:

Tables SQL
categories
categories_products
`products``

CategoriesTable.php

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

ProdtuctsTable.php

    $this->belongsToMany('Categories', [
            'foreignKey' => 'product_id',
            'targetForeignKey' => 'category_id',
            'joinTable' => 'categories_products'
        ]);

C'est ce qui me semble étonnant

Ah mais j'avais mal vue, il faut faire ta requête sur la table de jointure categories_products.
Quel est la structure de cette table ?

Bed0sk!l
Auteur

categories_products

CREATE TABLE `categories_products` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `category_id` int(11) DEFAULT NULL,
  `product_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

Par contre je n'ai pas créé de model pour cette table je dois en créer un ?

Non pas besoin en faite.

Test voir ceci :

$products = $this->Products->find();
$products->matching('Categories', function ($q) use ($category_ids) {
    return $q->where(['Categories.id IN' => $category_ids]);
});
Bed0sk!l
Auteur

Nop toujours pas ! Merci pour ton aide,
là pour le coups la requête m'affiche la totalité des produits..
Je sèche complètement