The existing multi-store works fine on the front-end where there are multiple stores For example, $this->config->get('config_name') will return the name of the store being viewed, however, $this->config->get('usps_status') will only return the value for the default store, since that is the only store any extension is configured for.
This can be a problem if different extension settings on different stores, for example: different shipping methods, or only allow certain payment gateways, etc.
Example 1
You want to use different shipping methods for different stores, but don't want the others showing up as options in the checkout. Or, you want to use the same shipping method in different geographical zones (or the same zone) at different rates on different stores.
Example 2
You want one store to use PayPal Standard as its only payment gateway, another store to use Google Checkout.
Example 3
One store uses gift vouchers, coupons and reward points, another store doesn't.
None of these are possible the way that multistore is currently implemented in OpenCart.
In the Administration
Extension settings are added to the "setting" table (using PayPal Standard as an example) by way of:
Code: Select all
$this->model_setting_setting->editSetting('pp_standard', $this->request->post);
$group -- the configuration group that is being edited. In the case of a store, this is 'config'. For an extension, it is the name of the extension, eg. 'pp_standard'.editSetting($group, $data, $store_id = 0)
$data -- the data array being posted through to the function. For a store, these are things like: 'config_name', 'config_url', 'config_currency', etc. For an extension, these would the things like the extension's staus, sort order, geographical zone, fee, tax class, etc.
$store_id -- the store ID that the setting is applied to. A default of "0" is used if no store ID is passed through. This is only implemented for store settings.
Since no store ID is passed through when editing extension settings, these settings are only ever configured for the default store ($store_id = 0), and are treated as "universal".
These "universal" settings are then retrieved from the settings table with $this->config->get(), for example:
both in the back-end and in the front-end.$this->config->get('pp_standard_status');
or
$this->config->get('fedex_geo_zone_id');
This works fine in the front-end, with $this->config->get('config_name') returning the name of the store being viewed, but in the back-end, $this->config->get('config_name') will only ever return the name of the default store.
While $this->config->get('some_setting') works fine on the front-end where there are multiple stores, the back-end is a different matter, simply because there is only one back-end. Subsequently, $this->config->get('some_setting') will always return the setting for the default store.
The Concept
When a new store is added, a call is made to the addStore() function in the model from the controller (admin/controller/setting/store.php):
Code: Select all
$store_id = $this->model_setting_store->addStore($this->request->post);
Code: Select all
$this->model_setting_setting->editSetting('config', $this->request->post, $store_id);
Code: Select all
$this->model_setting_setting->editSetting('config', $this->request->post, $this->request->get['store_id'];
Code: Select all
$store_info = $this->model_setting_setting->getSetting('config', $this->request->get['store_id']);
Code: Select all
if (isset($this->request->post['config_name'])) {
$data['config_name'] = $this->request->post['config_name'];
} elseif (isset($store_info['config_name'])) {
$data['config_name'] = $store_info['config_name'];
} else {
$data['config_name'] = '';
}
For true multistore, we need to GET the store ID and pass it through to the editSetting() function when the extension settings are edited, by way of:
Where $extension is then name of the extension.$this->model_setting_setting->editSetting($extension, $this->request->post, $this->request->get['store_id']);
This can be done by redirecting to a "select store" routine where the store can be selected and a GET value containing the store ID can be added to the URL. Of course, this process would be invisible in a single store operation.
This principle can be applied to all extensions: shipping, payment, order totals and product feeds (even modules - although not necessary for these).
Once we have the store ID, this can be passed on as a GET value when editing individual extensions (shipping methods, payment gateways, etc.). Subsequently, when saving the settings, we can then use (using PayPal Standard as an example):
Code: Select all
$this->model_setting_setting->editSetting('pp_standard', $this->request->post, $this->request->get['store_id']);
Extension settings can then be retrieved with something like:
Code: Select all
$fedex_settings = $this->model_setting_setting->getSetting('fedex', $this->request->get['store_id']);
Code: Select all
if (isset($this->request->post['fedex_geo_zone_id'])) {
$data['fedex_geo_zone_id'] = $this->request->post['fedex_geo_zone_id'];
} else {
$data['fedex_geo_zone_id'] = $this->config->get('fedex_geo_zone_id');
}
Code: Select all
if (isset($this->request->post['fedex_geo_zone_id'])) {
$data['fedex_geo_zone_id'] = $this->request->post['fedex_geo_zone_id'];
} elseif (isset($fedex_settings) && $fedex_settings['fedex_geo_zone_id']) {
$data['fedex_geo_zone_id'] = $fedex_settings['fedex_geo_zone_id'];
} else {
$data['fedex_geo_zone_id'] = '';
}
See Demos @ Fido-X. This is a multi-store demo.
On the front-end, you will find an extensions list displaying all the extensions, their status, geo zone and cost or rate (if any) for each store.
You can view the back-end by logging in to the admin with username/password pair of demo/demo. Once logged in, you can view the shipping, payment, order totals and feeds extensions. Most of those installed have modify permissions allowed so that you can change the settings and see the change reflected in the front-end in the extension list on the home page of each store.