prestashop_product_v2_hybrid_tabs · git:20260604.8ae1905 · 2026-06-04 · sha256 e78fa3980b4f27b2

prestashop_product_v2_hybrid_tabs git:20260604.8ae1905A

Immutable. This exact content never changes and is served at /api/v1/blob/e78fa3980b4f27b2.

---
name: prestashop_product_v2_hybrid_tabs
description: Definitive guide to creating Custom Tabs in PrestaShop 8+ Product Page V2 using Hybrid Injection (Symfony + Legacy).
---

# PrestaShop 8+ Product V2 Hybrid Tabs (The "OmniMind" Method)

## 🚨 CRITICAL: READ THIS BEFORE ATTEMPTING TO ADD TABS 🚨

Adding tabs to the new Symfony-based Product Page (V2) in PrestaShop 8.1+ requires a **Hybrid Approach** if you want to reuse legacy controllers/content easily.

### The "Tripod" Architecture
For the tab to appear and function, **THREE** components must exist and work simultaneously:

1.  **The Skeleton (Symfony Form Modifier)**
    *   **Role**: Creates the visual tab title and a hidden DOM target.
    *   **Class**: Must implement a method to add a `FormType` to the `$params['form_builder']`.
    *   **Key Code**:
        ```php
        $formBuilder->add('my_module_tab', FormType::class, [
            'label' => 'My Tab Title',
            'inherit_data' => true,
        ]);
        $formBuilder->get('my_module_tab')->add('injection_marker', TextType::class, [
            'attr' => ['class' => 'my-teleport-target'], // JS targets this class
        ]);
        ```
    *   **Location**: `classes/Form/Modifier/ProductFormBuilderModifier.php` (or similar).

2.  **The Content (Legacy Hook)**
    *   **Role**: Renders the actual HTML content (buttons, tables) using existing Smarty templates.
    *   **Hook**: `displayAdminProductsExtra`
    *   **Key**: Render your content normally. In V2, this hook renders at the bottom of the page (invisible or misplaced). We will move it.

3.  **The Mover (JavaScript Teleport)**
    *   **Role**: Moves the content from the bottom of the page into the Tab Skeleton.
    *   **Code**:
        ```javascript
        $(document).ready(function() {
            var $content = $('#my-legacy-content');
            var $target = $('.my-teleport-target').closest('.card'); // Find the tab container
            if ($target.length && $content.length) {
                $content.detach().appendTo($target);
                $content.show();
            }
        });
        ```

### 4. Hook Registration (Self-Healing)
You **MUST** ensure `actionProductFormBuilderModifier` is registered.
Add this safe-guard to your module's `__construct()`:

```php
if (defined('_PS_ADMIN_DIR_') && !$this->isRegisteredInHook('actionProductFormBuilderModifier')) {
    $this->registerHook('actionProductFormBuilderModifier');
}
```

### 5. Common Pitfalls
*   **Missing File**: If the Form Modifier class file is missing, the tab vanishes SILENTLY.
*   **Missing Hook**: If the hook is not registered, the tab vanishes SILENTLY.
*   **JS Timing**: Ensure your JS runs after the DOM is ready.
*   **Controller 500**: If you use AJAX in your tab, ensure your controllers accept `id_product` (as Task ID might not exist yet) and pass `$context` to services.

---
**Generated by AI Assistant on 2026-02-17 to prevent regression.**