Back to Top

How to create custom tab in back office product page

Updated 22 May 2024

In this blog, we are about to learn, how to create custom tab on the back office product page. So, we will define our own Symfony services in the module and will use existing components.

You can explore our PrestaShop Development Services and a large range of quality PrestaShop Modules.

Here, we are showing the process step by step with an example module ‘wktestmodule‘

First, create a module, with a composer.json file as per your requirement.

Step 1: Create the module class

Searching for an experienced
Prestashop Company ?
Find out More

Here, we have created the module class file “wktestmodule/wktestmodule.php“

In this class, we are initializing the module, product controllers tab, and form fields.

declare(strict_types=1);

use PrestaShop\Module\WkTestModule\Form\Modifier\ProductFormModifier;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;

class WkTestModule extends Module
{
    public function __construct()
    {
        $this->name = 'wktestmodule';
        $this->tab = 'front_office_features';
        $this->version = '1.0.0';
        $this->need_instance = 0;
        $this->bootstrap = true;
        parent::__construct();
        $this->displayName = $this->l('Webkul');
        $this->description = $this->l('Form types within PrestaShop');
        $this->ps_versions_compliancy = ['min' => '8.1', 'max' => _PS_VERSION_];
    }

    /**
     * @return bool
     */
    public function install()
    {
        return parent::install() && $this->registerHook(['actionProductFormBuilderModifier']);
    }
    
    /**
     * Modify product form builder
     *
     * @param array $params
     */
    public function hookActionProductFormBuilderModifier(array $params): void
    {
        /** @var ProductFormModifier $productFormModifier */
        $productFormModifier = $this->get(ProductFormModifier::class);
        $productId = isset($params['id']) ? new ProductId((int) $params['id']) : null;
        $productFormModifier->modify($productId, $params['form_builder']);
    }
}

After that, In the console in your module root run the command composer dump-autoload. This will generate a vendor folder containing an autoload.php file which allows the use of your namespace or the classes defined in the classmap.

Step 2: Define the service

Create a services.yml file inside the wktestmodule/config/services.yml folder

In the given code, we have defined our services. These will be used for form creation and form handling. Service is created inside the wktestmodule/src/Form/Modifier folder

services:
    PrestaShop\Module\WkTestModule\Form\Modifier\ProductFormModifier:
        autowire: true
        public: true
        arguments:
            $formBuilderModifier: '@form.form_builder_modifier'

    PrestaShop\Module\WkTestModule\Form\Type\CustomTabType:
        class: PrestaShop\Module\WkTestModule\Form\Type\CustomTabType
        parent: 'form.type.translatable.aware'
        public: true
        tags:
            - { name: form.type }

Step 3: Create a CustomTabType class

The tab class is created inside the wktestmodule/src/Form/Type folder

declare(strict_types=1);

namespace PrestaShop\Module\DemoProductForm\Form\Type;

use PrestaShopBundle\Form\Admin\Type\TranslatorAwareType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\PositiveOrZero;
use Symfony\Component\Validator\Constraints\Type;

class CustomTabType extends TranslatorAwareType
{
    /**
     * @var \Currency
     */
    private $defaultCurrency;

    /**
     * @param TranslatorInterface $translator
     * @param array $locales
     * @param \Currency $defaultCurrency
     */
    public function __construct(
        TranslatorInterface $translator,
        array $locales,
        \Currency $defaultCurrency
    ) {
        parent::__construct($translator, $locales);
        $this->defaultCurrency = $defaultCurrency;
    }

    /**
     * {@inheritDoc}
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        parent::buildForm($builder, $options);
        $builder
            ->add('webkul_custom_field', TextType::class, [
                'label' => $this->trans('Webkul Custom Field', 'Modules.Demoproductform.Admin'),
                'label_tag_name' => 'h3',
                // 'currency' => $this->defaultCurrency->iso_code,
                'required' => false,
                'constraints' => [
                    new NotBlank(),
                    new Type(['type' => 'float']),
                    new PositiveOrZero(),
                ],
            ])
        ;
    }

    /**
     * {@inheritDoc}
     */
    public function configureOptions(OptionsResolver $resolver)
    {
        parent::configureOptions($resolver);

        $resolver
            ->setDefaults([
                'label' => $this->trans('Webkul Tab', 'Modules.Demoproductform.Admin'),
            ])
        ;
    }
}

Step 4: Create a service ProductFormModifier class

declare(strict_types=1);

namespace PrestaShop\Module\WkTestModule\Form\Modifier;

use PrestaShop\Module\WkTestModule\Entity\CustomProduct;
use PrestaShop\Module\WkTestModule\Form\Type\CustomTabType;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShopBundle\Form\FormBuilderModifier;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Translation\TranslatorInterface;

final class ProductFormModifier
{
    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var FormBuilderModifier
     */
    private $formBuilderModifier;

    /**
     * @param TranslatorInterface $translator
     * @param FormBuilderModifier $formBuilderModifier
     */
    public function __construct(
        TranslatorInterface $translator,
        FormBuilderModifier $formBuilderModifier
    ) {
        $this->translator = $translator;
        $this->formBuilderModifier = $formBuilderModifier;
    }

    /**
     * @param ProductId|null $productId
     * @param FormBuilderInterface $productFormBuilder
     */
    public function modify(
        ?ProductId $productId,
        FormBuilderInterface $productFormBuilder
    ): void {
        $idValue = $productId ? $productId->getValue() : null;
        $customProduct = new CustomProduct($idValue);
        $this->addCustomTab($customProduct, $productFormBuilder);
    }

    /**
     * @param CustomProduct $customProduct
     * @param FormBuilderInterface $productFormBuilder
     */
    private function addCustomTab(CustomProduct $customProduct, FormBuilderInterface $productFormBuilder): void
    {
        $this->formBuilderModifier->addAfter(
            $productFormBuilder,
            'extra_modules',
            'custom_tab',
            CustomTabType::class,
            [
                'data' => [
                    'webkul_custom_field' => $customProduct->custom_price,
                ],
            ]
        );
    }
}

The above module uses a Form Builder Modifier (FormBuilderModifier) and adds a new Tab “Webkul Tab” with a field “Webkul Custom Field”.
After successfully installation of the above module. You will get the result as follows

NOTE: “actionProductFormBuilderModifier” supports in PrestaShop Version V8.1.0

So, this hook will work in the below PrestaShop Versions.

That’s all.

You also learn to save and display custom form field using PrestaShop Hook.

If you are facing any issues or doubts in the above process, please feel free to contact us in the comment section.

I would be happy to help.

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home