Three related tables are (1) products, (2) offers, and (3) offer_rows.
-- SQL
create table products(
id serial not null auto_increment primary key,
...
);
create table offers(
id serial not null auto_increment primary key,
...
);
create table offer_rows(
id serial not null auto_increment primary key,
product_id bigint(20) unsigned references products(id),
offer_id bigint(20) unsigned not null references offers(id),
...
);
Offer rows have some extra data in addition of being the associative table between products and offers, and thus I had configured them previously as:
(class OffersTable)
@property \Cake\ORM\Association\HasMany $OfferRows
// initialize
$this->hasMany('OfferRows', [
'foreignKey' => 'offer_id'
]);
(class ProductsTable)
@property \Cake\ORM\Association\BelongsToMany $OfferRows
// initialize
$this->belongsToMany('OfferRows', [
'foreignKey' => 'product_id',
'joinType' => 'INNER',
]);
(class OfferRowsTable)
@property \Cake\ORM\Association\BelongsTo $Offers
@property \Cake\ORM\Association\HasOne $Products
// initialize
$this->belongsTo('Offers', [
'foreignKey' => 'offer_id',
'joinType' => 'INNER'
]);
$this->hasOne('Products', [
'className' => 'Products',
'propertyName' => 'reference_product_obj',
'foreignKey' => 'reference_product'
]);
Then I modified the association description to be:
(As to “why break working code”, this modification was due to an error when deleting entity, which reflected some error in association configuration and I figured out that it should be fixed and thus changed it accordingly.)
(class OffersTable)
@property \Cake\ORM\Association\BelongsToMany $Products
// initialize
$this->belongsToMany('Products', [
'through' => 'OfferRows',
'foreignKey' => 'offer_id',
'joinType' => 'INNER',
'joinTable' => 'offer_rows',
]);
(class ProductsTable)
@property \Cake\ORM\Association\BelongsToMany $Offers
// initialize
$this->belongsToMany('Offers', [
'through' => 'OfferRows',
'foreignKey' => 'product_id',
'joinType' => 'INNER',
'joinTable' => 'offer_rows',
]);
(class OfferRowsTable)
@property \Cake\ORM\Association\BelongsTo $Products
@property \Cake\ORM\Association\BelongsTo $Offers
// initialize
$this->belongsTo('Products', [
'foreignKey' => 'product_id'
]);
$this->belongsTo('Offers', [
'foreignKey' => 'offer_id',
'joinType' => 'INNER'
]);
Used versions are:
aura/installer-default 1.0.0 Installs Aura packages using the Composer defaults.
aura/intl 1.1.1 The Aura.Intl package provides internationalization (I18N) tools, specifically
cakephp/bake 1.2.14 Bake plugin for CakePHP 3.0
cakephp/cakephp 3.3.16 The CakePHP framework
cakephp/chronos 1.1.2 A simple API extension for DateTime.
cakephp/debug_kit 3.9.5 CakePHP Debug Kit
cakephp/migrations 1.6.7 Database Migration plugin for CakePHP 3.0 based on Phinx
cakephp/plugin-installer 1.0.0 A composer installer for CakePHP 3.0+ plugins.
composer/ca-bundle 1.0.7 Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.
composer/composer 1.4.2 Composer helps you declare, manage and install dependencies of PHP projects, ensuring you have the right stack everywhere.
composer/semver 1.4.2 Semver library that offers utilities, version constraint parsing and validation.
composer/spdx-licenses 1.1.6 SPDX licenses list and validation library.
dnoegel/php-xdg-base-dir 0.1 implementation of xdg base directory specification for php
friendsofcake/cakepdf 3.2.3 CakePHP plugin for creating and/or rendering Pdfs, several Pdf engines supported.
jakub-onderka/php-console-color 0.1
jakub-onderka/php-console-highlighter v0.3.2
jdorn/sql-formatter v1.2.17 a PHP SQL highlighting library
justinrainbow/json-schema 5.2.1 A library to validate a json schema.
mobiledetect/mobiledetectlib 2.8.25 Mobile_Detect is a lightweight PHP class for detecting mobile devices. It uses the User-Agent string combined with specific HTTP headers to detect the mo...
nikic/php-parser v3.0.6 A PHP parser written in PHP
psr/http-message 1.0.1 Common interface for HTTP messages
psr/log 1.0.2 Common interface for logging libraries
psy/psysh v0.8.8 An interactive shell for modern PHP.
ralouphie/mimey 1.0.8 PHP package for converting file extensions to MIME types and vice versa.
riesenia/cakephp-duplicatable v3.0.5 CakePHP ORM plugin for duplicating entities (including related entities)
robmorgan/phinx v0.6.5 Phinx makes it ridiculously easy to manage the database migrations for your PHP app.
seld/cli-prompt 1.0.3 Allows you to prompt for user input on the command line, and optionally hide the characters they type
seld/jsonlint 1.6.1 JSON Linter
seld/phar-utils 1.0.1 PHAR file format utilities, for when PHP phars you up
symfony/config v3.3.2 Symfony Config Component
symfony/console v3.3.2 Symfony Console Component
symfony/debug v3.3.2 Symfony Debug Component
symfony/filesystem v3.3.2 Symfony Filesystem Component
symfony/finder v3.3.2 Symfony Finder Component
symfony/polyfill-mbstring v1.4.0 Symfony polyfill for the Mbstring extension
symfony/process v3.3.2 Symfony Process Component
symfony/var-dumper v3.3.2 Symfony mechanism for exploring and dumping PHP variables
symfony/yaml v3.3.2 Symfony Yaml Component
zendframework/zend-diactoros 1.4.0 PSR HTTP Message implementations
How should I now access the relation data? Previously I just “linked” the offer_rows to offer (with the "contain" => ["OfferRows"]
), and the offer had all the rows in “offer_rows”. Now one offer_row is accessible only through corresponding item in products-array (product."_joinData")).
// PREVIOUSLY retrieving the offer (in the Controller) was as simple as:
$offer = $this->Offers->get($id, [
'contain' => ['OfferRows']
]);
// result was something like: offer => offer_rows [ 1 => row 1, 2 => row 2, ..]
NOW I must execute the following hand made function (from OffersTable) to make the same:
$offer = $this->get($id, [
'contain' => ['Products'] // NB: this must be declared, or the below "this->OfferRows->find" fails!
]);
$offerRows = $this->OfferRows->find('all')->where(['offer_id' => $id])->toArray();
$offer->offer_rows = $offerRows;
return $offer;
I have tried to follow the instructions carefully from cakephp documentation, but because previously the offer rows data access was easy and now I must do some extra function calls to make the same I am suspecting I try to access/use the associative data in the wrong way.
(Furthermore, I am facing some problems with duplicatable plugin and have raised a question for possible issue there: https://github.com/riesenia/cakephp-duplicatable/issues/23).