Associating an item to multiple other items (of a

2019-09-03 02:20发布

问题:

Having just arrived at Prestashop 1.5, I am making a very simple module: a video of the week, associated with multiple products that need to appear right next to it.

I decided to start from the Backoffice. Right now, I can view, add, edit and remove all the Video entries but I'm a bit lost on how to map the N-N association between a video and its related products... The lack of documentation isn't helping either.

Any ideas how to pull this off?

Here's a bit of my code, the Video class is defined by:

class Video extends ObjectModel {

    public $id_video;
    public $title;
    public $url;
    public $active;

    public static $definition = array(
        'table'     => 'video',
        'primary'   => 'id_video',
        'multilang' => false,
        'fields' => array(
            'id_video' => array(
                'type' => ObjectModel :: TYPE_INT
            ),
            'title' => array(
                'type' => ObjectModel :: TYPE_STRING, 
                'required' => true
            ),
            'url' => array(
                'type' => ObjectModel :: TYPE_STRING, 
                'required' => true
            ), 
            'active' => array(
                'type'      => ObjectModel :: TYPE_BOOL, 
                'required'  => true
            )
        ),
    );

(...)

and the AdminVideo class is here:

class AdminVideoController extends ModuleAdminController {

    public function __construct()
    {
        $this->table = 'video';
        $this->className = 'Video';
        $this->lang = false;

        $this->fields_list['id_video'] = array(
            'title' => $this->l('ID'),
            'align' => 'center',
        );

        $this->fields_list['title'] = array(
            'title' => $this->l('Title'),
            'width' => 'auto'
        );

        $this->fields_list['url'] = array(
            'title' => $this->l('URL'),
            'width' => 'auto'
        );

        $this->fields_list['active'] = array(
            'title' => $this->l('Active'),
            'width' => '70',
            'align' => 'center',
            'active' => 'status',
            'type' => 'bool',
            'orderby' => false
        );

        parent::__construct();
    }

    public function postProcess()
    {
         parent::postProcess();
    }

    public function renderList()
    {
        $this->addRowAction('edit');
        $this->addRowAction('delete');
        $this->addRowAction('details');

        return parent::renderList();
    }

    public function renderForm()
    {
        if (!($obj = $this->loadObject(true)))
            return;

        $this->fields_form = array(
            'legend' => array(
                'title' => $this->l('This weeks video'),
                'image' => '../img/admin/world.gif'
            ),
            'input' => array(
                array(
                    'type' => 'text',
                    'label' => $this->l('Nome'),
                    'name' => 'title',
                    'size' => 33,
                    'required' => true,
                    'desc' => $this->l('Title')
                ),
                array(
                      'type' => 'text',
                      'label' => $this->l('URL'),
                      'name' => 'url',
                      'size' => 33,
                      'required' => true,
                      'desc' => $this->l('Video URL')
                ),
                array(
                    'type' => 'radio',
                    'label' => $this->l('Active:'),
                    'name' => 'active',
                    'required' => false,
                    'class' => 't',
                    'is_bool' => true,
                    'values' => array(
                        array(
                            'id' => 'active_on',
                            'value' => 1,
                            'label' => $this->l('Enabled')
                        ),
                        array(
                            'id' => 'active_off',
                            'value' => 0,
                            'label' => $this->l('Disabled')
                        )
                    ),
                    'desc' => $this->l('Only one video can be active at any given time')
                ),
            )
        );

        if (Shop::isFeatureActive())
        {
            $this->fields_form['input'][] = array(
                'type' => 'shop',
                'label' => $this->l('Shop association:'),
                'name' => 'checkBoxShopAsso',
            );
        }

        $this->fields_form['submit'] = array(
            'title' => $this->l('   Save   '),
            'class' => 'button'
        );

        if (!($obj = $this->loadObject(true)))
            return;

        return parent::renderForm();
    }
  }

One other thing: would it be possible to add a preview of the video inside the backoffice? I tried to echo YouTube's embed code, but it gets inserted even before the header. Is there a clean way of doing this or do I have to use some jQuery trickery? I was basically doing an echo of YT's embed code just before the end of postProcess().

Thanks in advance!

回答1:

The simplest way to associate the videos to the products is by adding a "products" text field in your "video" table to store a comma separated list of the ids of the associated products (eg.: 1,10,27). Even if it's a bit rudimentary, it should work.
Alternatively, you could use a table like this:

create table video_product (
  id_association int not null auto_increment,
  id_video int,
  id_product int,
  primary key (id_association)
);

The problem with this solution is that the PrestaShop ObjectModel core does not provide any method to automatically update or delete the related tables (at least as far as I know), so you have to insert the code to manage the "video_product" table in your "Video" class.
If you want an example of how to do this, you should look at the classes/Product.php script, which manages the product table and all its related tables (categories, tags, features, attachments, etc.).
To have an idea of how the Prestashop database is structured, have a look at the docs/dbmodel.mwb file, which contains the schema of the database; this file can be viewed by using the MySQL Workbench application.