I'm writing a basic module that will create a Bill of Materials for items we sell in Magento 2.4.2 CE. The module has three tables: chlorinators, equipment, and chlorinator_equipment.
These tables are generated by db_schema.xml seen below:
<?xml version="1.0" encoding="UTF-8"?> <schema xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Setup/Declaration/Schema/etc/schema.xsd"> <table name="chlorinators" resource="default" engine="innodb" comment="Chlorinators Table"> <column xsi:type="smallint" name="chlorinator_id" unsigned="true" nullable="false" comment="Chlorinator ID"/> <column xsi:type="varchar" name="chlorinator_name" nullable="false" length="1024" comment="Chlorinator Name"/> <column xsi:type="boolean" name="has_pump" nullable="false" comment="Chlorinator has pump"/> <constraint xsi:type="primary" referenceId="PRIMARY"> <column name="chlorinator_id"/> </constraint> </table> <table name="equipment" resource="default" engine="innodb" comment="Equipment Table"> <column xsi:type="smallint" name="equipment_id" unsigned="true" nullable="false" comment="Equipment ID"/> <column xsi:type="varchar" name="equipment_name" nullable="false" length="1024" comment="Equipment Name"/> <column xsi:type="varchar" name="cutsheet_url" nullable="false" default="" comment="Cutsheet URL - Complete"/> <column xsi:type="varchar" name="cutsheet_stub" nullable="false" comment="Cutsheet URL - Stub"/> <constraint xsi:type="primary" referenceId="PRIMARY"> <column name="equipment_id"/> </constraint> </table> <table name="chlorinator_equipment" resource="default" engine="innodb" comment="Chlorinator Equipment Relation Table"> <column xsi:type="smallint" name="id" unsigned="true" nullable="false" identity="true" comment="Chlorinator Equipment ID"/> <column xsi:type="smallint" name="equipment_id" unsigned="true" nullable="false" comment="Equipment ID"/> <column xsi:type="smallint" name="chlorinator_id" unsigned="true" nullable="false" comment="Chlorinator ID"/> <column xsi:type='tinyint' name='quantity' unsigned='true' nullable='false' comment='Quantity' /> <constraint xsi:type="primary" referenceId="PRIMARY"> <column name="id"/> </constraint> <constraint xsi:type='foreign' referenceId="FK_CHLOR_ID" table='chlorinator_equipment' column='chlorinator_id' referenceTable='chlorinators' referenceColumn='chlorinator_id' onDelete='CASCADE'/> <constraint xsi:type='foreign' referenceId="FK_EQUIP_ID" table='chlorinator_equipment' column='equipment_id' referenceTable='equipment' referenceColumn='equipment_id' onDelete='CASCADE'/> </table> </schema>
Now that I have created the table, I'm looking to input data into the table using Magento's declarative schema. For the purposes of this question, I am only concerned with entering data into the 'chlorinators' table.
I have created a model for the chlorinators (\Jared\Submittal\Model\Chlorinator.php):
<?php namespace Jared\Submittal\Model; class Chlorinator extends \Magento\Framework\Model\AbstractModel { protected function _construct() { $this->_init('Jared\Submittal\Model\ResourceModel\Chlorinator'); } }
And a ResourceModel (\Jared\Submittal\Model\ResourceModel\Chlorinator.php):
<?php class Chlorinator extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb { protected function _construct() { $this->_init('chlorinators','chlorinator_id'); } }
At this point, I'm just trying to insert data into the created table via these models, but I'm not having any luck. I'm using a data patch to try to insert the data, which is below:
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Jared\Submittal\Setup\Patch\Data; use Magento\Framework\Setup\Patch\DataPatchInterface; /** */ class AddData implements \Magento\Framework\Setup\Patch\DataPatchInterface { /** * @var \Magento\Framework\Setup\ModuleDataSetupInterface */ private $moduleDataSetup; private $chlorinator; /** * @param \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup */ public function __construct( \Magento\Framework\Setup\ModuleDataSetupInterface $moduleDataSetup, \Jared\Submittal\Model\ResourceModel\Chlorinator $chlorinator ){ /** * If before, we pass $setup as argument in install/upgrade function, from now we start * inject it with DI. If you want to use setup, you can inject it, with the same way as here */ $this->moduleDataSetup = $moduleDataSetup; $this->chlorinator = $chlorinator; } /** * {@inheritdoc} */ public function apply() { $chlorinatorData = []; $chlorinatorData['chlorinator_id'] = '1'; $chlorinatorData['chlorinator_name'] = 'chlorinator 1'; $chlorinatorData['has_pump'] = '1'; $this->chlorinator->addData($chlorinatorData); $this->chlorinator->getResource()->save($this->chlorinator); } /** * {@inheritdoc} */ public static function getDependencies() { /** * This is dependency to another patch. Dependency should be applied first * One patch can have few dependencies * Patches do not have versions, so if in old approach with Install/Ugrade data scripts you used * versions, right now you need to point from patch with higher version to patch with lower version * But please, note, that some of your patches can be independent and can be installed in any sequence * So use dependencies only if this important for you */ return []; } public function revert() { $this->moduleDataSetup->getConnection()->startSetup(); //Here should go code that will revert all operations from `apply` method //Please note, that some operations, like removing data from column, that is in role of foreign key reference //is dangerous, because it can trigger ON DELETE statement $this->moduleDataSetup->getConnection()->endSetup(); } /** * {@inheritdoc} */ public function getAliases() { /** * This internal Magento method, that means that some patches with time can change their names, * but changing name should not affect installation process, that's why if we will change name of the patch * we will add alias here */ return []; } public static function getVersion() { return "1.0.0"; } }
I was under the impression that models inherited all the CRUD operations, but when I call create() in AddData.php, I get errors for calling an undefined method. My confusion is exacerbated by the fact that several modules online seem to use identical syntax and work, such as this one:
https://github.com/cedcommerce/Magento2.3-GraphQl/blob/master/Setup/Patch/Data/AddData.php
The error I'm getting has been copied below, please let me know if you see an error in my code that's causing these issues:
Fatal error: Uncaught Error: Call to undefined method Jared\Submittal\Model\ResourceModel\Chlorinator::create() in /var/www/html/app/code/Jared/Submittal/Setup/Patch/Data/AddData.php:63 Stack trace: #0 /var/www/html/vendor/magento/framework/Setup/Patch/PatchApplier.php(162): Jared\Submittal\Setup\Patch\Data\AddData->apply() #1 /var/www/html/setup/src/Magento/Setup/Model/Installer.php(1081): Magento\Framework\Setup\Patch\PatchApplier->applyDataPatch() #2 /var/www/html/setup/src/Magento/Setup/Model/Installer.php(947): Magento\Setup\Model\Installer->handleDBSchemaData() #3 /var/www/html/setup/src/Magento/Setup/Console/Command/UpgradeCommand.php(147): Magento\Setup\Model\Installer->installDataFixtures() #4 /var/www/html/vendor/symfony/console/Command/Command.php(255): Magento\Setup\Console\Command\UpgradeCommand->execute() #5 /var/www/html/vendor/symfony/console/Application.php(1009): Symfony\Component\Console\Command\Command->run() #6 /var/www/html/vendor/symfony/console/Application.php(273): Symfony\Component\Console\Applic in /var/www/html/app/code/Jared/Submittal/Setup/Patch/Data/AddData.php on line 63 {"messages":{"error":[{"code":500,"message":"Fatal Error: 'Uncaught Error: Call to undefined method Jared\\Submittal\\Model\\ResourceModel\\Chlorinator::create() in \/var\/www\/html\/app\/code\/Jared\/Submittal\/Setup\/Patch\/Data\/AddData.php:63\nStack trace:\n#0 \/var\/www\/html\/vendor\/magento\/framework\/Setup\/Patch\/PatchApplier.php(162): Jared\\Submittal\\Setup\\Patch\\Data\\AddData->apply()\n#1 \/var\/www\/html\/setup\/src\/Magento\/Setup\/Model\/Installer.php(1081): Magento\\Framework\\Setup\\Patch\\PatchApplier->applyDataPatch()\n#2 \/var\/www\/html\/setup\/src\/Magento\/Setup\/Model\/Installer.php(947): Magento\\Setup\\Model\\Installer->handleDBSchemaData()\n#3 \/var\/www\/html\/setup\/src\/Magento\/Setup\/Console\/Command\/UpgradeCommand.php(147): Magento\\Setup\\Model\\Installer->installDataFixtures()\n#4 \/var\/www\/html\/vendor\/symfony\/console\/Command\/Command.php(255): Magento\\Setup\\Console\\Command\\UpgradeCommand->execute()\n#5 \/var\/www\/html\/vendor\/symfony\/console\/Application.php(1009): Symfony\\Component\\Console\\Command\\Command->run()\n#6 \/var\/www\/html\/vendor\/symfony\/console\/Application.php(273): Symfony\\Component\\Console\\Applic' in '\/var\/www\/html\/app\/code\/Jared\/Submittal\/Setup\/Patch\/Data\/AddData.php' on line 63","trace":"Trace is not available."}]}}