多嚿魚教室

Opencart優化技巧

In Opencart Admin panel, this is an Autocomplete function for entry of product attributes. When user types in something into the text field of product attribute, a word box of defined product attributes will appear below the field to let user click that wanted to save the typing time.

However, if the user does not click the word box and type a complete word by oneself, the Opencart system will not save the product attribute data the user types. In fact, the Autocomplete function wanted to prevent user inputting undefined product attributes. In other words, the system does not record what the user types but just detects which item the user clicks in the word box. The Autocomplete function is user-unfriendly, especially there are many product attributes defined.

To simplify the entry of product attributes, I have programmed a vQmod plug-in to change the text field into drop-down list so that the user does not need to type anything.

If vQmod have been installed in your Opencart system,
click the below fish and save the XML script into the directory [vqmod/xml].


<p>
&#60;!--<br />
Make sure that you have properly installed Opencart vQmod.<br />
Copy this page of script.<br />
Save as a .xml file of utf-8 encoding without BOM into the directory [vqmod/xml].<br />
Name the file as you like.<br />
--&gt;</p>
<pre contenteditable="true">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;modification&gt;
 &lt;id&gt;Display attribute choices of products in drop-down list&lt;/id&gt;
 &lt;version&gt;1.1.0&lt;/version&gt;
 &lt;author&gt;Flexidigi Solution Ltd.&lt;/author&gt;
 &lt;file name=&quot;admin/model/catalog/product.php&quot;&gt;
  &lt;operation&gt;
   &lt;search position=&quot;after&quot;&gt;&lt;![CDATA[class ModelCatalogProduct extends Model {]]&gt;&lt;/search&gt;
   &lt;add&gt;&lt;![CDATA[
 public function get_all_attribute_names() {
  $query = $this-&gt;db-&gt;query(&quot;SELECT attribute_group_id, attribute_id , name FROM &quot; . DB_PREFIX . &quot;attribute_description NATURAL JOIN &quot; . DB_PREFIX . &quot;attribute WHERE language_id = '&quot; . (int)$this-&gt;config-&gt;get('config_language_id') . &quot;' order by attribute_group_id DESC&quot;);
  
  return $query-&gt;rows;
 }
 public function get_all_attribute_group_names() {
  $query = $this-&gt;db-&gt;query(&quot;SELECT attribute_group_id , name FROM &quot; . DB_PREFIX . &quot;attribute_group_description WHERE language_id = '&quot; . (int)$this-&gt;config-&gt;get('config_language_id') . &quot;' order by attribute_group_id DESC&quot;);
  
  return $query-&gt;rows;
 }  
   ]]&gt;&lt;/add&gt;
  &lt;/operation&gt;
 &lt;/file&gt;
 &lt;file name=&quot;admin/controller/catalog/product.php&quot;&gt;
  &lt;operation&gt;
   &lt;search position=&quot;after&quot;&gt;&lt;![CDATA[private function getForm() {]]&gt;&lt;/search&gt;
   &lt;add&gt;&lt;![CDATA[
     $this-&gt;data['attribute_names'] = array();
  $results = $this-&gt;model_catalog_product-&gt;get_all_attribute_names();
  foreach ($results as $result) {
   $this-&gt;data['attribute_names'][] = array(
    'name' =&gt; $result['name'],
    'attribute_id' =&gt; $result['attribute_id'],
    'attribute_group_id' =&gt; $result['attribute_group_id']);
  }
  $this-&gt;data['attribute_group_names'] = array();
  $results = $this-&gt;model_catalog_product-&gt;get_all_attribute_group_names();
  foreach ($results as $result) {
   $this-&gt;data['attribute_group_names'][] = array(
    'name' =&gt; $result['name'],
    'attribute_group_id' =&gt; $result['attribute_group_id']);
  }
   ]]&gt;&lt;/add&gt;
  &lt;/operation&gt;
 &lt;/file&gt;
 &lt;file name=&quot;admin/view/template/catalog/product_form.tpl&quot;&gt;
 &lt;!-- Show all existing Product attributes --&gt;
  &lt;operation&gt;
   &lt;search position=&quot;before&quot; offset=&quot;1&quot;&gt;&lt;![CDATA[&lt;div id=&quot;tab-option&quot;&gt;]]&gt;&lt;/search&gt;
   &lt;add&gt;&lt;![CDATA[
   &lt;aside&gt;
   &lt;header style=&quot;margin-right: 3em;float:left;font-size:1.5em&quot;&gt;&lt;?php echo $entry_attribute; ?&gt;&lt;/header&gt;
            &lt;?php foreach ($attribute_group_names as $all_attribute_group){ ?&gt;
            &lt;details style=&quot;border:#6FF solid thin; margin-right: 3em; padding:1em;float:left;&quot;&gt;
            &lt;summary style=&quot;text-decoration:underline;&quot;&gt;&lt;?php print($all_attribute_group['name']); ?&gt;&lt;/summary&gt;
        &lt;ul style=&quot;list-style-type:none;&quot; title=&quot;&lt;?php echo $all_attribute_group['name']; ?&gt;&quot;&gt;
        &lt;?php foreach ($attribute_names as $all_attribute){ 
   if($all_attribute['attribute_group_id']==$all_attribute_group['attribute_group_id']) { ?&gt;
         &lt;li&gt;&lt;?php print($all_attribute['name']); ?&gt;&lt;/li&gt;
        &lt;?php } } ?&gt;
        &lt;/ul&gt;
        &lt;/details&gt;
        &lt;?php } ?&gt;
        &lt;/aside&gt;
   ]]&gt;&lt;/add&gt;
  &lt;/operation&gt;
  &lt;operation&gt;
   &lt;search position=&quot;replace&quot;&gt;&lt;![CDATA[&lt;input type=&quot;text&quot; name=&quot;product_attribute[' + attribute_row + '][name]&quot;]]&gt;&lt;/search&gt;
   &lt;add&gt;&lt;![CDATA[';
   html += '&lt;select title=&quot;Product attributes&quot; name=&quot;product_attribute[' + attribute_row + '][name]&quot; onchange=&quot;document.getElementsByName(\'product_attribute[' + attribute_row + '][attribute_id]\')[0].value=this.options[this.selectedIndex].value;&quot;&gt;';
   html += '&lt;option value=&quot;&quot; selected=&quot;selected&quot;&gt;&lt;?php echo $text_select; ?&gt;&lt;/option&gt;';
  &lt;?php foreach ($attribute_group_names as $all_attribute_group){ ?&gt;
  html += '&lt;optgroup label=&quot;&lt;?php echo $all_attribute_group['name']; ?&gt;&quot;&gt;';
  &lt;?php foreach ($attribute_names as $all_attribute){ 
   if($all_attribute['attribute_group_id']==$all_attribute_group['attribute_group_id']) { ?&gt;
   html += '&lt;option value=&quot;&lt;?php echo $all_attribute['attribute_id']; ?&gt;&quot;&gt;&lt;?php print($all_attribute['name']); ?&gt;&lt;/option&gt;';
  &lt;?php } } ?&gt;
  html += '&lt;/optgroup&gt;';
  &lt;?php } ?&gt;
 html += '    &lt;/select&gt;';
   html += '&lt;input style=&quot;visibility:hidden&quot; list=&quot;attribute_list&quot; type=&quot;text&quot; name=&quot;product_attribute[' + attribute_row + '][name]&quot;]]&gt;&lt;/add&gt;
  &lt;/operation&gt;
 &lt;/file&gt;
&lt;/modification&gt;
</pre>
唔識英文?
自己查字典啦!

我在Opencart後台用CKEditor編輯文章,想插入圖片,於是用CKEditor上傳圖片,但失敗了。到底是甚麼一回事?

以下是錯誤的圖片上傳示範:

  1. 在CKEditor按「影像」,「影像屬性」視窗會彈出。
  2. 按「上傳」標籤,再按「瀏覽...」。
  3. 挑選一個檔案,按「開啟舊檔」。
  4. 按「上傳至伺服器」。
  5. 出錯了!沒有圖片上傳到Opencart伺服器。
上載唔到圖片
有乜叉用!

CKEditor本身不是用來上傳檔案,要插入圖片就要配合檔案上傳工具(file manager)。CKFinder是CKEditor的官方搭檔,專門配合CKEditor上傳圖片。
CKFinder file manager

不過,Opencart並沒有安裝CKFinder,因為Opencart本身已經有檔案上傳工具“Image Manager”。


Finding Solution

正確的圖片上傳方法:

  1. 在CKEditor按「影像」,「影像屬性」視窗會彈出。
  2. 按「影像資訊」標籤,再「瀏覽伺服器端」,“Image Manager”視窗會彈出。
  3. 按“Upload”,檔案瀏覽器會彈出。
  4. 挑選需要的圖片檔案,按「開啟舊檔」。
  5. 上傳完成後,所需圖片會出現在“Image Manager”,雙擊圖片。
  6. 在「影像資訊」輸入有關設定,按「確定」完成圖片插入。

原來Opencart已經有圖片上載工具。但是既然CKEditor的「上傳」是無效,怎樣防止其他人再用?

CKEditor的「上傳」標籤十分誤導用家,既然是失效的,就應該隱藏掉。

隱藏「上傳」標籤的步驟:

  1. 到安裝了Opencart的伺服器,開啟路徑[admin/view/javascript/ckeditor/plugins/image/dialogs]。
  2. 編輯[image.js],搜尋並刪除以下程式碼,然後儲存檔案:
    {id:'Upload',hidden:true,filebrowser:'uploadButton',label:b.lang.image.upload,elements:[{type:'file',id:'upload',label:b.lang.image.btnUpload,style:'height:40px',size:38},{type:'fileButton',id:'uploadButton',filebrowser:'info:txtUrl',label:b.lang.image.btnUpload,'for':['Upload','upload']}]},
    
  3. 在CKEditor按「影像」,「影像屬性」視窗會彈出。「上傳」標籤不見了。

Opencart後台內置了CKEditor,讓用家以所見即所得方式編輯文本,例如 product 和 category 的 description。

不過,Opencart和CKEditor的版本更新並不同步,所以用家要自行安裝新版本的CKEditor到Opencart。


為什麼要使用新版本的CKEditor?
怎樣安裝新版本的CKEditor到Opencart?

HTML的最新版本——HTML5在網絡越來越普及,而新版本的CKEditor已支援HTML5的新標籤,包括<article><section><header>等等。另外,新版本有糾正錯誤和新增功能。

做乜叉嘢?


以下方法適用於Opencart v1.5.1.3

更新步驟:

  1. CKEditor官網下載最新版本的CKEditor,並解壓縮出來。
  2. 打開ckeditor文件夾,將多餘的“_samples”和“_source”文件夾刪除。
  3. 到安裝了Opencart的伺服器,開啟[admin/view/javascript/ckeditor]路徑,下載“config.js”和“contents.css”,儲存到剛才解壓縮出來的ckeditor文件夾,覆蓋掉原有的檔案。
  4. 將新版本的ckeditor文件夾上傳到伺服器,覆蓋掉舊版本的ckeditor文件夾即可。