How to save data in database magento2? - magento2

I have integrated theme in magento2, and now I need to change In the registration form of theme.I need to add some field and save in database.
But I am new in magento2 and I didnt get the how to find controller for it and whats the flow?
So can any one have ideas about this?regarding how to start on customize in the theme?

For add field, you can add field in Setup/UpgradeSchema.php in your custom module:
namespace Name\moduleName\Setup;
use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
use Magento\Framework\DB\Ddl\Table;
class UpgradeSchema implements UpgradeSchemaInterface {
public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) {
$installer = $setup;
$installer->startSetup();
$installer->getConnection()->addColumn(
$installer->getTable('tablename'), 'field name', [
'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
'nullable' => true,
'length' => 255,
'comment' => 'xxxxx'
]
);
$installer->endSetup();
}
}
but you should change setup_version in module.xml and setup:upgrade
Or just add in database direcly:
ALTER TABLE table_name
ADD column_name datatype;

Related

TYPO3 TCA make the 'default' value dynamic

The title is rather self explanatory, but what i would like to have is a dynamic default value.
The idea behind it is to get the biggest number from a column in the database and then add one to the result. This result should be saved as the default value.
Lets take for example this code:
$GLOBALS['TCA'][$modelName]['columns']['autojobnumber'] = array(
'exclude' => true,
'label' => 'LLL:EXT:path/To/The/LLL:tx_extension_domain_model_job_autojobnumber',
'config' => [
'type' => 'input',
'size' => 10,
'eval' => 'trim,int',
'readOnly' =>1,
'default' => $result,
]
);
The SQL looks like this:
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tx_extension_domain_model_job');
$getBiggestNumber = $queryBuilder
->select('autojobnumber')
->from('tx_extension_domain_model_job')
->groupBy('autojobnumber')
->orderBy('autojobnumber', 'DESC')
->setMaxResults(1)
->execute()
->fetchColumn(0);
$result = $getBiggestNumber + 1;
So how can i do that "clean"?
I thought about processCmdmap_preProcess but i dont know how to pass the value to the coorisponding TCA field. Plus i do not get any results on my backend when i use the DebuggerUtility like i get them when i use processDatamap_afterAllOperations after saving the Object.
Can someone point me to the right direction?
I don't think it is supported to create a dynamic default value, see default property of input field.
What you can do however, is to create your own type (use this instead of type="input"). You can use the "user" type. (It might also be possible to create your own renderType for type="input", I never did this, but created custom renderTypes for type= "select").
You can look at the code of InputTextElement, extend that or create your own from scratch.
core code: InputTextElement
documentation for user type
more examples in FormEngine documentation
Example
(slightly modified, from documentation)
ext_localconf.php:
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['nodeRegistry'][<current timestamp>] = [
'nodeName' => 'customInputField',
'priority' => 40,
'class' => \T3docs\Examples\Form\Element\CustomInputElement::class,
];
CustomInputElement
<?php
declare(strict_types = 1);
namespace Myvendor\MyExtension\Backend\FormEngine\Element\CustomInputElement;
use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
// extend from AbstractFormElement
// alternatively, extend from existing Type and extend it.
class CustomInputElement extends AbstractFormElement
{
public function render():array
{
$resultArray = $this->initializeResultArray();
// add some HTML
$resultArray['html'] = 'something ...';
// ... see docs + core for more info what you can set here!
return $resultArray;
}
}

How to configure extbase to fetch inline / IRRE relations to tt_content?

I've built a extension where I can assign content elements (tt_content) inline (IRRE) to my entries in the TYPO3 Backend.
But I can't figure out how I can resolve the relations so that I can display the assigned content elements in the frontend.
I've created the extension with the 'Extension Builder' in TYPO3 9.5.5.
I created a Model Object 'Content' and selected 'Map to existing table' in the 'Domain object settings' and choosed 'tt_content'.
In my model 'ProductTab' I configured a 1:n relation of type 'Inline (IRRE)' with the name 'content' to my 'Content' model.
If I add content elements to my model entries in the Backend, it works like expected. The relational fields in the DB are mapped correctly. With the 'Extbase Variable Dump' I can see that all my relations are passed to the front end plugin, but my 'content' relation is an empty 'ObjectStorage'.
What am I missing so that the extbase persistence fetches my content relations?
ext_tables.sql excerpts
CREATE TABLE tx_myext_domain_model_producttab (
product int(11) unsigned DEFAULT '0' NOT NULL,
title varchar(255) DEFAULT '' NOT NULL,
content int(11) unsigned DEFAULT '0' NOT NULL,
);
CREATE TABLE tt_content (
producttab int(11) unsigned DEFAULT '0' NOT NULL,
);
TCA excerpts
'content' => [
'exclude' => false,
'label' => 'producttab.content',
'config' => [
'type' => 'inline',
'foreign_table' => 'tt_content',
'foreign_field' => 'producttab',
'maxitems' => 9999,
'appearance' => [
'collapseAll' => 0,
'levelLinksPosition' => 'top',
'showSynchronizationLink' => 1,
'showPossibleLocalizationRecords' => 1,
'showAllLocalizationLink' => 1
],
],
],
Since I can add and edit the content elements in the Backend, I think the DB and TCA relation is fine.
But something is still missing, so that the relation is fetched and provided to the FE template so that I can display the assigned content elements with a ViewHelper.
ProductTab.php excerpts
class ProductTab extends \TYPO3\CMS\Extbase\DomainObject\AbstractValueObject
{
protected $content = null;
protected function initStorageObjects()
{
$this->content = new \TYPO3\CMS\Extbase\Persistence\ObjectStorage();
}
public function addContent(\MyExt\Domain\Model\Content $content)
{
$this->content->attach($content);
}
public function removeContent(\MyExt\Domain\Model\Content $contentToRemove)
{
$this->content->detach($contentToRemove);
}
public function getContent()
{
return $this->content;
}
public function setContent(\TYPO3\CMS\Extbase\Persistence\ObjectStorage $content)
{
$this->content = $content;
}
}
Extbase Variable Dump
Screenshot of debug output
On the screenshot you can see the fetched products (one item in this case) and the producttabs (also 1 item). There is one content element assigned, but the property content of the ProductTab with uid=1 is empty.
Update
Since I'm still not able to solve this issue, I've created a minimalistic extension with the Extension Builder to demonstrate the issue: https://github.com/apiening/demo_irrecontent
The extension is the most simple one I could create with one model holding only one property and the relation to tt_content. It has a plugin list which also shows the debug output.
I've put some more details in the README.mdof the GitHub project.

magento2 adding customer attributes

Using Magento 2.3.0
Whenever trying to save customer I get errors that newly created attributes are required, even when I set their values.
etc/extend_attributes.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Customer\Api\Data\CustomerInterface">
<attribute code="customershipping_enabled" type="string" />
<attribute code="customershipping_price" type="string" />
</extension_attributes>
</config>
Setup/InstallData.php
<?php
namespace <vendor>\<module_name>\Setup;
use Magento\Eav\Model\Entity\Attribute\Source\Boolean;
use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
class InstallData implements InstallDataInterface {
private $customerSetupFactory;
public function __construct(
\Magento\Customer\Setup\CustomerSetupFactory $customerSetupFactory
) {
$this->customerSetupFactory = $customerSetupFactory;
}
public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) {
$customerSetup =$this->customerSetupFactory->create(['setup'=>$setup]);
$setup->startSetup();
$customerSetup->addAttribute('customer', 'customershipping_enabled', [
'label'=>'Customer Shipping Enabled',
'type' => 'int',
'input' => 'select',
'source' => Boolean::class,
'required'=>true,
'visible'=>true,
'default' => 0,
'position' => 198,
]);
$customerSetup->addAttribute('customer', 'customershipping_price', [
'label'=>'Customer Shipping Price',
'type'=>'decimal',
'input' => 'text',
'required'=>true,
'visible'=>true,
'default' => 0,
'position' => 199,
]);
$enabledAttribute = $customerSetup->getEavConfig()->getAttribute('customer', 'customershipping_enabled');
$enabledAttribute->setData('used_in_forms', ['adminhtml_customer']);
$enabledAttribute->save();
$priceAttribute = $customerSetup->getEavConfig()->getAttribute('customer', 'customershipping_price');
$priceAttribute->setData('used_in_forms', ['adminhtml_customer']);
$priceAttribute->save();
$setup->endSetup();
}
}
I have read many tutorials and documentation on this, and I believe this should be working correctly, am I missing something?
Whenever I try to add new customer or update existing customer, it says that these 2 attributes are required values, save fails.
Also looks identical to this post:
mage2gen.com/snippets/customerattribute
I had similar issue recently, try to add this in 'used_in_forms'.
You might have to remove the attribute and reinstall it:
'used_in_forms' => ['adminhtml_customer', 'customer_account_edit', 'customer_account_create']
edit
Oh I think this should solve the issue, just checked my installData and upgradeData scripts and they all have system => 0. Just add it in.
$customerSetup->addAttribute('customer', 'customershipping_enabled', [
'label'=>'Customer Shipping Enabled',
'type' => 'int',
'input' => 'select',
'source' => Boolean::class,
'required'=>true,
'visible'=>true,
'default' => 0,
'position' => 198,
'system' => 0
]);
It'll be related to this issue:
https://apiworks.net/magento2/magento-2-is-not-saving-the-customer-attribute/
The function getCustomAttributesMetadata is looping through all EAV
attributes and checking if the attribute is marked as “is_system”
inside the “customer_eav_attribute” table, which was the case with my
custom attribute.
Solution:
By default, Magento flagged my custom attribute as is_system = 1, so I
just needed to add ‘system’ => false in my upgrade script and execute
it again (after I removed the original attribute directly from the
database. ).
Root cause of this issue is design behavior of magento 2.
If custom attribute is set as a required one than it must be configured to be shown on storefront and to be shown in all the forms.
If you wants a custom attribute to be required only on some certain forms, then an extension attribute should be used instead with 'required'=>false.
Extension attributes are used to extend functionality of custom attributes.
You just need to replace
'required'=>true,
with
'required'=>false,
For more details please refer the link:
Click here

How to disable filter of a field in Zend Framework 2 in the controller?

Form to add/edit user I get from service manager with already installed filter, which is the test password. But this password is not needed when the user is edited. Can I somehow disabled password field validation in the controller?
In the getServiceConfig function of the module:
// ....
'UserCRUDFilter' => function($sm)
{
return new \Users\Form\UserCRUDFilter();
},
'UserCRUDForm' => function($sm, $param, $param1)
{
$form = new \Users\Form\UserCRUDForm();
$form->setInputFilter($sm->get('UserCRUDFilter'));
return $form;
},
// ....
In the controller I first of all getting a form object from service manager:
$form = $this->getServiceLocator()->get('UserCRUDForm');
Then disable user password validation and requirements, when user is edited and password not specified:
if ($user_id > 0 && $this->request->getPost('password') == '') {
$form->.... // Someway gained access to the filter class and change the password field validation
}
And after this i make a validation:
$form->isValid();
I found it!
// If user is editted - clear password requirement
if ($user_id > 0) {
$form->getInputFilter()->get('password')->setRequired(false);
$form->getInputFilter()->get('confirm_password')->setRequired(false);
}
This lines is disables requirement of input form fields :)
if you like to set all validators by yourself, call inside your form class
$this->setUseInputFilterDefaults(false);
to disable auto element validations/filter added from zend.
if you like to remove filter from elements call in your controller after your form object this
$form->getInputFilter()->remove('InputFilterName');
$form->get('password')->removeValidator('VALIDATOR_NAME'); should do the trick.
Note that you may have to iterate trough the Validatorchain when using Fieldsets.
$inputFilter->add(array(
'name' => 'password',
'required' => true,
'allow_empty' => true,
));
And on ModeleTable: saveModule:
public function saveAlbum(Album $album)
{
$data = array(
'name' => $album->name,
);
if (isset($album->password)){
$data['password'] = $album->password;
}

Repository/controller: How can I force TYPO3 to load the field "sorting"?

In a controller/template I'd like to have access to the field sorting of an entity.
I've tried to access it like:
$category->getSorting();
But it fails, as the method does not exist. When I dump the entity, all those meta fields, like hidden, starttime etc. aren't listed at all.
How can I tell TYPO3 to load those fields along with the other fields of the entitiy?
Since you are in Extbase context, you have to add the property to your model or (if you use the model of another extension) extend it and add the property. In both cases a getter and a setter method is needed if you want to access and edit the properties value:
/**
* #var integer
*/
protected $sorting;
public function setSorting($sorting) {
$this->sorting = $sorting;
}
public function getSorting() {
return $this->sorting;
}
Make sure you have that field configured in the TCA as well:
...
'columns' => array(
'sorting' => array(
'label' => 'sorting',
'config' => array(
'type' => 'passthrough'
)
),
...
After this you should be able to access the sorting property.