First of all I want to say that the address_type
is not used for customer addresses. It is used only for quote and order addresses, so there is no need to use that in order to flag your own address type.
if you need to retrieve only your store finder addresses I have an idea, but later on that.
First, you will need to create a new module to handle your new address type in order not to change the core code.
Let's call this module StackExchange_Storefinder
.
You will need the following files:
app/etc/modules/StackExchange_Storefinder.xml
- the declaration file:
<?xml version="1.0"?>
<config>
<modules>
<StackExchange_Storefinder>
<codePool>local</codePool>
<active>true</active>
<depends>
<Mage_Customer />
<Mage_Adminhtml />
</depends>
</StackExchange_Storefinder>
</modules>
</config>
app/code/local/StackExchange_Storefinder/etc/config.xml
- the configuration file
<?xml version="1.0"?>
<config>
<modules>
<StackExchange_Storefinder>
<version>1.0.0</version>
</StackExchange_Storefinder>
</modules>
<global>
<resources>
<stackexchange_storefinder_setup>
<setup>
<module>StackExchange_Storefinder</module>
<class>Mage_Customer_Model_Resource_Setup</class>
</setup>
</stackexchange_storefinder_setup>
</resources>
<models>
<stackexchange_storefinder>
<class>StackExchange_Storefinder_Model</class>
</stackexchange_storefinder>
</models>
<helpers>
<stackexchange_storefinder>
<class>StackExchange_Storefinder_Helper</class>
</stackexchange_storefinder>
</helpers>
<blocks>
<stackexchange_storefinder>
<class>StackExchange_Storefinder_Block</class>
</stackexchange_storefinder>
<adminhtml>
<rewrite>
<customer_edit_tab_addresses>Stackexchange_Storefinder_Block_Adminhtml_Customer_Edit_Tab_Addresses</customer_edit_tab_addresses>
</rewrite>
</adminhtml>
</blocks>
</global>
<adminhtml>
<events>
<adminhtml_customer_prepare_save>
<observers>
<stackexchange_storefinder>
<class>stackexchange_storefinder/adminhtml_observer</class>
<method>checkStoreFinderAddress</method>
</stackexchange_storefinder>
</observers>
</adminhtml_customer_prepare_save>
</events>
</adminhtml>
</config>
app/code/local/StackExchange/Storefinder/sql/stackexchange_storefinder_setup/install-1.0.0.php
- the install script that adds a new customer attribute to store the store finder address id (just like billing and shipping).
<?php
/** @var Mage_Customer_Model_Resource_Setup $this */
$this->addAttribute(
'customer',
'default_store_finder_id',
array(
'type' => 'int',
'label' => 'Default Store Finder Address',
'input' => 'text',
'backend' => 'stackexchange_storefinder/customer_attribute_backend_storefinder',
'required' => false,
'sort_order' => 82,
'visible' => false,
)
);
app/code/local/StackExchange/Storefinder/Model/Customer/Attribute/Backend/Storefinder.php
- the backend model of the store finder attribute:
<?php
class StackExchange_Storefinder_Model_Customer_Attribute_Backend_Storefinder extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract
{
public function beforeSave($object)
{
$helper = $this->_getHelper();
$defaultStoreFinder = $helper->getDefaultStorefinder($object);
if (is_null($defaultStoreFinder)) {
$object->setData('default_store_finder_id', null);
}
}
public function afterSave($object)
{
if ($defaultStoreFinder = $this->_getHelper()->getDefaultStorefinder($object))
{
$addressId = false;
/**
* post_index set in customer save action for address
* this is $_POST array index for address
*/
foreach ($object->getAddresses() as $address) {
if ($address->getPostIndex() == $defaultStoreFinder) {
$addressId = $address->getId();
}
}
if ($addressId) {
$object->setDefaultStoreFinderId($addressId);
$this->getAttribute()->getEntity()
->saveAttribute($object, $this->getAttribute()->getAttributeCode());
}
}
}
/**
* @return StackExchange_Storefinder_Helper_Address
*/
protected function _getHelper()
{
return Mage::helper('stackexchange_storefinder/address');
}
}
app/code/local/StackExchange/Storefinder/Helper/Address.php
- a helper so you won't rewrite the customer model:
<?php
class StackExchange_Storefinder_Helper_Address extends Mage_Core_Helper_Abstract
{
public function getDefaultStorefinder(Mage_Customer_Model_Customer $customer)
{
return $customer->getData('default_store_finder_id');
}
public function getDefaultStorefinderAddress(Mage_Customer_Model_Customer $customer)
{
return $customer->getPrimaryAddress($customer->getData('default_store_finder_id'));
}
}
app/code/local/StackExchange/Storefinder/Block/Adminhtml/Customer/Edit/Tab/Addresses.php
- rewrite the admin address block to add the new radio button
<?php
class Stackexchange_Storefinder_Block_Adminhtml_Customer_Edit_Tab_Addresses
extends Mage_Adminhtml_Block_Customer_Edit_Tab_Addresses
{
public function __construct()
{
parent::__construct();
$this->setTemplate('stackexchange_storefinder/tab/addresses.phtml');
}
}
app/design/adminhtml/default/default/template/stackexchange_storefinder/tab/addresses.phtml
- the new address admin template. Same as the default one but with one extra radio button. I wrote this in a gist because it's too big to put in here
app/code/local/StackExchange/Storefinder/Model/Adminhtml/Observer.php
- an observer for the customer save event so the new address flag will be recognized:
<?php
class StackExchange_Storefinder_Model_Adminhtml_Observer
{
public function checkStoreFinderAddress($observer)
{
/** @var Mage_Customer_Model_Customer $customer */
$customer = $observer->getCustomer();
/** @var Mage_Core_Controller_Request_Http $request */
$request = $observer->getRequest();
$data = $request->getPost();
if (isset($data['account']['default_storefinder'])) {
$customer->setData('default_store_finder_id', $data['account']['default_storefinder']);
}
}
}
app/code/local/StackExchange/Storefinder/Helper/Data.php
- the module default helper. Not sure this is needed.
<?php
class StackExchange_Storefinder_Helper_Data extends Mage_Core_Helper_Abstract
{
}
When you are done clear the cache.
Now, in order to get all addresses that have this new flag set, you first need to get all the customers and get the value of $customer->getDefaultStoreFinderId()
and then get the address collection where the id is in the values collected above.
But from my point of view, these is a totally different question. First check if you can add a third address type by using the code above.
[EDIT]
To get all the addresses that are marked as store finder you need to do something like this:
$customerCollection = Mage::getModel('customer/customer')->getCollection()
->addAttributeToSelect('default_store_finder_id');
$addressIds = array();
foreach ($customerCollection as $customer) {
$addressId = $customer->getDefaultStoreFinderId();
if ($addressId) {
$addressIds[] = $addressId;
}
}
if (count($addressIds)) {
$addresses = Mage::getModel('customer/address')->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('entity_id', array('in' => $addressIds));
//do what you need with $addresses.
}
Well, the first step you should check for the model in question is: Is there a Repository Service Contract? If so, use that, because Service Contracts are bound to semantic versioning and will continue to behave like they should up until Magento 3.x comes out. Needless to say, when you create your own modules with models that require persistence, you should also write the repository for that.
public function __construct(
\Magento\Catalog\Api\ProductRepositoryInterface $productRepository
) {
$this->productRepository = $productRepository;
/** @var \Magento\Catalog\Api\Data\ProductInterface $product */
$this->productRepository->save($product);
}
If there is no repository present, use the resource model. Note that resource models don't contain a state: they're utilizing persistence for their 'regular' models. Therefore you are not required to include them using a factory:
public function __construct(
\Magento\Catalog\Model\ResourceModel\Product $productResource,
\Magento\Catalog\Model\ProductFactory $productFactory
) {
$this->productResource = $productResource;
$this->productFactory = $productFactory;
...
/** @var \Magento\Catalog\Api\Data\ProductInterface $product */
$product = $this->productFactory->create();
$this->productResource->save($product);
}
"So what benefit brings a Service Contract / Repository over a Resource Model?" you might ask. Well, in theory a Resource Model should only be responsible for the persistence of a Data Model, whereas a Repository also takes into account the additional tasks involved upon saving an entity. Think about updating indexes, creating relations with other entities, etc. This is the theory, although in real life these lines tend to blur quite often. But it's good for yourself to keep this in mind.
You should not use the models' direct save()
, load()
, etc. -methods. They are deprecated because it's semantic incorrect. Think about it in a SOLID way:
- (Data) Models should only be responsible for containing data.
- Resource Models should be responsible for the persistence of such data.
- Repositories should be responsible for the communication inside and outside the module for persistence actions.
And it's that last point that makes a difference: when communicating with other modules, in an ideal world one should never have to rely on that modules' internal persistent logic (or any of it's public methods for that matter, but that's another discussion), but only use that functionality that is provided by the modules' Service Contracts.
In Conclusion
To answer your question: in order of preference. The correct way to load a model is:
- If there is a Repository, load it using the Repository.
- Only if there is no Repository, use the Resource Model (in combination with a factory).
Best Answer
And my question is... Why you don't create an attribute for the IMEI. Then change the grid on the adminhtml to show IMEI on it.
With it, you could display it where you want easily.
In addition, you don't have to make a lot of code, and its more functionality for cron jobs or imports.