OpenCart

Page last edited 1 921 giorni 19 ore fa
Da wiki.betaingegneria.it.

OpenCart[modifica]

Un software open source, scritto in PHP con connettori per vari tipi di database, per la gestione di negozi elettronici.

Installazione[modifica]

Non è prevista la multi aziendalità: negozi diversi devono stare su tabelle diverse da configurare ex novo per ognuno. Per questo è previsto il prefisso nel nome delle tabelle. Ma se non c'è il problema multi azienda è meglio non usarlo.

Personalizzazione delle etichette[modifica]

Ho scaricato la patch per la versione Italiana. E' incompleta, non tutte le etichette sono state tradotte. La localizzazione è concentrata nelle due cartelle di primo livello admin e catalog.

All'interno di queste vi sono le cartelle language/italian e, a seguire, sotto, una cartella per entità; lì dentro ci sono le etichette da personalizzare. Prima di cominciare, ho fatto un backup delle cartelle admin e catalog, e ciò si è rivelato provvidenziale.

Per aiutarsi, se in una pagine esce un'etichetta non localizzata (si può leggere qualcosa di tipo 'text_default' oppure 'text_empty'), leggere l'url: ci dev'essere qualcosa del tipo:

route=extension/module

quel path ci dice il percorso sotto admin/language/italian o catalog/language/italian in cui cercare, per esempio, l'etichetta text_empty:

$ find . -name "*" -exec grep _H "text_empty" {} \;

Confontare poi il path con admin.orig/language/english dello stesso file e lì si può vedere quali voci mancano nella localizzazione, e quindi procedere all'integrazione.

Integrazione di un attributo nei prodotti[modifica]

Questo è un attimo più complicato.

0) decidere precisamente il nome dell'attributo (ad esempio product.ref)

1) modificare la tabella relativa all'entità (model, product, payment, ...) così (ad esempio):

alter table ocproduct add ref varchar(100);

2) ora, il model: dentro a catalog/model/catalog/product.php ci sono le query per leggere il prodotto; generalmente (a meno che non si debbano fare query su qyesto specifico campo, ad esempio query ordinata in base al nuovo campo) non occorre cambiare nulla

3) dentro a admin/model/catalog/product.php ci sono invece le query anche per INSERT e UPDATE: mutare mutandis.

4) a questo punto il modello è a posto, si deve passare al controller; in catalog/controller/product.php c'è l'inizializzazione della variabile contenente il campo (riga 134); in questo esempio ho aggiunto un attributo ref e viene messo nella variabile il valore:

$this->data['text_ref'] = $this->language->get('text_ref');

5) ora è il momento della view, come il dato viene visualizzato. Aprire catalog/view/theme/default/template/product/product.tpl aggiungere nel template HTML, nella posizione che si desidera, il frammento di HTML che ospiterà il campo; nel mio esempio (nota che la variabile si chiama $ref.

<?php if ($ref) { 
// aggiungo un campo nuovo per prova              
?>

  <tr>

    <td><b><?php echo $text_ref; ?></b></td>

    <td><a href="<?php echo str_replace('&', '&', $ref); ?>"><?php echo $ref; ?></a></td>

  </tr>

<?php } ?>

E' orrendo, ma è così :(

Per aggiungere l'intestazione della colonna occorre modificare il file controller/catalog/category.php (ad esempio, se voglio modificare la tabella delle categorie) e sempre per esempio se si vuole aggiungere la colonna descrizione delle categorie:

 $this->data['column_description'] = $this->language->get('column_description');

Integrare una nuova entità e le conseguenti relazioni[modifica]

Rispetto a questo modello, dobbiamo associare lo Store alla Company anziché al Manufacturer. Occorre rimuovere la tabella di collegamento n:m di Manufacturer to Store e al suo posto implementare la relazione Company to Store e tutto il codice PHP. Forse è più immediato modificare il codice per ottenere la nuova relazione.

1) Creare una nuova entità Company (che per noi è Azienda Ospedaliera, ULSS, IOV) sulla falsariga di un'altra entità senza dipendenze (cioè senza chiavi esterne, ad esempio Manufacturer)

2) Creare la tabella Store_to_Company.

Per iniziare:

  • da admin/model/catalog/manufacturer.php creo company.php
  • da admin/controller/catalog/manufacturer.php creo company.php

Per le views:

  • admin/view/template/catalog/manufacturer_form.php => admin/view/template/catalog/company_form.php
  • admin/view/template/catalog/manufacturer_list.php => admin/view/template/catalog/company_list.php

dopo queste modifiche (ovviamente previe modifiche DB) non vedo le companies tra le voci del catalogo. How to?

Aggiungere una voce ai menu[modifica]

Occorre mettere mano alla tabella Layout,

Poi occorre innanzitutto aggiungere l'etichetta al file:

 admin/language/italian/common/header.php

nell'esempio in cui aggiungiamo le aziende:

 $_['text_company']           = 'Aziende';

Poi al file di template della view:

 admin/view/template/common/header.tpl

la riga

 $_['text_company']           = 'Aziende';

e al controller

 admin/controller/common/header.tpl

la riga

 $this->data['text_company'] = $this->language->get('text_company');


A questo punto compare l'etichetta, ma dobbiamo ancora definire l'URL a cui deve puntare:

Per modifcare anche l'URL del menu occorre aggiungere una entry in

 admin/controller/common/header.php 

e aggiungere una riga del tipo:

 $this->data['company'] = $this->url->link('catalog/company', 'token=' . $this->session->data['token'], 'SSL');

Per la definizione delle etichette dei singoli layout (form, elenco etc) di ciascuna entità conviene partire da un file già funzionante, ad esempio:

 admin/language/italian/catalog/manufacturer.php => admin/language/italian/catalog/company.php

Il link invia al controllore giusto ma ho un problema di permessi (Permesso Negato!): bisogna modificare qualcos'altro.

Questa qualcos'altro mi introduce alla gestione dei permessi negli oggetti OpenCart.

Come OpenCart gestisce l'accesso ai singoli oggetti del modello[modifica]

L'accesso ai singoli script è regolato dalla tabella user_group che contiene due gruppi:

  • Top Administrator
  • Demonstration

Ciascun gruppo ha un campo permission che contiene una stringa serializzata in cui è scritto l'elenco delle azioni seguito dall'elenco dei metodi collegati a tale azione. Ne riporto un estratto:

 a:2:{s:6:"access";a:125:{i:0;s:17:"catalog/attribute";i:1;s:23:"catalog/attribute_group";i:2;s:16:"catalog/category";i:3;s:16:"catalog/download";i:4;s:19:"catalog/information";
 i:5;s:20:"catalog/manufacturer";i:6;s:14:"catalog/option";i:7;s:15:"catalog/product";i:8;s:14:"catalog/review";i:9;s:18:"common/filemanager"; ... }
 s:6:"modify";a:125:{i:0;s:17:"catalog/attribute";i:1;s:23:"catalog/attribute_group";i:2;s:16:"catalog/category";i:3;s:16:"catalog/download";
 i:4;s:19:"catalog/information";i:5;s:20:"catalog/manufacturer";i:6;s:14:"catalog/option"; ... }

Per concedere i permessi all'uso dei metodi si devono aggiungere due entry, una nella sezione access e una nella sezione modify:

 i:124;s:15:"catalog/company";

dove

  • i:124 è il progressivo dell'entry;
  • s:15 è la lunghezza della stringa della entry;
  • "catalog/company" è la stringa della entry.

Questa modifica va fatta sia nella stringa serializzata che rappresenta la sezione "access" che nella stringa "modify".

Va anche aggiornato il numero di entry nella stringa all'inizio delle due sezioni (da 124 a 125, perché il conteggio parte da 0).

Fatto questo, basta fare refresh e oplà tutto funzia!

Per arrivare alla soluzione ho dovuto cercare su google "Unexpected end of serialized data" (l'errore che mi dava OpenCart) e poi visitare questo forum. Utilizzando l'editor esadecimale mi sono accorto che la serializzazione conteneva due entry "access" e "modify": occorreva aggiornarle tutte e due, mentre erroneamente aggiornavo il contatore della prima entry e l'elenco della seconda!

Modifica dell'interfaccia PHP/HTML[modifica]

Modifico

 /admin/controller/catalog/company.php

in cui modifico

  • getList(), allineando i campi di "$this->data['companys'][] = array(" con i campi della tabella company ;
  • getForm(), aggiungendo i campi di tipo
 $this->data['entry_address'] = $this->language->get('entry_address');

e aggiungendo anche

 if (isset($this->request->post['address'])) {
   $this->data['address'] = $this->request->post['address'];
 } elseif (isset($company_info)) {
   $this->data['address'] = $company_info['address'];
 } else {
   $this->data['address'] = ;
 }

per ogni campo che devo aggiungere.

Modifico

 /admin/view/template/catalog/company_form.php

per modificare i campi della form.

Modifico

 /admin/model/catalog

per aggiornare i campi della tabella (aggiungere i nuovi, togliere i vecchi o modificare quelli esistenti). Se serve un campo di tipo file esterno (tipo le immagini) se si parte da company è già mezzo lavoro fatto.

Relazioni uno a molti[modifica]

Nella company c'è una relazione uno-a-molti che rappresenta i magazzini di una azienda (possono essere da uno in su). Nel controller, i magazzini vengono caricati con una istruzione del tipo:

 $this->load->model('setting/store');
 $this->data['stores'] = $this->model_setting_store->getStores();
 if (isset($this->request->post['company_store'])) {
    $this->data['company_store'] = $this->request->post['company_store'];
 } elseif (isset($company_info)) {
    $this->data['company_store'] = $this->model_catalog_company->getCompanyStores($this->request->get['company_id']);
 } else {
    $this->data['company_store'] = array(0);
 }      


Quindi per la relazione uno a molti vanno realizzati

  • un metodo nel model e uno nel controller che legge gli stores legati alla company ($this->model_catalog_company->getCompanyStores)
  • un metodo nel model e uno nel controller che legge tutti gli stores.

Questo per ogni relazione di tipo 1:n.

Come realizzare una combo in una form[modifica]

Leggere il file che si trova su questo percorso

 catalog/attribute


Sua Maestà il Controller[modifica]

I dati che vengono visualizzati nelle form vengono caricati dal Controller interrogando il Model. All'interno del controller che controlla una form, i dai vengono caricati in istruzioni tipo questa:

 $this->data['product'] 

Esporre una nuova colonna in una tabella HTML[modifica]

Occorre modificare tre cose:

1) il model, se necessario esplicitando nella query la nuova colonna da esporre:

 /admin/model/catalog/category.php

linea 105: modifico la query:

SELECT 
  c.*, 
  cd.description as description <--------- nuova colonna da esporre
  FROM " . DB_PREFIX . "category c 
  LEFT JOIN " . DB_PREFIX . "category_description cd <--------- condizione di join
    ON (c.category_id = cd.category_id) 
WHERE c.parent_id = '" . (int)$parent_id . "' 
  AND cd.language_id = '" . (int)$this->config->get('config_language_id') . "' 
ORDER BY c.company_id, c.sort_order, cd.name ASC";

Poi occorre caricare nell'arraY i dati letti: stesso file linea 122:

 foreach ($query->rows as $result) 
 {
   $category_data[] = array(
     'category_id' => $result['category_id'],
     'name'        => $this->getPath($result['category_id'], $this->config->get('config_language_id')),
     'description' => $result['description'],
     'company_id'  => $result['company_id'],  <--------- nuova colonna da esporre
     'status'      => $result['status'],      
     'sort_order'  => $result['sort_order']
   );
 }

2) il Controller:, nel preparare i dati da passare alla view viene inzializzato un secondo array,

 /admin/controller/catalog/category.php

linea 105

 $this->data['categories'][] = array(
   'category_id' => $result['category_id'],
   'name'        => $result['name'],
   'description' => $result['description'],
   'company_id'  => $result['company_id'], <--------- nuova colonna da esporre
   'sort_order'  => $result['sort_order'],
   'selected'    => isset($this->request->post['selected']) && in_array($result['category_id'], $this->request->post['selected']),
   'action'      => $action
 );

alla linea 118 occorre passare alla view anche l'intestazione (i18n) della colonna:

 $this->data['column_company'] = $this->language->get('column_company');

3) per ultimo la view:

 /admin/view/template/catalog/category_list.tpl

linea 27 aggiungo un table data per l'intestazione:

  <td class="left"><?php echo $column_company; ?></td>

linea 53 aggiungo un table data per esporre il dato:

  <td class="left"><?php echo $category['company_id']; ?></td>


4) Ora occorre definire il valore i18n dell'etichetta:

 /admin/language/italian/catalog/category.php

Linea 13

 $_['column_company']         = 'Azienda';

Modalità multi store[modifica]

[betaingegneria]

Differenziare i cataloghi a seconda dell'azienda[modifica]

Interfaccia amministrazione > Moduli > (ad esempio) Ultimi arrivi >

  • Limite = 3
  • Layout = AOP

e per la seconda azienda

  • Limite = 5
  • Layout = ULSS

In questo modo vengono visualizzati due set distinti, con gli id prodotto coerenti con lo store!!