Showing posts with label prestashop. Show all posts
Showing posts with label prestashop. Show all posts

Prestashop 的back office tab 筆記 - part 6

此篇是對應筆記3的1.5+版本, 在1.5之前要新增一個form 真係話難唔難但係話易又真係唔算易的, 因為入面包括了很多的html code 及頁面上的設定, 但來到1.5 就真係變得容易了很多呢...

在1.5, 我地只要overwrite renderForm 這個function 更可以了,

public function renderForm(){ 
 $prod = new Product($this->last_pid);
  
 $this->fields_form = array(
  'legend' => array(
   'title' => $this->l('Fast Get Discount Setting')    
  ),
  'input' => array(
   array(
    'type' => 'text',
    'label' => $this->l('Product name').":",
    'disabled' => true,
    'name' => 'product_name'    
   ),
   array(
    'type' => 'hidden',     
    'name' => 'id_product'
   ),
   array(
    'type' => 'text',
    'label' => $this->l('No. of Sold').":",
    'name' => 'position',
    'size' => 25,
    'required' => true,
    'hint' => sprintf($this->l('Allowed number only'))
   ),
   array(
    'type' => 'text',
    'label' => $this->l('Reduction').":",
    'name' => 'reduction',
    'size' => 25,
    'required' => true,
    'hint' => sprintf($this->l('Input the Amount/Percentage you want to discount.').$this->l('Allowed number only'))     
   ),
   array(
    'type' => 'select',
    'label' => $this->l('Reduction Type').":",
    'name' => 'reduction_type',
    'options' => array(      
     'query' => array(array('reduction_type' => 'amount', 'name' => $this->l('Amount')), array('reduction_type' => 'percentage', 'name' => $this->l('Percentage'))),
     'id' => 'reduction_type',
     'name' => 'name'      
    )
   ),
   array(
    'type' => 'date',
    'label' => $this->l('From').":",
    'name' => 'from',
    'size' => 20,
    'class' => 'timepicker',
    'desc' => sprintf($this->l('Leave blank to clear the time'))
   ),
   array(
    'type' => 'date',
    'label' => $this->l('To').":",
    'name' => 'to',
    'size' => 20,
    'class' => 'timepicker',
    'desc' => sprintf($this->l('Leave blank to clear the time'))
   ),    
  ),
  'submit' => array(
   'title' => $this->l('Save'),
   'class' => 'button'
  )
 );
 
 $this->fields_value = array(
  'product_name' => $prod->name[$this->context->language->id]
 );
   
 return parent::renderForm();
}

可以看到在1.5裏,系統已經提供了內置的function讓我地只需要設定變數fields_form就能建立好張form

利用fields_form['legend']可以設定form legend 的部份...
'legend' => array(
 'title' => $this->l('Fast Get Discount Setting')    
 ),
設定後的效果

fields_form['input'] 讓我們設定能提供的變數, 先看看以下的頁面


它其實是由下面的code所建立成
array(
 'type' => 'text',
 'label' => $this->l('Product name').":",
 'disabled' => true,
 'name' => 'product_name'    
),
array(
 'type' => 'hidden',     
 'name' => 'id_product'
),
array(
 'type' => 'text',
 'label' => $this->l('No. of Sold').":",
 'name' => 'position',
 'size' => 25,
 'required' => true,
 'hint' => sprintf($this->l('Allowed number only'))
),
  • 第一個item我地設定disable為true後, 頁面上這個field 就會變成為唯讀
  • 第二個item,我地設定它為hidden,所以在頁面上是看不到它的存在
  • 第三個item,我地設定required為true,所以可以看到*在後面,而且也因為設定了hint,所以在滑鼠移上去時會出現提示信息
fields_form['submit']可以讓我們更改title bar入面的儲存按鈕
'submit' => array(
 'title' => $this->l('Save'),
 'class' => 'button'
)
由於第一個item(product_name),不是直接由database中取出來的(頁面所設定的className), 所以它的內容要透過fields_value來設定
$this->fields_value = array(
 'product_name' => $prod->name[$this->context->language->id]
);
最後,當然要call 番parent的renderform, 如果唔係可是會出現白頁的情況呢!
return parent::renderForm();


Prestashop 的back office tab 筆記 - Part 5

之前講到prestashop升級至1.5.x後它的backoffice 改動很太,所以基本上admin tab 也是要重新寫過的呢,如果看看它的change log, 基本上v1.5.0.1把之前的admintab 也換了是controller 呢,所以寫法上也會有一點點的出入,所以之前的筆記23是不太適用於1.5+呢

好首先最主要的改動是我地由之前extends AdminTab變成為AdminController
class AdminFastGetDiscountSettingControllerCore extends AdminController{
...
}

它的constructor 基本上是類似的, 不過之前所用的fieldsDisplay就換成為fields_list
參考example:
public function __construct()
{  
 $this->table = 'product_fast_get_discount';
 $this->className = 'FastGetDiscount';
 $this->lang = false;
 
 $this->identifier = "id_pfgd";
 
 $this->addRowAction('edit');
 $this->addRowAction('delete');
 
 $this->bulk_actions = array('delete' => array('text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?')));
  
 $this->fields_list = array(
  'id_pfgd' => array(
   'title' => $this->l('ID'),
   'align' => 'center',
   'width' => 25
  ),  
  'product_name' => array(
   'title' => $this->l('Name'),
   'align' => 'left',    
   'orderby' => false,
   'filter' => false,
   'search' => false
  ),
  'position' => array(
   'title' => $this->l('No. of Sold'),
   'align' => 'center',
   'width' => 90
  ),
  'reduction' => array(
   'title' => $this->l('Reduction'),
   'align' => 'right',
   'width' => 100
  )
 );   

 parent::__construct();  
}

除此之外之前是利用edit/delete的變數來設定每一行可以做的action, 但在controller的叫法則改變了
// 之前在AdminTab 時用$this->edit=true;
$this->addRowAction('edit');
// 之前在AdminTab 時用$this->delete=true;
$this->addRowAction('delete');

也可以利用bulk_action來設定批量的移除
$this->bulk_actions = array(
 'delete' => array(
  'text' => $this->l('Delete selected'), 
  'confirm' => $this->l('Delete selected items?'))
 );
加入批量的效果


Prestashop 的back office tab 筆記 - Part 4

由於prestashop 升級了1.5.x, 而且佢把入面基本的core 也作出了不少的改動,就連最基本的object class 也改了寫法呢, 當然舊有的寫法還是可以support的, 但新的寫法感覺上不錯而且也更易明,所以就記下新的寫法吧!可以在這裏回憶一下舊的寫法

如果嘗試睇一下ObjectModel這個class就會發現了很多東西也是 @deprecated 1.5.0呢, 其中包括了很多在筆記一所提到的變數呢
/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['table'] property instead
 */
protected $table;

/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['primary'] property instead
 */
protected $identifier;

/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['fields'] property instead
 */
protected $fieldsRequired = array();

/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['fields'] property instead
 */
protected $fieldsSize = array();

/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['fields'] property instead
 */
protected $fieldsValidate = array();

/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['fields'] property instead
 */
protected $fieldsRequiredLang = array();

/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['fields'] property instead
 */
protected $fieldsSizeLang = array();

/**
 * @deprecated 1.5.0 This property shouldn't be overloaded anymore in class, use static $definition['fields'] property instead
 */
protected $fieldsValidateLang = array();

從入面可以睇到好多的變數也改變成在definition中設,那就看看我重新寫的object class
public static $definition = array(
 'table' => 'product_fast_get_discount',
 'primary' => 'id_pfgd',
 'fields' => array(
  'id_product' =>  array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true),  
  'position' =>  array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt', 'required' => true),     
  'reduction' =>   array('type' => self::TYPE_FLOAT, 'validate' => 'isPrice', 'required' => true),
  'reduction_type' => array('type' => self::TYPE_STRING, 'validate' => 'isReductionType', 'required' => true),
  'from' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false),
  'to' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false)  
 )
);
新的Object class, 只要設定好definition這個static 變數就可以了,因為入面的'table', 'primary', 'fields' 就已經包含了第筆記一中提到的那些設定..

除此之外,在筆記一中提到要建立的getFieldsgetTranslationsFieldsChild來到1.5+後也不用自己寫了

所以雖然1.5+的確作出了不少的改動,但感覺上在object class 的一part是改得不錯,因為整體來說佢係更加易明同整潔了呢


Prestashop 的back office tab 筆記 - part 3

上一篇筆記成功地建立了一個最基本的檢視頁面,這一次就為admin tab 加入最基本的新增功能吧 (由於prestashop 最近升級了版本, 筆記part 1 至 3, 只適用於1.4.9)

sample code:
 function displayForm(){   
    global $currentIndex;
    $defaultLanguage = intval(Configuration::get('PS_LANG_DEFAULT'));
    $languages = Language::getLanguages();
   
    $obj = $this->loadObject(true);
   
    echo '
        <script type="text/javascript">
            id_language = Number('.$defaultLanguage.');
        </script>';

    echo '
        <form action="' . $currentIndex . '&submitAdd' .  $this->table . '=1&token=' . $this->token . '" method="post" class="width3">
            ' . ($obj->id ? '<input type="hidden" name="id_' . $this->table . '" value="' . $obj->id . '" />' : '').'
            <fieldset><legend><img src="../img/admin/profiles.png" />' . $this->l('Admin Test') . '</legend>
            <label>'.$this->l('Name:').' </label>
            <div class="margin-form">';       
   
    foreach ( $languages as $language )
        echo '
            <div id="test_' . $language['id_lang'|'id_lang'] . '" style="display: ' . ($language['id_lang'|'id_lang'] == $defaultLanguage ? 'block' : 'none') . '; float: left;">
                <input size="33" type="text" name="name_' . $language['id_lang'|'id_lang'] . '" value="' . htmlentities( $this->getFieldValue( $obj, 'name', intval( $language['id_lang'|'id_lang'] ) ), ENT_COMPAT, 'UTF-8' ) . '" /><sup>*</sup>
                <span class="hint" name="help_box">'.$this->l('Allowed characters: letters, spaces and').' ().-<span class="hint-pointer">&nbsp;</span></span>
            </div>';
   
    $this->displayFlags( $languages, $defaultLanguage, 'test', 'test' );
   
    echo '<div class="clear"></div></div>';                 
    echo '<label>'.$this->l('Description:').' </label>
            <div class="margin-form">
            <textarea name="description" rows="10" cols="100">'.htmlentities( $this->getFieldValue( $obj, 'description'), ENT_COMPAT, 'UTF-8' ).'</textarea>';
    echo '<div class="clear"></div></div>
            <div class="margin-form">
            <input type="submit" value="'.$this->l('Save').'" name="submitAdd'.$this->table.'" class="button" />
            </div>
            <div class="small"><sup>*</sup> '.$this->l('Required field').'</div>
        </fieldset>
        </form> ';       
}

要在按下新增或修改時出現form, 我地需要overwrite displayForm, 係入面設定我地需要的form elements, 而form 入面最重要的當然係張form 的action link同入面d parameters, 因為perstashop 原本的class 只會認指定了的名同parameter, 如果你的唔同了而你又沒有為自己新定的action加上code, 它可是不會作出對應的動作呢,所以基本上這一個form 的tag 是不用作出什麼改變的

echo '<form action="' . $currentIndex . '&submitAdd' .  $this->table . '=1&token=' . $this->token . '" method="post" class="width3">

而其他的則只需好似平時普通的html form 一樣,如果想為到張form 加回由db的值就要用上
// fields 為非多語言support時
$this->getFieldValue( $obj, 'description')

// fields 為多語言support時
$this->getFieldValue( $obj, 'name', intval( $language['id_lang'|'id_lang'] ) )

以上就可以為到prestashop 設定最basic的一個admin tab,不過由於prestashop出了新版而且也把admin的一部份也改成了controller,寫法上也有些改變,所以這筆記只可以應用在1.4.9版本中呢!


Prestashop 的back office tab 筆記 - part 2

上一份筆記寫下了db object 後, 這一篇的筆記就來掛上back-office 的頁面作出設定吧...

好首先就建立一個最基本的admin page, :
<?php
    class AdminTest extends AdminTab {
        public function __construct() {
            $this->table = 'test';
            $this->className = 'Test';
            $this->lang = true;
            $this->edit = true;  
            $this->delete = true;
            $this->fieldsDisplay = array(
              'id_test' => array(
                'title' => $this->l('ID'),
                'align' => 'center',
                'width' => 25),
              'name' => array(
                'title' => $this->l('Name'),
                'width' => 200),
              'description' => array(
                    'title' => $this->l('description'),
                    'width' => 510)          
            );

            $this->identifier = 'id_test';

            parent::__construct();
        }
  }
?> 

以上的code 掛上back-office後能出現以下的頁面
頁面
adminpage 也和db object class相類似, 也是需要去extends 一個基本的class - AdminTab, 之後就可以overwrite 它的 __construct來為版面作出設定..

$this->table = 'test';
$this->className = 'test';
$this->lang = true;

這裏的table是指你要為DB裏那一個table作出設定,所以就於入上次所建立的`test`, 同樣地是不用加上prefix的, 而className 則是這個table所對應的db object class, 所以填上上次所建立的Test, 由於我們當中有Field 是支援多語言的, 所以這個lang就要設定成true了..
注意: 如果沒有了_lang 的table, 但把lang設定為true 是會出現bad sql query 的錯誤!

我們可以設定不同的action, 只要把對應的變數設定係true 便可了

設定好需要顯示的fields
$this->fieldsDisplay = array(
  'id_test' => array(
    'title' => $this->l('ID'),
    'align' => 'center',
    'width' => 25),
  'name' => array(
    'title' => $this->l('Name'),
    'width' => 200),
  'description' => array(
    'title' => $this->l('description'),
    'width' => 510)           
); 

設定後的頁面
再set 番個table key 入去個identifier變數裏. $this->identifier = 'id_test';
最後因為你overwrite 了__construct , 所以當然不要忘記call 番parent 呢...
parent::__construct();

忘記了call 番parent 的__construct 可是會出現error 的呢..
這樣就可以有最基本的admin page了, 不過這時按下add new/edit 只會出現白頁,如何為頁面加入簡單的form 就留待下一篇筆記先再寫了


Prestashop 的back office tab 筆記 - Part 1

最近因為一些原因接觸了一下prestashop 這一個free open-source 的shopping cart platform, 其實睇番原來年多前也有接觸過它,不過當時就沒有什麼深入研判過它的code同寫法, 今次終於睇完它的developer guide 同試左寫下d modules同admin tab, 基本上其實真係唔難去用同寫的....


基本上佢official site上面個developer guide 的前半部是寫得不錯的,一步一步來, 倒是它的後面部份講如何去寫一個back-office tab時就好似簡單了一點, 得個example 完全冇解釋呢, 好在自己摸下摸下總算摸得明白了,有了個太約知道可以點去寫,所以就係度寫低一d筆記以免將來會忘記了...

好,首先是database的部份吧,由於個系統是support多個語言的,所以當然就試下寫可以作出多個語言的設定吧,官方的sample 唔知點解個db part 不是一個多個語言的,但係到左寫個admin page 時就係多個語言,導致個page 行來行去都係行唔到,真係吹脹了, 搞左我好耐先發現問題的原因@@

以下就是我的db:
CREATE TABLE `ps_test` (
  `id_test` int(11) NOT NULL AUTO_INCREMENT,
  `description` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id_test`)
) ENGINE=InnoDB AUTO_INCREMENT=1;

--ps_test_lang 是用來放多個語言的字串
CREATE TABLE `ps_test_lang` (
  `id_test` int(11) DEFAULT NULL, -- 這個是ps_test的primary key
  `id_lang` int(11) DEFAULT NULL, -- 這個是不同語言的key
  `name` varchar(32) DEFAULT NULL -- 不同語言的field
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

和官網的不同,其中多了一個ps_test_lang 是用來放多個語這的字串, 這裏`_lang` 是指定了的surfix, 而它的prefix就是另一個table(ps_test).由於只是得一個variable (name) 設定成可以支援多個語言,所以這table就只得`name`,這一個field

沒有了這個_lang 的table, 但在後期(admin page)設置multi-lang 的setting時是會出現db error 的呢

接著就可以睇下個class了
<?php
class Test extends ObjectModel
{
  /** @var string Name */

  public $id;
  public $name;
  public $description;

  protected $fieldsRequired = array('description');
  protected $fieldsSize = array('description' => 510);
  protected $fieldsValidate = array( 'description' => 'isGenericName');

  protected $fieldsRequiredLang = array('name');
  protected $fieldsSizeLang = array('name' => 64);
  protected $fieldsValidateLang = array('name' => 'isGenericName');

  protected $table = 'test';
  protected $identifier = 'id_test';

  public function getFields()
  {
        parent::validateFields();       
       
        $fields['description'] = pSQL($this->description);
               
        return $fields;
  }

  public function getTranslationsFieldsChild()
    {           
        if (!parent::validateFieldsLang())
            return false;
        return parent::getTranslationsFields(array('name'));
    }
}
?> 

首先這一個db object class 是要extends ObjectModel 的,接著就是object 的field 了, 這裏我地有3個variable - id, name 同description, 而其中的name 是support 多個語言的
<?php
class Test extends ObjectModel
{
  /** @var string Name */

  public $id;
  public $name;
  public $description;

之後就可以設定那些field 的必須的, 這裡我分別設定description及name 都是必須的, 而其中 name 是一個多個語言的field.
protected $fieldsRequired = array('description');
  protected $fieldsSize = array('description' => 510);
  protected $fieldsValidate = array( 'description' => 'isGenericName');

  protected $fieldsRequiredLang = array('name');
  protected $fieldsSizeLang = array('name' => 64);
  protected $fieldsValidateLang = array('name' => 'isGenericName');  

設定好這個class是會連去db 那一個table同它的key
protected $table = 'test'; 
protected $identifier = 'id_test';

注意在這裏的table name 是 `test` 而不是 `ps_test`, 因為`ps_`這個prefix 會在系統運行sql時加上的,所以這裏就可以免了

加入getFields的function, 這裏是不用把name 這個多個語言的field 放入去的, 只要把所有非多個語言field放上去就可以了, 多個語這的field是透過getTranslationsFieldsChild來處理的...
function getFields()
{
    parent::validateFields();

    $fields['description'] = pSQL($this->description);

    return $fields;
}

加上getTranslationsFieldsChild來support 多個語言
public function getTranslationsFieldsChild()
{
    if (!parent::validateFieldsLang())
        return false;
    return parent::getTranslationsFields(array('name'));
}  

如果是多於一個field是support 多語這的, 只要把它加進array入面就可以了 - parent::getTranslationsFields(array('name', 'field2'));
下一part 筆記將會是另一重要部分back-office tab 的掛上和設定了...