CakePHP 3.x: How do I use a non-conforming datasource?

Hi,

I built the basic version of my application, and now I need to integrate an additional datasource, but this one does not conform to CakePHP’s naming conventions, and I cannot alter the structure of it, since there is third-party Java code that relies on that structure. My thought here was to build a CakePHP plugin to use that datasource. Thankfully, their database has a nearly-compliant structure.

Specifically, the associative tables don’t conform. Here’s an example with placeholder names:

durps: id, name, value

blahs: id, name, value

durpsblahs: durps_id, blahs_id

users: id, name

usersdurps: users_id, durps_id

So, the users, durpsblahs, and usersdurps tables are the ones that are the issue here.

My issue with the users table is that I need to link my existing User entity and table models to the new one. With the associative tables, the names are not underscore separated, but, since the two columns in those tables have foreign key constraints, CakePHP only party treats those tables as associative. For example, I added one Durp, and one Blah, but the Add Durpsblahs page has no controls to either enter the values for durps_id and blahs_id or select them from dropdown menus. I can CRUD the base entities just fine.

My questions:

  • What parts of the generated code for Durpsblahs (entity and table models) do I need to modify?

  • How do I modify my original User entity and table models to link to the new FancyPlugin\User models?

For your question #1
You can change the table name in your /src/Model/Table/DurpsBlahsTable.php initialize() method by invoking $this->table('durpsblahs');

OK, cool. Thanks. :slight_smile:

Now, I await an answer to number 2. :smiley:

Here’s some more specifics on the mock database that mirrors the issues that I am seeing:

mysql> SHOW CREATE TABLE durps;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                    |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| durps | CREATE TABLE `durps` (
  `id` mediumint(9) NOT NULL DEFAULT '0',
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

mysql> SHOW CREATE TABLE blahs;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                    |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
| blahs | CREATE TABLE `blahs` (
  `id` mediumint(9) NOT NULL DEFAULT '0',
  `name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE durpsblahs;
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table      | Create Table                                                                                                                                                                                                                                                                                                                                                                                                               |
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| durpsblahs | CREATE TABLE `durpsblahs` (
  `durps_id` mediumint(9) NOT NULL DEFAULT '0',
  `blahs_id` mediumint(9) NOT NULL DEFAULT '0',
  PRIMARY KEY (`durps_id`,`blahs_id`),
  KEY `durpsblahs_ibfk_2` (`blahs_id`),
  CONSTRAINT `durpsblahs_ibfk_1` FOREIGN KEY (`durps_id`) REFERENCES `durps` (`id`),
  CONSTRAINT `durpsblahs_ibfk_2` FOREIGN KEY (`blahs_id`) REFERENCES `blahs` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

Also, here’s the code for DurpsblahsTable.php:

  1 <?php`
  2 namespace DBAuth2\Model\Table;
  3 
  4 use Cake\ORM\Query;
  5 use Cake\ORM\RulesChecker;
  6 use Cake\ORM\Table;
  7 use Cake\Validation\Validator;
  8 use DBAuth2\Model\Entity\Durpsblah;
  9 
 10 /**
 11  * Durpsblahs Model
 12  *
 13  * @property \Cake\ORM\Association\BelongsTo $Durps
 14  * @property \Cake\ORM\Association\BelongsTo $Blahs
 15  */
 16 class DurpsblahsTable extends Table
 17 {
 18 
 19     /**
 20      * Initialize method
 21      *
 22      * @param array $config The configuration for the Table.
 23      * @return void
 24      */
 25     public function initialize(array $config)
 26     {
 27         parent::initialize($config);
 28 
 29         $this->table('durpsblahs');
 30         $this->displayField('durps_id');
 31         $this->primaryKey(['durps_id', 'blahs_id']);
 32 
 33         $this->belongsTo('Durps', [
 34             'foreignKey' => 'durps_id',
 35             'joinType' => 'INNER',
 36             'className' => 'DBAuth2.Durps'
 37         ]);
 38         $this->belongsTo('Blahs', [
 39             'foreignKey' => 'blahs_id',
 40             'joinType' => 'INNER',
 41             'className' => 'DBAuth2.Blahs'
 42         ]);
 43     }
 44 
 45     /**
 46      * Returns a rules checker object that will be used for validating
 47      * application integrity.
 48      *
 49      * @param \Cake\ORM\RulesChecker $rules The rules object to be modified.
 50      * @return \Cake\ORM\RulesChecker
 51      */
 52     public function buildRules(RulesChecker $rules)
 53     {
 54         $rules->add($rules->existsIn(['durps_id'], 'Durps'));
 55         $rules->add($rules->existsIn(['blahs_id'], 'Blahs'));
 56         return $rules;
 57     }
 58 
 59     /**
 60      * Returns the database connection name to use by default.
 61      *
 62      * @return string
 63      */
 64     public static function defaultConnectionName()
 65     {
 66         return 'dbauth_module';
 67     }
 68 }`

I see that the table model is using the composite key, so, that’s good. It looks like it should just work from there, but, as the generated code shows on line 29 above, it’s already using the correct table.

Ideas?

Hmm, this may be as simple as answering the following question:

What is the convention used for an entity URL when a composite key is used?

I meant compound key.

CakePHP doesn’t really provide a convention for this. You could do something like /durpsblahs/1/2 though.

As an aside you should consider updating your schema to have less horrible table names :smile:

Regarding question #2 it is not clear for me what do you want to achieve. Do you have two users table? Why do you need a plugin?

Yes, there are two “users” tables: one in my base application, and the 3rd party Java module has its own database, which includes a “users” table.

That module does not perform user management, so I want to be able to perform that within my application. Since I cannot modify their database without “breaking” the module, I need a way to link the two User models together.

Using a plugin, so I don’t have to do some silly renaming of the secondary user model E V E R Y W H E R E. I thought that it would be much easier to simply refer to the plugin user model like this: DBAuth2\User

Please, correct me if am mistaken in this assumption.

Thanks.

@markstory, I tried your suggestion. I created a row in “durps”, one in “blahs”, and one in the associative table, “durpsblahs”.

mysql> SELECT * FROM durps;
+----+----------+
| id | name     |
+----+----------+
|  0 | durp zero |
+----+----------+
1 row in set (0.00 sec)

mysql> SELECT * FROM blahs;
+----+----------+
| id | name     |
+----+----------+
|  0 | blah zero |
+----+----------+
1 row in set (0.00 sec)

mysql> SELECT * FROM durpsblahs;
+----------+----------+
| durps_id | blahs_id |
+----------+----------+
|        0 |        0 |
+----------+----------+
1 row in set (0.00 sec)

When I go to “/dbauth2/durpsblahs/view/0/0” I get the following error:

Record not found in table “durpsblahs” with primary key [‘0’]

Ideas?

Also, my schema rocks! :smiley: #DurpsAndBlahsForever

Why don’t you create your user table (base app) with one-one connection with the existing user table (java module)?

In the same time you can create model, controller and views for the java module users table also in your app. In the end it is just a database table and you can read and write it from more sources, eg from java and from your base app - if it helps you in your situation.

OK, crisis averted. I spoke with the module vendor, and they’ve agreed to the changes that I requested for the Java module’s database structure. So, I can simply added the properly named tables to my application’s database, and add the appropriately named columns to my application’s “users” table. Along with that, the proper keys and constraints.

#issueResolved