PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Sunday, March 13, 2022

[FIXED] Loading a baked Plugin Model fails with "Table class for alias Data.History could not be found"

 March 13, 2022     cakephp, cakephp-4.x, cakephp-bake, cakephp-model     No comments   

Issue

I baked a model into a plugin, but it fails to load.

What I did:

  1. Baked a model

    bin/cake bake model History --connection data --plugin Data --no-rules --no-validation --table elements_history
    

One moment while associations are detected.

Baking table class for History...

Creating file /var/www/app/plugins/Data/src/Model/Table/HistoryTable.php Wrote /var/www/app/plugins/Data/src/Model/Table/HistoryTable.php

Baking entity class for History...

Creating file /var/www/app/plugins/Data/src/Model/Entity/History.php Wrote /var/www/app/plugins/Data/src/Model/Entity/History.php

Baking test fixture for History...

Creating file /var/www/app/plugins/Data/tests/Fixture/HistoryFixture.php Wrote /var/www/app/plugins/Data/tests/Fixture/HistoryFixture.php Bake is detecting possible fixtures...

Baking test case for Data\Model\Table\HistoryTable ...

Creating file /var/www/app/plugins/Data/tests/TestCase/Model/Table/HistoryTableTest.php Wrote /var/www/app/plugins/Data/tests/TestCase/Model/Table/HistoryTableTest.php Done

  1. Loaded the newly created plugin via $this->addPlugin('Data');

  2. Verified the plugin was loaded via bin/cake plugin loaded

  3. Confirmed plugins/Data/src/Model/Table/HistoryTable.php exists

    root@debian:/var/www/app# cat plugins/Data/src/Model/Table/HistoryTable.php
    <?php
    declare(strict_types=1);
    
    namespace Data\Model\Table;
    
    use Cake\ORM\Query;
    use Cake\ORM\RulesChecker;
    use Cake\ORM\Table;
    use Cake\Validation\Validator;
    
    /**
     * History Model
     *
     * @method \Data\Model\Entity\History newEmptyEntity()
     * @method \Data\Model\Entity\History newEntity(array $data, array $options = [])
     * @method \Data\Model\Entity\History[] newEntities(array $data, array $options = [])
     * @method \Data\Model\Entity\History get($primaryKey, $options = [])
     * @method \Data\Model\Entity\History findOrCreate($search, ?callable $callback = null, $options = [])
     * @method \Data\Model\Entity\History patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
     * @method \Data\Model\Entity\History[] patchEntities(iterable $entities, array $data, array $options = [])
     * @method \Data\Model\Entity\History|false save(\Cake\Datasource\EntityInterface $entity, $options = [])
     * @method \Data\Model\Entity\History saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
     * @method \Data\Model\Entity\History[]|\Cake\Datasource\ResultSetInterface|false saveMany(iterable $entities, $options = [])
     * @method \Data\Model\Entity\History[]|\Cake\Datasource\ResultSetInterface saveManyOrFail(iterable $entities, $options = [])
     * @method \Data\Model\Entity\History[]|\Cake\Datasource\ResultSetInterface|false deleteMany(iterable $entities, $options = [])
     * @method \Data\Model\Entity\History[]|\Cake\Datasource\ResultSetInterface deleteManyOrFail(iterable $entities, $options = [])
     *
     * @mixin \Cake\ORM\Behavior\TimestampBehavior
     */
    class HistoryTable extends Table
    {
        /**
         * Initialize method
         *
         * @param array $config The configuration for the Table.
         * @return void
         */
        public function initialize(array $config): void
        {
            parent::initialize($config);
    
            $this->setTable('elements_history');
            $this->setDisplayField('id');
            $this->setPrimaryKey('id');
    
            $this->addBehavior('Timestamp');
    
        }
    
        /**
         * Returns the database connection name to use by default.
         *
         * @return string
         */
        public static function defaultConnectionName(): string
        {
            return 'data';
        }
    }
    
  4. Added the plugin model to an arbitrary controller method:

    • either $this->loadModel('Data.History');,
    • or TableRegistry::getTableLocator()->get('Data.History');
  5. Got the error:

Table class for alias Data.History could not be found. Cake\ORM\Exception\MissingTableClassException CORE/src/ORM/Locator/TableLocator.php:245

What have I tried:

  • I have looked into CORE/src/ORM/Locator/TableLocator.php and I can log that _getClassName receives Data.History, but returns a null. I have also logged $this->locations which it loops through, and the plugin path is not there:

    Array
    (
        [0] => Model/Table
    )
    
  • Added debug to CORE/src/Core/App.php right before it runs a test for \Model\Table\HistoryTable against _classExistsInBase.

    debug([
        '$plugin' => $plugin,
        '$name' => $name,
        '$base' => $base,
        '$fullname' => $fullname,
        '_classExistsInBase' => static::_classExistsInBase($fullname, $base),
    ]);
    
    CORE/src/Core/App.php (line 70)
    [
    '$plugin' => 'Data',
    '$name' => 'History',
    '$base' => 'Data',
    '$fullname' => '\Model\Table\HistoryTable',
    '_classExistsInBase' => false,
    ]
    

Do you know what is the issue and how to fix? I'm on CakePHP 4.2.4 and Bake 2.


Solution

In case of manually created plugins you need to make sure that you update your composer.json's autoloader configuration accordingly and dump the autoloader, otherwise your plugin classes cannot be found.

For your local Data plugin that would look something like this:

{
    // ...
    "autoload": {
        "psr-4": {
            // ...
            "Data\\": "plugins/Data/src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            // ...
            "Data\\Test\\": "plugins/Data/tests/"
        }
    }
}

and then you dump the autoloader:

composer dumpautoload

If you create your plugins using bake, it will ask you whether it should modify your composer.json, and if you allow it it will update it accordingly and dump the autoloader.

See also

  • Cookbook > Plugins > Manually Autoloading Plugin Classes
  • Cookbook > Plugins > Creating Your Own Plugins > Creating a Plugin Using Bake


Answered By - ndm
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing