Magentoの手順

Magentoは、オンラインストア管理システムです。 Alexaによると、Magentoは2013年2月に世界で最も人気のあるオンラインストア管理システムです。



現在、すべてのeコマースソリューションの中で、Magentoを好みます。





このトピックに関する多くの記事がインターネット上にありますが、このセクションはまだハブで埋められているので、この分野での私の知識を共有しようとします。



Magentoでのモジュールの開発は、ローカル(接続時にモジュールを投稿する予定の場合はコミュニティ)で行う必要があります。

したがって、基本モジュールは次のもので構成されます。





モジュールのロードは非常に簡単です。Magentoは、まずデータベース、セッション、キャッシュなどの設定でapp / etc / local.xmlをロードし、次にapp / etc / modules / * 。Xmlからモジュールのブートストラップをロードし、 <の依存関係に従ってソートしますdepend>app / code / * / * / * / etc / config.xmlをロードし、すべてのXMLを1つのグローバルXMLにマージし、app / etc / local.xmlをグローバルXMLに再度ロードして、local.xmlからデータが失われないようにします。



本質的に、Magentoでのすべての開発のポイントは、カーネルモジュール(または他のモジュール)のソースコードを最小限に干渉することです。このため、Magentoにはいくつかのアプローチがあります。

1)そして、おそらく最も基本的なイベント。 既存の機能を追加/変更する必要がある場合、ほとんどの場合、イベントのインターセプトで十分です。

2)クラスを書き換える

3)ローカルオーバーライド



イベント


Magentoのイベントは、既存の機能を変更する際の最も正しいアプローチです。 独自の機能を開発するときは、イベントを使用することを忘れないでください。特に、それほど難しくないため、
Mage::dispatchEvent('namespace_module_something', array('model' => $this, 'something' => $that))
      
      





さらに、イベントをインターセプトする場合:

 // app/code/local/Namespace/Module/Observer.php public function someName(Varien_Event_Observer $observer) { $model = $observer->getModel(); // getData('model') $something = $observer->getSomething(); // getData('something') }
      
      





インターセプト自体の定義は、 イベントノードのconfig.xmlで説明されてます。

 <config> <global> <events> <namespace_module_something> <observers> <some_name> <class>namespace_module/observer</class> <method>someName</method> </some_name> </observers> </namespace_module_something> </events> </global> </config>
      
      





また、イベントをグローバルにインターセプトすることは必ずしも必要ではないため、グローバルなイベントに加えて、イベントをフロントエンド/ adminhtml / crontabに書き込むことができます



書き換えクラス


モデル、ヘルパー、およびブロックは、コード内のほぼすべての場所でファクトリメソッドを通じて呼び出されます。



これらすべてのメソッドは、それぞれMage_Core_Model_ConfigのgetModelClassName / getHelperClassName / getBlockClassNameを使用します

すべてのメソッドの最初のパラメーターは、モデル/ヘルパー/ブロックのエイリアスです:たとえば、カタログ/製品

クラス名を直接使用することもできますが、これは当てはまりません。 書き換えシステムは完全に終了します-新しいNamespace_Module_Model_Something()と基本的に同じです-設定でこのクラスをオーバーライドすることはできません。そのため、モジュールで直接クラス名を使用しないようにしてください。

 fgetcsv($handle, 0, Namespace_Module_Model_Something::DELIMITER, Namespace_Module_Model_Something::ENCLOSURE, Namespace_Module_Model_Something::ESCAPE )
      
      





実際、モジュールのすべてのユーザーに、指定されたDELIMITER / ENCLOSURE / ESCAPEのみを使用するように強制します。 このような問題は、たとえば、数バージョン前にはMage_ImportExportモジュールにあり、同様の問題がコード内にまだあることがあります。

したがって、構成ファイルを検討してください。



 <config> <modules> <Namespace_Module> </Namespace_Module> </modules> <global> <models> <namespace_module> <class>Namespace_Module_Model</class> </namespace_module> </models> <helpers> <namespace_module> <class>Namespace_Module_Helper</class> </namespace_module> </helpers> <blocks> <namespace_module> <class>Namespace_Module_Block</class> </namespace_module> </blocks> </global> </config>
      
      





モデル、ヘルパー、ブロックはnamespace_moduleエイリアスの下で利用可能になると述べています。

したがって、Namespace_Module_Model_Modelnameに到達する必要がある場合は、Mage :: getModel( 'namespace_module / modelname')(またはシングルトンが必要な場合はMage :: getSingleton)を使用するだけです。 状況はブロックとヘルパーで同じですが、追加されるのは1つだけです。Mage:: helper( 'namespace_module')はメインモジュールヘルパーを呼び出します:Namespace_Module_Helper_Data

また、ブロックとコントローラーは変換関数を呼び出すときにこのヘルパーを使用するため($ this-> __( "Somestring"))、ヘルパーはMage_Core_Helper_Abstractから継承する必要があります。

書き換えの場合は、次を示すだけです。

 ... <models> <catalog> <rewrite> <product>Namespace_Module_Model_Product</product> </rewrite> </catalog> </models> ...
      
      





モデル(ブロック、ヘルパー)ごとに、書き換えを指定する必要があります。 上記のXMLでは、製品モデルをNamespace_Module_Model_Productに再定義しているため、Mage :: getModel( 'catalog / product')は絶対にNamespace_Module_Model_Productを返します。



ローカルオーバーライド


ファイルのエラーを修正する可能性がない場合にのみ必要です。たとえば、Abstractクラスにエラーがあり、どのような方法でも再定義できない場合(特に、この抽象クラスが他の多数のクラスで使用される場合)。

デフォルトでは、 include_path = app / code / local; アプリ/コード/コミュニティ; アプリ/コード/コア; libので、コミュニティまたはコアクラスでエラーが発生した場合、ローカルのみでファイルと同じ場所にコピーできます。たとえば、local / Mage / Catalog / Model / Abstract.phpの場合、ファイルはコアの代わりにローカルからダウンロードされます。

もちろん、最善の方法ではありません Magentoを更新する場合、ファイルを更新する必要があります(問題が修正されていない場合)が、特に最適化に関しては、生存権があります。



実用化




タスク:注文のフィールド「is_exported」を追加し、管理パネルの注文リストに表示します。

まず、ブートストラップを作成します。

app / etc / modules / Easy_Interfacing.xml

 <?xml version="1.0"?> <config> <modules> <Easy_Interfacing> <active>true</active> <codePool>local</codePool> <depends> <Mage_Sales/> </depends> </Easy_Interfacing> </modules> </config>
      
      





Mage_Salesモジュールによって作成されたテーブルの構造を変更するため、依存関係でMage_Salesを設定する必要があります。 これをインストールしないと、既存のMagentoではすべて問題なく動作しますが、最初から展開した場合、最初にスクリプトを起動するとsales_flat_orderテーブルがないためインストールスクリプトが「落ちる」可能性があります。

アプリ/コード/ローカル/簡単/インターフェース/ etc / config.xml

 <?xml version="1.0"?> <config> <modules> <Easy_Interfacing> <version>0.0.1</version> </Easy_Interfacing> </modules> <global> <resources> <easy_interfacing_setup> <setup> <module>Easy_Interfacing</module> <class>Mage_Sales_Model_Resource_Setup</class> </setup> </easy_interfacing_setup> </resources> <helpers> <easy_interfacing> <class>Easy_Interfacing_Helper</class> </easy_interfacing> </helpers> <blocks> <easy_interfacing> <class>Easy_Interfacing_Block</class> </easy_interfacing> </blocks> </global> </config>
      
      





リソースノードでは、モジュールにインストールスクリプトがあり、Mage_Sales_Model_Resource_Setupクラスになることが基本的に示されています。

アプリの作成/コード/ローカル/簡単/インターフェース/ sql / easy_interfacing_setup / install-0.0.1.php

 /* @var $this Mage_Sales_Model_Resource_Setup */ $this->addAttribute('order', 'is_exported', array('type' => 'int', 'grid' => true));
      
      





ここで、順序テーブルにint属性を追加します。grid=> trueは、この属性でグリッドテーブルを更新する必要があることも示します。 フィールド名に大文字を使用しないことが重要です-ゲッターとセッターはそれらを正しく使用できません-(get)setSomeValueは(get)setData( 'some_value')のみと同等ですが、(get)setData( 'SomeValue')とは同等ではありません



当初、注文はEAVパターンで実装されていましたが、EAVの特性により、1つの注文を記録するために、1つのオブジェクトを複数の子オブジェクトで1ダースのテーブルに合計5万個のテーブルで書き込み、1つの注文のみを記録するので、パフォーマンスの観点からは不利です。それらに関連するもの(請求書、配送、割り当て、住所)は、重複したグリッドテーブルを使用するフラットテーブルです。

DDLメソッドを使用することをお勧めします 新しく作成したテーブルにのみ$ this-> run($ sql)を使用しても安全です。runメソッドでALTER TABLEを使用してもZendテーブルのキャッシュはクリアされず、フィールドを保存しない理由を誤解して長時間「スタック」する可能性があります

ここで、注文リストの管理パネルを少し変更してみましょう。

コミュニティモジュールでよくある間違い-注文リストのJOIN-グリッドテーブルにデータを書き込むだけでなく、Mage_Adminhtml_Block_Sales_Order_Gridブロックをオーバーライドすることにより、データを 'sales / order_grid_collection'コレクションに添付します。 :データが既にグリッドテーブルに書き込まれている場合、そこに1つ以上のフィールドを追加するだけではどうですか?

そのため、ブロックMage_Adminhtml_Block_Sales_Order_Gridを再定義します。 彼のエイリアスはadminhtml / sales_order_gridです:

 .... <blocks> <adminhtml> <rewrite> <sales_order_grid>Easy_Interfacing_Block_Adminhtml_Sales_Order_Grid</sales_order_grid> </rewrite> </adminhtml> </blocks> ....
      
      





ブロック名の先頭にAdminhtmlを追加したことに注意してください-ブロックを管理者やフロントと区別する方が便利です-結局、Sales_Order_GridはSalesではなくAdminhtmlモジュールにあり、sales / order_historyも再定義する必要がある場合は、ディレクトリにブロックが表示されます/ Grid.phpの隣の注文もHistory.phpであり、混乱を招きます。



ファイルアプリ/コード/ローカル/イージー/インターフェース/ブロック/セールス/オーダー/Grid.phpを作成します。

 <?php class Easy_Interfacing_Block_Adminhtml_Sales_Order_Grid extends Mage_Adminhtml_Block_Sales_Order_Grid { protected function _prepareColumns() { parent::_prepareColumns(); $options = array( null => $this->helper('eav')->__('No'), 1 => $this->helper('eav')->__('Yes'), ); $this->addColumnAfter( 'is_exported', array( 'header' => $this->__('Exported'), 'index' => 'is_exported', 'type' => 'options', 'width' => '70px', 'options' => $options ), 'status' ); $this->sortColumnsByOrder(); } }
      
      





簡単です。ステータスの後に、エクスポートされた列をグリッドに追加しました。 type = optionsであるため、オプションを配列id => valueの形式で指定する必要があります。

eav / entity_attribute_source_booleanを直接使用することはできません。この場合のように、No = 0であり、NULLではないためです。



この機能をテストするには、単純なコンソールスクリプトを使用します。

 <?php require 'app/Mage.php'; Mage::app('admin'); Mage::getModel('sales/order')->load(194)->setIsExported(1)->save();
      
      





is_exported属性は両方のテーブルに存在するため、注文オブジェクトを保存するとき、または、Mage_Sales_Model_Abstract :: _ afterCommitCallbackメソッドは注文のリソースモデルからGridRecordsを更新し、モデルからグリッドテーブルにフィールドデータをコピーします。



これで、イベントを通じて関心のあるエクスポートを実装するだけで十分です(モデルの説明を追加することを忘れないでください)。

 <config> <global> ... <models> <easy_interfacing> <class>Easy_Interfacing_Model</class> </easy_interfacing> </models> <events> <sales_order_save_commit_after> <observers> <easy_interfacing_order> <class>easy_interfacing/observer</class> <method>exportOrder</method> </easy_interfacing_order> </observers> </sales_order_save_commit_after> </events> ... </global>
      
      





イベントの名前を調べる方法は? それは非常に簡単です-app / Mage.phpを開き、dispatchEventメソッドを見つけてログを追加します(もちろん、一時的に):

 public static function dispatchEvent($name, array $data = array()) { Mage::log($name, LOG_DEBUG, 'events.log', true);
      
      





次に、必要なアクションを実行し、トリガーされたイベントのリストを参照します(ファイル "<MAGENTO_ROOT> /var/log/events.log")。 AfterCommitは、最良の選択です。 これは、注文オブジェクトが正常に保存されたときに発生するイベントです。 これをafterSaveにすると、モジュールのいずれかが例外をスローした場合、モジュールが既にデータをエクスポートしている可能性がありますが、これは間違っています。 トランザクション全体がキャンセルされ、注文は元の状態に戻ります(INSERT INTOロールバックの場合、存在しない場合もあります)。



クラスObserver アプリ/コード/ローカル/イージー/インターフェース/モデル/Observer.php自体を作成します。

 <?php class Easy_Interfacing_Model_Observer { public function exportOrder(Varien_Event_Observer $observer) { $order = $observer->getOrder(); /* @var $order Mage_Sales_Model_Order */ if (!$order->getIsExported() && $order->getState() == Mage_Sales_Model_Order::STATE_PROCESSING) { try { Mage::getModel('easy_interfacing/order')->export($order); $order->setIsExported(1)->addStatusHistoryComment('Exported order'); } catch (Exception $ex) { $order->addStatusHistoryComment('Failed exporting order: ' . $ex->getMessage())->save(); } } } }
      
      





複雑なことはなく、注文が既にエクスポートされているかどうか、およびエクスポートできるかどうかを簡単に確認します。エクスポートに適しているのはPROCESSING状態の注文のみです。これらは有料注文です。



そして最後に、easy_interfacing / order app / code / local / Easy / Interfaces / Model / Order.php

 <?php class Easy_Interfacing_Model_Order { public function export(Mage_Sales_Model_Order $order) { Mage::throwException('Not implemented'); } }
      
      







エクスポート機能をテストするには、テストスクリプトを次のように変更します。

 <?php require 'app/Mage.php'; Mage::app('admin'); Mage::getModel('sales/order')->load(188)->setDummyValue(1)->save();
      
      







順序を保存するには、存在しない値を設定する必要があります-_origData = _dataの場合、モデルはMagentoに保存されないため、beforeSave / afterSave / afterCommitイベントは発生しません。 このスクリプトを実行すると、注文のコメント履歴に新しいコメントが表示されます。

22/07/2014 6:43:43 AM|Processing

Customer Not Notified

Failed exporting order: Not implemented







最終的なconfig.xml
 <?xml version="1.0"?> <config> <modules> <Easy_Interfacing> <version>0.0.1</version> </Easy_Interfacing> </modules> <global> <resources> <easy_interfacing_setup> <setup> <module>Easy_Interfacing</module> <class>Mage_Sales_Model_Resource_Setup</class> </setup> </easy_interfacing_setup> </resources> <models> <easy_interfacing> <class>Easy_Interfacing_Model</class> </easy_interfacing> </models> <helpers> <easy_interfacing> <class>Easy_Interfacing_Helper</class> </easy_interfacing> </helpers> <blocks> <easy_interfacing> <class>Easy_Interfacing_Block</class> </easy_interfacing> <adminhtml> <rewrite> <sales_order_grid>Easy_Interfacing_Block_Adminhtml_Sales_Order_Grid</sales_order_grid> </rewrite> </adminhtml> </blocks> <events> <sales_order_save_commit_after> <observers> <easy_interfacing_order> <class>easy_interfacing/observer</class> <method>exportOrder</method> </easy_interfacing_order> </observers> </sales_order_save_commit_after> </events> </global> </config>
      
      









これは、注文を作成するときにMagentoにエクスポートするためのこのような簡単な方法で、スケルトンが〜12キロバイトで実装される方法です。 あとは、必要なエクスポートアルゴリズムをEasy_Interfacing_Model_Orderモデルに実装するだけです。



All Articles