Вы здесь

Создание формы добавления товара в корзину

Будем писать простую форму добавления товара в корзину и выводить эту форму на странице товара чтобы юзверь мог нажать на кнопку и добавить товар в корзину.

Назовем модуль trade_add_to_cart

- создаем папку
modules/trade/modules/trade_add_to_cart
(например mkdir --parent ...modules/trade/modules/trade_add_to_cart)
- создаем в папке файл trade_add_to_cart.info.yml

name: Trade add to cart
description: Trade add to cart
type: module
package: Trade
# core: 8.x
dependencies:
  - trade

# Information added by Drupal.org packaging script on 2017-09-08
version: '8.x-1.0'
core: '8.x'
project: 'trade'
datestamp: 1504875675

- создаем файл trade_add_to_cart.module где описывае поле с формой и выводим в него форму ...

<?php

use \Drupal\Core\Entity\EntityInterface;
use \Drupal\Core\Entity\Display\EntityViewDisplayInterface;

/**
* @file
* Module file for trade_product.
*/

/**
* Implements hook_entity_extra_field_info().
*/
function trade_add_to_cart_entity_extra_field_info() {
  $extra['node']['trade_product']['display']['trade_add_to_cart'] = [
    'label' => t('Add to cart'),
    'description' => t('Trade add to cart'),
    'weight' => 100,
    'visible' => TRUE,
  ];
  return $extra;
}

/**
* Implements hook_ENTITY_TYPE_view().
*/
function trade_add_to_cart_node_view(array &$build, EntityInterface $node, EntityViewDisplayInterface $display, $view_mode) {
  if ($display->getComponent('trade_add_to_cart')) {
    $form = \Drupal::formBuilder()
      ->getForm('Drupal\trade_add_to_cart\Form\TradeAddToCartForm', $node->id());
    $build['trade_add_to_cart'] = $form;
  }
}

- чуть не забыли саму форму :)
создаем файл trade_add_to_cart/src/Form/TradeAddToCartForm.php
ну это уже у каждого совя форма, на примере форма ajax овая чтобы страницу не пергружать ...

<?php

namespace Drupal\trade_add_to_cart\Form;

use Drupal\Core\Flood\FloodInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\user\UserAuthInterface;
use Drupal\user\UserStorageInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\node\Entity\Node;
use Drupal\taxonomy\Entity\Term;
use Drupal\Component\Utility\Html;
use Drupal\Core\Render\Element;
use Drupal\Core\Url;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Ajax\InvokeCommand;

/**
* Provides trade add to cart form.
*/
class TradeAddToCartForm extends FormBase {

  /**
   * The flood service.
   *
   * @var \Drupal\Core\Flood\FloodInterface
   */
  protected $flood;

  /**
   * The user storage.
   *
   * @var \Drupal\user\UserStorageInterface
   */
  protected $userStorage;

  /**
   * The user authentication object.
   *
   * @var \Drupal\user\UserAuthInterface
   */
  protected $userAuth;

  /**
   * The renderer.
   *
   * @var \Drupal\Core\Render\RendererInterface
   */
  protected $renderer;

  /**
   * Constructs a new TradeAddToCartForm.
   *
   * @param \Drupal\Core\Flood\FloodInterface $flood
   *   The flood service.
   * @param \Drupal\user\UserStorageInterface $user_storage
   *   The user storage.
   * @param \Drupal\user\UserAuthInterface $user_auth
   *   The user authentication object.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer.
   */
  public function __construct(FloodInterface $flood, UserStorageInterface $user_storage, UserAuthInterface $user_auth, RendererInterface $renderer) {
    $this->flood = $flood;
    $this->userStorage = $user_storage;
    $this->userAuth = $user_auth;
    $this->renderer = $renderer;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('flood'),
      $container->get('entity.manager')->getStorage('user'),
      $container->get('user.auth'),
      $container->get('renderer')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'trade_add_to_cart_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $node_id = 0) {
    $config = $this->config('system.site');
    $form = [];
    $node = Node::load($node_id);

    if ($node) {
      if ($form_state->has('trade_ajax_form_id')) {
        $form_id = $form_state->get('trade_ajax_form_id');
      }
      else {
        $form_id = Html::getId("trade_add_to_cart_form_{$node_id}");
      }
      $form['#id'] = $form_id;

      $form['#attributes']['class'][] = 'trade-add-to-cart-form';
      $form['entity_id'] = [
        '#type' => 'hidden',
        '#value' => $node_id,
      ];

      //product option entity reference fields
      if (\Drupal::moduleHandler()->moduleExists('trade_option_term')) {
        $fields = \Drupal::service('trade_option_term.manager')
          ->getFields($node);
        if ($fields) {
          $option_term_field = \Drupal::service('trade_option_term.trade_option_term_field')
            ->readUseDefault($node);
          foreach ($fields as $field_name => $field) {
            if (!empty($option_term_field[$field_name]->target_id)
              && ($term = Term::load($option_term_field[$field_name]->target_id))
            ) {
              $default_value = $term->id();
            }
            else {
              $default_value = '_none';
            }
            $element_type = $this->config('trade.adm')
              ->get('devel') ? 'textfield' : 'hidden';
            $form[$field_name] = [
              '#type' => $element_type,
              '#title' => $field_name,
              '#default_value' => $default_value,
              '#attributes' => [
                'data-trade-field' => $field_name,
                'data-trade-form' => $form_id,
              ],
            ];
          }
        }
      }
      $form['quantity'] = [
        '#type' => 'number',
        '#default_value' => 1,
        '#step' => 1,
        '#size' => 16,
        '#maxlength' => 16,
        '#placeholder' => t('Quantity'),
      ];
      if (!empty($node->field_trade_units)) {
        $units_label = $node->field_trade_units->entity->label();
        $form['quantity']['#description'] = $units_label;
        $form['units_label'] = [
          '#type' => 'hidden',
          '#value' => $units_label,
        ];
      }
      $form['actions'] = [
        '#type' => 'actions',
      ];
      $form['actions']['submit'] = [
        '#type' => 'submit',
        '#value' => $this->t('Add to cart'),
        '#ajax' => [
          'callback' => '::ajaxSubmit',
        ],
      ];
      $form['messages'] = [
        '#type' => 'container',
        '#attributes' => [
          'class' => [
            'trade-add-to-cart-messages',
          ],
        ],
      ];
      $this->renderer->addCacheableDependency($form, $config);
    }
    return $form;
  }

  /**
   * Implements set form default value.
   *
   * @param array $form
   *   Form render array.
   */
  public
  function setFormDefaultValue(&$form) {
    foreach (Element::children($form) as $element_children_key) {
      if (isset($form[$element_children_key]['#default_value'])
        && isset($form[$element_children_key]['#value'])) {
        $form[$element_children_key]['#value'] = $form[$element_children_key]['#default_value'];
      }
    }
  }

  /**
   * Implements ajax submit callback.
   *
   * @param array $form
   *   Form render array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Current state of the form.
   *
   * @return array $form
   */
  public
  function ajaxSubmit(array &$form, FormStateInterface $form_state) {
    $form['messages']['#attributes']['class'][] = 'trade-attach-modal-slide';
    $form['messages']['status'] = [
      '#type' => 'status_messages',
    ];
    $form_selector = '#' . $form_state->get('trade_ajax_form_id');
    $response = new AjaxResponse();
    $response->addCommand(new ReplaceCommand($form_selector, $form));
    $response->addCommand(new InvokeCommand($form_selector, 'trigger', ['replaceTradeAddToCartForm']));
    return $response;
  }

  /**
   * {@inheritdoc}
   */
  public
  function submitForm(array &$form, FormStateInterface $form_state) {
    $node = Node::load($form_state->getValue('entity_id'));
    if (\Drupal::moduleHandler()->moduleExists('trade_order')
      && !empty($node)
    ) {
      $order_storage = \Drupal::service('entity.manager')
        ->getStorage('trade_order');
      $cart = $order_storage->loadCart();
      if (empty($cart)) {
        $order_storage->createCart();
        $cart = $order_storage->loadCart();
      }

      //add item
      if (!empty($cart)) {
        $values = $form_state->getValues();

        //get product options
        if (\Drupal::moduleHandler()->moduleExists('trade_option_term')) {
          $options_fields = \Drupal::service('trade_option_term.manager')
            ->getFields($node);
          $values['options'] = array_intersect_key($form_state->getValues(), $options_fields);
          $options_texts = [];
          foreach ($values['options'] as $field_name => $field_value) {
            $field_value_entity = TERM::load($field_value);

            if (!empty($field_value_entity)) {
              $field_value_label = $field_value_entity->label();
              if (empty($field_value_label)) {
                $field_value_label = $field_value;
              }
              $options_texts[] = $node->getFieldDefinition($field_name)
                  ->label() . ':' . $field_value_label;
              $values['options_text'] = implode(';', $options_texts);
            }
          }
        }
        $cart->addItem($node, $values);
      }
    }
    $cart_url = Url::fromRoute('trade_order.cart')->toString();
    drupal_set_message($this->t('Product <strong>:nam</strong> added to <a href=":cart_url">cart</a>.', [
      ':nam' => $node->label(),
      ':cart_url' => $cart_url,
    ]));
    $form_state->set('trade_ajax_form_id', $form['#id']);
    $form_state->setRebuild(TRUE);
  }
}