0

I'm new to Magento 2 and to this forum. I'm trying to add a newsletter subscription on the customer menu, just after the core one.

For that, i created a module "ACME_Newsletter"

  1. I added a custom field to the customer_entity table via a db_schema :

     <table name="customer_entity">
     <column
         xsi:type="boolean"
         name="acme_nl_subscription"
         nullable="false"
         default="false"
         comment="Acme Newsletter Subscription"
     />
    
  2. I created a layout that completes the existing one "customer_newsletter"

    <body>
        <referenceBlock name="customer_newsletter">
            <container name="customer.form.newsletter.extra">
                <block
                    class="ACME\Newsletter\Block\Subscription"
                    name="customer_form_newsletter_extra" as="acme_nl_subscription"
                    template="ACME_Newsletter::customer/form/subscription.phtml"
                />
            </container>
        </referenceBlock>
    </body>

Here is my template :

    <?php

/** @var \ACME\Newsletter\Block\Subscription $block */
?>
<?= $block->getChildHtml('customer.form.newsletter.extra') ?>
<div class="field choice">
    <input type="checkbox" name="acme_nl_subscription" id="acme_nl_subscription" value="1"
           title="<?= $block->escapeHtmlAttr(__('ACME\'s Newsletter Subscription')) ?>"
        <?php if ($block->getCustomerSession()->getCustomer()->getAcmeNlSubscription()) : ?> checked="checked"<?php endif; ?>
           class="checkbox">
    <label for="acme_nl_subscription"
           class="label"><span><?= $block->escapeHtml(__('ACME\'s Newsletter Subscription')) ?></span></label>
</div>

And my block :

    <?php

namespace ACME\Newsletter\Block;

use Magento\Customer\Block\Newsletter;

class Subscription extends Newsletter
{
    public function getCustomerSession()
    {
        return $this->customerSession;
    }

}

With all that I manage to retrieve the value stored in database.

Now I try to modify that value and to store it in db, within an after plugin on the Magento\Newsletter\Controller\Manage\Save::execute() method.

I can't find the right way to write my method to persist this data. For the moment, my plugin looks like this :

<?php

namespace ACME\Newsletter\Plugin;

use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\Session;
use Magento\Newsletter\Controller\Manage\Save;
use Magento\Framework\App\RequestInterface;
use Magento\Customer\Model\ResourceModel\CustomerRepository as CustomerRepository;
use Magento\Customer\Model\ResourceModel\Customer as CustomerResource;
use Magento\Customer\Model\Customer as CustomerModel;

class AfterSavePlugin
{
    protected $customerSession;
    protected $request;
    protected $customerRepository;
    protected $customerRepositoryInterface;
    protected $customerResource;
    protected $customerModel;

    public function __construct(
        Session                     $customerSession,
        RequestInterface            $request,
        CustomerRepositoryInterface $customerRepositoryInterface,
        CustomerRepository          $customerRepository,
        CustomerResource            $customerResource,
        CustomerModel               $customerModel
    )
    {
        $this->customerSession = $customerSession;
        $this->request = $request;
        $this->customerRepository = $customerRepository;
        $this->customerRepositoryInterface = $customerRepositoryInterface;
        $this->customerResource = $customerResource;
        $this->customerModel = $customerModel;
    }

    public function afterExecute(Save $subject, $result)
    {
        $acmeNlSubscription = $this->request->getParam('acme_nl_subscription') ? (bool)$this->request->getParam('acme_nl_subscription') : 0;

        $sessionCustomer = $this->customerSession->getCustomer();
        $customerData = $sessionCustomer->getData();

        $repositoryCustomer = $this->customerRepository->getById($sessionCustomer->getId());

//        $modelCustomer->loadByEmail($sessionCustomer->getEmail());
        $modelCustomer = $this->customerModel;
        $modelCustomer->setData($customerData);

        $resourceCustomer = $this->customerResource->loadByEmail($modelCustomer, $modelCustomer->getEmail());

        $modelCustomer->save();

        return $result;
    }
}

Could a kind soul help me to take a step in my understanding of Adobe Commerce 2 (Magento 2) please?

What am I doing wrong? All comments are welcome, thank you!

3 Answers 3

0

Try adding before:

$modelCustomer->save();

The following line:

$modelCustomer->setAcmeNlSubscription($acmeNlSubscription);
1
  • Thank you for your help @Sundar. I finally found a solution that I'm posting next.
    – jlegrand79
    Commented May 10, 2023 at 9:01
0

Thank you for your help, but it didn't help me to resolve my problem yet.

I tried that too :

public function afterExecute(Save $subject, $result)
    {
        $acmeNlSubscription = $this->request->getParam('acme_nl_subscription') ? (int)$this->request->getParam('acme_nl_subscription') : 0;

        $customerId = $this->customerSession->getCustomerId();
        $customer = $this->customerRepositoryInterface->getById($customerId);
        $customer->setData('acme_nl_subscription', $acmeNlSubscription);

        $this->customerRepositoryInterface->save($customer);

        return $result;
    }

I can't understand why that doesn't work ???

0

I finally found a solution by adding a Data Patch

<?php

namespace ACME\Newsletter\Setup\Patch\Data;

use Magento\Customer\Model\Customer;
use Magento\Customer\Setup\CustomerSetup;
use Magento\Customer\Setup\CustomerSetupFactory;
use Magento\Eav\Model\Entity\Attribute\Set;
use Magento\Eav\Model\Entity\Attribute\SetFactory;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;
use Magento\Framework\Setup\Patch\PatchRevertableInterface;

class AddSubscriptionColumn implements DataPatchInterface, PatchRevertableInterface
{
    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

    /**
     * @var SetFactory
     */
    private $attributeSetFactory;

    /**
     * @var CustomerSetup
     */
    private $customerSetupFactory;

    /**
     * Constructor
     *
     * @param ModuleDataSetupInterface $moduleDataSetup
     * @param SetFactory $attributeSetFactory
     * @param CustomerSetupFactory $customerSetupFactory
     */
    public function __construct(
        ModuleDataSetupInterface $moduleDataSetup,
        SetFactory $attributeSetFactory,
        CustomerSetupFactory $customerSetupFactory
    ) {
        $this->moduleDataSetup = $moduleDataSetup;
        $this->attributeSetFactory = $attributeSetFactory;
        $this->customerSetupFactory = $customerSetupFactory;
    }

    /**
     * {@inheritdoc}
     */
    public function apply()
    {
        $this->moduleDataSetup->getConnection()->startSetup();
        /** @var CustomerSetup $setupCustomer */
        $setupCustomer = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $customerEntity = $setupCustomer->getEavConfig()->getEntityType(Customer::ENTITY);
        $defaultAttributeSetId = $customerEntity->getDefaultAttributeSetId();

        /** @var $attributeSet Set */
        $attributeSet = $this->attributeSetFactory->create();
        $attributeGroupId = $attributeSet->getDefaultGroupId($defaultAttributeSetId);

        $setupCustomer->addAttribute(
            Customer::ENTITY,
            'acme_nl_subscription',
            [
                'type' => 'static',
                'label' => 'Acme Newsletter Subscription',
                'input' => 'text',
                'required' => false,
                'visible' => true,
                'user_defined' => true,
                'sort_order' => 1000,
                'position' => 1000,
                'system' => 0,
            ]
        );

        $attribute = $setupCustomer->getEavConfig()->getAttribute(Customer::ENTITY, 'acme_nl_subscription');
        $attribute->addData([
            'used_in_forms' => [
                'adminhtml_customer',
                'adminhtml_checkout',
                'checkout_register',
                'customer_account_create',
                'newsletter_manage',
                'newsletter_manage_save'
            ]
        ]);
        $attribute->addData([
            'attribute_set_id' => $defaultAttributeSetId,
            'attribute_group_id' => $attributeGroupId
        ]);
        $attribute->save();

        $this->moduleDataSetup->getConnection()->endSetup();
    }

    /**
     * Rollback all changes
     *
     * @return void
     */
    public function revert()
    {
        $this->moduleDataSetup->getConnection()->startSetup();
        /** @var CustomerSetup $setupCustomer */
        $setupCustomer = $this->customerSetupFactory->create(['setup' => $this->moduleDataSetup]);
        $setupCustomer->removeAttribute(Customer::ENTITY, 'acme_nl_subscription');
        $this->moduleDataSetup->getConnection()->endSetup();
    }

    /**
     * {@inheritdoc}
     */
    public function getAliases()
    {
        return [];
    }

    /**
     * {@inheritdoc}
     */
    public static function getDependencies()
    {
        return [];
    }

}

The latest version of my method AfterSavePlugin::afterExecute()

    public function afterExecute(Save $subject, $result)
    {
        try {
            $acmeNlSubscription = $subject->getRequest()->getParam('acme_nl_subscription') ? $subject->getRequest()->getParam('acme_nl_subscription') : 0;

            $customerId = $this->customerSession->getCustomerId();

            $customer = $this->customerFactory->create()->load($customerId);

            $customer->setAcmeNlSubscription($acmeNlSubscription);

            $this->customerRepository->save($customer->getDataModel());

        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage());
        }

        return $result;
    }

If anyone can explain to me why this is necessary to create a Data Patch, I'm interested! Feel free to comment or suggest a better solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.