EAV database for Magento (1.9) in practice (frontend)

Under Magento it means the following:

  • entity table (defines entity)
  • attribute table (defines attribute, its type and other options, e.g. source model, type, input, label)
  • value table (it is separated according to types, partly because of indexability and searches, e.g. catalog_product_entity_int, catalog_product_entity_varchar etc.)

 

The attributes could be stored in the main table, couldn’t they?

In the EAV data model, while adding new attributes to the entities, there is no need to modify the original table. So too large tables can be avoided, thus the speed of queries will be faster, and also unnecessary data with lists will not appear, only those that we add to the collection.

Here, we are going to create a module, with both admin and frontend interfaces, using an EAV solution.

 

Having installed the online store on the server and after configuring it (base url, database name, database user stb.), and if everything shows right, we start the development.

 

For defining the module, we need to create an xml file named with the module’s name in the app/etc/modules directory. In our case it is Aion_Items.xml, the codePool is local, but it could also be placed in the community codePool.

 

The xml looks like this:

 

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

 

This is not yet finished. The module will not appear even after emptying the cache, not even in the module list in the admin panel.

Next we should create the module defined in the xml, within the directory that was set in the codePool. Here, in this case, it means the local directory (if it does not yet exist) under the app/code folder, and within it an Aion/Items directory is to be found.

So the final path in this case is: app/code/local/Aion/Items.

 

module_path

 

In the following steps to come, the general rules of module development are to be applied with some minor differences. If you have forgotten some details, it is completely acceptable to look up the content of Magento core modules for some help : )

Create the module config.xml file, step by step:

 

<?xml version="1.0" encoding="UTF-8" ?>
<config>
    <modules>
        <Aion_Items>
            <version>0.0.1</version>
        </Aion_Items>
    </modules>
</config>

 

Define the paths of the models and resource models, and also the entity table(s) for the module. Insert the following elements before the </config> node and right after the </modules> node:

 

<global>
    <models>
        <aion_items>
            <class>Aion_Items_Model</class>
            <resourceModel>aion_items_resource</resourceModel>
        </aion_items>
        <aion_items_resource>
            <class>Aion_Items_Model_Resource</class>
            <entities>
                <article>
                    <table>aion_items_article</table>
                </article>

 

We haven’t yet closed the <entities> node, we keep “staying with” it and define the other EAV data tables, type by type:

 

            <article_datetime>
                <table>aion_items_article_datetime</table>
            </article_datetime>
            <article_decimal>
                <table>aion_items_article_decimal</table>
            </article_decimal>
            <article_int>
                <table>aion_items_article_int</table>
            </article_int>
            <article_text>
                <table>aion_items_article_text</table>
            </article_text>
            <article_varchar>
                <table>aion_items_article_varchar</table>
            </article_varchar>
            <article_char>
                <table>aion_items_article_char</table>
            </article_char>
        </entities>
    </aion_items_resource>
</models>

 

Now we define the paths of helpers and blocks:

 

<helpers>
    <aion_items>
        <class>Aion_Items_Helper</class>
    </aion_items>
</helpers>
<blocks>
    <aion_items>
        <class>Aion_Items_Block</class>
    </aion_items>
</blocks>

 

Now, to have our tables created, we need to set the resources, which means defining the installer and database connection. It can be inserted below </blocks>, but it is important to have them on the same level.

 

        <resources>
            <aion_items_setup>
                <setup>
                    <module>Aion_Items</module>
                    <class>Aion_Items_Model_Resource_Setup</class>
                </setup>
            </aion_items_setup>
        </resources>
    </global>
</config>

 

As you can see, we have closed the nodes, next we will create the basic helper (it is very important (!), your module will not work without it) and the models. They need to be created in the location defined in the xml. The models are created in the Aion/Items/Model directory, while the helper in the Aion/Items/Helper directory.

 

The default helper belonging to the module is named Data in every case, the Mage::getHelper(‘aion_items’) tries to create this, which is equal to the Mage::getHelper(‘aion_items/data’) call.

Thus our helper has the class name Aion_Items_Helper_Data, and file name Data and is derived from the Mage_Core_Helper_Abstract class.

 

Let’s create the models and resource models.

We defined the article under <entities>, so let’s make it our model, let’s create the

  • Aion_Items_Model_Article
  • Aion_Items_Model_Resource_Article
  • Aion_Items_Model_Resource_Article_Collection classes.

 

Since we have chosen the EAV data model, we do not derive them from the usual Mage_Core_Model_Resource_Abstract and Mage_Core_Model_Resource_Db_Collection_Abstract classes, but, based on the order of the aforementioned elements, from the following classes:

  • Mage_Eav_Model_Entity_Abstract
  • Mage_Eav_Model_Entity_Collection_Abstract

There is still a small change in the resource model:

 

class Aion_Items_Model_Resource_Article extends Mage_Eav_Model_Entity_Abstract
{
const ENTITY = ‘aion_items_article’;

public function __construct()
{
$this->setType(self::ENTITY)
->setConnection(‘core_read’, ‘core_write’);
}
}

 

The first model was omitted from the list deliberately (Aion_Items_Model_Article). It is still derived from the Mage_Core_Model_Abstract class, so there is no change. When the models have been created, the installer class needs to be created. This has been defined in the basic configuration file of the module (Aion_Items_Model_Resource_Setup). Let’s create it in the appropriate location, with the following content:

 

class Aion_Items_Model_Resource_Setup extends Mage_Eav_Model_Entity_Setup
{
    public function getDefaultEntities()
    {
        $entityAttributes = array(
            Aion_Items_Model_Resource_Article::ENTITY => array(
                'entity_model' => 'aion_items/article',
                'attribute_model' => '',
                'table' => 'aion_items/article',
                'attributes' => array(
                    'name' => array(
                        'type' => 'varchar',
                        'label' => 'Name',
                        'input' => 'text',
                        'global' => 0,
                        //this set the attribute to store entity data separated to every store not globally
                        'visible' => true,
                        'required' => true,
                        'user_defined' => true,
                        'visible_on_front' => true
                    ),
                    'customer_id' => array(
                        'type' => 'integer',
                        'label' => 'Customer',
                        'input' => 'select',
                        'global' => 1,
                        'visible' => false,
                        'required' => true,
                        'user_defined' => true,
                        'visible_on_front' => false,
                        'source' => 'aion_items/article_attribute_source_customer'
                    ),
                ),
            )
        );

        return $entityAttributes;
    }
}

 

These attributes will be created for the entity type when the installer is run. There are other possibilities apart from the attribute options mentioned above, but since these are not different from the default values, there is no need to define them.

 

We can see it at the customer_id attribute that we included the source option, so we will need a source model. Create the Customer.php file in the defined location and with the defined name in the app/code/local/Aion/Items/Model/Article/Attribute/Source directory, with the following content:

 

class Aion_Items_Model_Article_Attribute_Source_Customer extends Mage_Eav_Model_Entity_Attribute_Source_Table
{
    public function getAllOptions()
    {
        if (!$this->_options) {
            $customers = Mage::getResourceModel('customer/customer_collection')
                ->addAttributeToSort('lastname', 'ASC')
                ->addAttributeToSort('firstname', 'ASC');
            foreach ($customers as $customer) {
                $name = [$customer->getFirstname(), $customer->getLastname()];
                $this->_options[] = ['value' => $customer->getId(), 'label' => join(' ', $name)];
            }
        }
        return $this->_options;
    }
}

 

In order to create our table, there is only the installer left to be created. It should be done in the directory defined in the <resources> node, within the sql located under our module.

Since in this case it is <aion_items_setup>, therefore the directory will be aion_items_setup as well.

 

We have given the version, in <version> node, earlier in the config.xml file of our module. This will be the version number of our installer. Now, create an install-0.0.1.php file in the app/code/local/Aion/Items/sql/aion_items_setup directory, with the following content:

 

try {
    $this->startSetup();
    $this->createEntityTables('aion_items/article');
    $this->addEntityType(Aion_Items_Model_Resource_Article::ENTITY, [
        'entity_model' => 'aion_items/article',
        'attribute_model' => '',
        'table' => 'aion_items/article',
        'increment_model' => '',
        'increment_per_store' => '0'
    ]);

    $this->installEntities();
    $this->endSetup();
} catch (Exception $e) {
    Mage::logException($e);
}

 

When done, the module is ready for install. But before running it, take a look at the directory and file structure:

 

files_in_module_1

 

 

In order to make our module’s installer run, empty cache in the admin panel under System – > Cache management. If the installer has been run successfully, we are to see the following tables apart from the basic tables in the database.

 

eav_tables

 

 

Not to miss a thing, switch on error log in the admin area before running the installer. Also, check the var/log directory whether they contain exception.log or system.log files. Additionally, we can see if the customer_id and name attributes have been created in the eav_attribute table with a descending order based on the attribute_id. We can also see, next to it in the entity_id field, what ID number has been given to the new entity type. You can make it visible by clicking on it.

All done right? Then let’s make a frontend page for our module to test if everything works fine. Insert the following code section under <global> node, but before </config> node:

 

<frontend>
    <routers>
        <aion_items>
            <use>standard</use>
            <args>
                <module>Aion_Items</module>
                <frontName>aionitems</frontName>
            </args>
        </aion_items>
    </routers>
</frontend>

 

For frontend display, we also need layout, controller, block and template files. Insert the layout file definition under the same <frontend> node:

 

<layout>
    <updates>
        <aion_items>
            <file>aion/items.xml</file>
        </aion_items>
    </updates>
</layout>

 

Next, create the layout xml file here: app/design/frontend/rwd/default/layout. It is important to always create the basic template files, belonging to our module, in the layout directory under default belonging to the theme, because in this case any later modifications will affect its duplicate (copy) and not the original file. The same applies to template files.

 

<?xml version="1.0"?>
<layout version="0.1.0">
    <aion_items_index_index translate="label">
        <label>Aion Items</label>
        <reference name="root">
            <action method="setTemplate"><template>page/1column.phtml</template></action>
        </reference>
        <reference name="content">
            <block type="aion_items/list" name="aion.items.list" as="aion_items_list" template="aion/items/index.phtml"/>
        </reference>
    </aion_items_index_index>
</layout>

 

Now let’s get to the template file and the block. We have indicated aion/items/index.phtml as the template file in the xml, thus we place the index.phtml file one level higher in the app/design/frontend/rwd/default/template/aion/items directory. Then we place a List.php file in the app/code/local/Acion/Items/Block directory with the following content:

 

class Aion_Items_Block_List extends Mage_Core_Block_Template
{
    /**
     * @return \Aion_Items_Model_Resource_Article_Collection
     * @throws \Mage_Core_Exception
     */
    public function getArticleCollection()
    {
        $articles = Mage::getModel('aion_items/article')->getCollection()
            ->addAttributeToSelect('*');

        return $articles;
    }
}

 

Now let’s return to the index.phtml template file and, temporarily, make its content the following:

 

/** @var Aion_Items_Block_List $this */
$articles = $this->getArticleCollection();
Zend_Debug::dump($articles->getData(),'articles');

 

To have the content of the collection displayed, we only need a controller. Create the IndexController.php file in the app/code/local/Aion/Items/controllers directory with the following content:

 

class Aion_Items_IndexController extends Mage_Core_Controller_Front_Action
{
    /**
     * @return $this
     */
    public function indexAction()
    {
        $this->loadLayout();
        $this->renderLayout();

        return $this;
    }
}

 

Next, empty cache again in the admin panel and call the url belonging to the module on frontend (in the example this is /aionitems/ which is equal to an /aionitems/index/index/ call. If everything was set right, the following (or something similar) should appear:

 

frontend_display

 

 

So far so good.

But in fact nothing is yet displayed, as no data is included in the table. To make our example look good, write a data installer to see if our attributes work fine.

In one of the previous images there was a data directory whose role is exactly this. Non-system related modifications can be carried out through this. Structurally, it is connected to the sql directory, therefore we need an aion_items_setup sub-directory within it.

There is one more difference in terms of operation compared to a “plain” installer script: the files located under such structure are searched by Magento with a data- prefix.

Create a data-upgrade-0.0.1-0.0.2.php file in the app/code/local/Aion/Items/data/aion_items_setup directory (as the install-0.0.1.php has already been run) and also create an upgrade-0.0.1-0.0.2.php file in the app/code/local/Aion/Items/sql/ directory. In the latter we only indicate what happens and where it happens. Thus the upgrade-0.0.1-0.0.2.php contains the following:

 

/** @var Aion_Items_Model_Resource_Setup $this */
try {
    $this->startSetup();
    //app\code\local\Aion\Items\data\aion_items_setup\data-upgrade-0.0.1-0.0.2.php
    $this->endSetup();
} catch (Exception $e) {
    Mage::logException($e);
}

 

The app/code/local/Aion/Items/data/aion_items_setup/data-upgrade-0.0.1-0.0.2.php includes the following:

 

/** @var Aion_Items_Model_Resource_Setup $this */
try {
    $defaultStoreId = Mage::app()->getDefaultStoreView()->getId();
    $attributeSet = Mage::getResourceModel('eav/entity_attribute_set_collection')
        ->addFieldToFilter(
            'entity_type_id',
            Mage::getModel('eav/entity')
                ->setType(Aion_Items_Model_Resource_Article::ENTITY)
                ->getTypeId()
        )->addFieldToFilter(
            'attribute_set_name',
            'Default'
        )->getFirstItem();
    $articles = [
        [
            'store_id' => $defaultStoreId,
            'name' => 'Article name 1',
            'attribute_set_id' => $attributeSet->getId(),
        ],
        [
            'store_id' => $defaultStoreId,
            'name' => 'Article name 2',
            'attribute_set_id' => $attributeSet->getId(),
        ]
    ];
    foreach ($articles as $article) {
        Mage::getModel('aion_items/article')->setData($article)->save();
    }
} catch (Exception $e) {
    Mage::logException($e);
}

 

We haven’t finished yet.

After updating, the new installer does not run, so, again, emptying cache is needed. Additionally, increase 0.0.1, in the config.xml file belonging to the module, under <version> node, to 0.0.2, and then update the page. If everything has been working OK, you’ll see this in the databse:

 

data_installed

 

 

In the aion_items_article_varchar table the names are seen separately associated to the different entities.

 

data_eav_installed

 

 

After updating, we see the following on frontend:

 

frontend_display_data

 

 

Summary

I think I’m not very much mistaken if I say that EAV is a very useful and sophisticated solution which is not needed in most of the cases.

Most mid and small range developments do not require such a structural build since they include more, interconnected tables originally.

It is recommended to make it clear beforehand what characteristics our database management will have and what kind of resources it may use in the future, as it is possible to store these data in a generated, cumulative “flat” table—just the same as Magento does it with data organized in the same structure.

It would be quite time consuming and costly to reorganize existing tables with complex structures and large numbers into an EAV structure.

 

567 replies
  1. Overreaction says:

    I’m curious to find out what blog platform you’re working with? I’m having some minor security issues with my latest site and I’d like to find something more risk-free. Do you have any solutions?

  2. bitcoin crash chart says:

    Very nice post. I just stumbled upon your weblog and wanted to say that I have really enjoyed browsing your blog posts. In any case I will be subscribing to your feed and I hope you write again very soon!

  3. average student debt usa says:

    I wanted to create you the very little remark to finally give thanks the moment again for your personal beautiful information you have shown in this article. It has been simply pretty open-handed of people like you to convey without restraint just what a few people could have supplied as an electronic book in order to make some profit for their own end, precisely seeing that you could have tried it in the event you desired. Those tips likewise acted as a good way to fully grasp most people have a similar fervor really like my very own to realize way more in respect of this matter. Certainly there are thousands of more fun times up front for folks who check out your blog.

  4. Kurt says:

    jungle scout alternative

    Every weekend i used to go to see this site, for the
    reason that i wish for enjoyment, as this this web site conations really fastidious funny data too.

  5. Slot Joker123 says:

    Hello, Neat post. There’s an issue along with your website in web explorer, would test this?K IE still is the market leader and a huge portion of people will leave out your great writing due to this problem.

  6. TikTok Views says:

    Hi there, just was alert to your blog via Google, and located that it is really informative. I’m going to watch out for brussels. I will be grateful in case you proceed this in future. Many people will likely be benefited from your writing. Cheers!

  7. sanchore college says:

    An interesting discussion is worth comment. I think that you should write more on this topic, it might not be a taboo subject but generally people are not enough to speak on such topics. To the next. Cheers

  8. turkish pillow covers says:

    Thanks for the good writeup. It actually used to be a leisure account it. Glance complicated to more brought agreeable from you! However, how could we be in contact?

  9. Tutos says:

    of course like your web-site but you have to check the spelling on several of your posts. Several of them are rife with spelling issues and I find it very bothersome to inform the truth on the other hand I’ll surely come again again.

  10. College says:

    I’ve been absent for some time, but now I remember why I used to love this web site. Thank you, I will try and check back more often. How frequently you update your site?

  11. Joker123 Net says:

    I appreciate, cause I found just what I was looking for. You have ended my 4 day long hunt! God Bless you man. Have a nice day. Bye

  12. comprar libid gel says:

    Pretty nice post. I just stumbled upon your blog and wanted to say that I have really enjoyed surfing around your weblog posts. After all I will be subscribing on your rss feed and I hope you write again soon!

  13. Login Joker388 says:

    whoah this blog is fantastic i love reading your posts. Keep up the great work! You understand, a lot of persons are hunting round for this information, you could help them greatly.

  14. job advertising site says:

    Hi, just required you to know I he added your site to my Google bookmarks due to your layout. But seriously, I believe your internet site has 1 in the freshest theme I??ve came across. It extremely helps make reading your blog significantly easier.

  15. สล็อต says:

    Do you have a spam problem on this website; I also am a blogger, and I was curious about your situation; many of us have developed some nice procedures and we are looking to swap methods with other folks, why not shoot me an e-mail if interested.

  16. https://vnz.bz/ says:

    An interesting discussion is worth comment. I think that you should write more on this topic, it might not be a taboo subject but generally people are not enough to speak on such topics. To the next. Cheers

  17. Games podcasts says:

    A person essentially help to make seriously posts I would state. This is the first time I frequented your website page and thus far? I surprised with the research you made to make this particular publish incredible. Wonderful job!

  18. 10-TOP-Google-Tipps says:

    Some really wonderful info , Glad I detected this. “Genuine goodness is threatening to those at the opposite end of the moral spectrum.” by Charles Spencer.

  19. sbobet says:

    A lot of whatever you state is supprisingly appropriate and that makes me ponder the reason why I had not looked at this in this light before. Your article really did switch the light on for me personally as far as this specific topic goes. Nevertheless there is one particular issue I am not necessarily too comfortable with so while I try to reconcile that with the actual core theme of the point, allow me observe what all the rest of the readers have to point out.Nicely done.

  20. slotxo says:

    Aw, this was a really nice post. In thought I would like to put in writing like this additionally – taking time and precise effort to make a very good article… however what can I say… I procrastinate alot and by no means seem to get one thing done.

  21. find out says:

    I will immediately snatch your rss feed as I can not to find your e-mail subscription link or e-newsletter service. Do you’ve any? Kindly permit me recognize in order that I may subscribe. Thanks.

  22. สล็อต says:

    An interesting discussion is worth comment. I think that you should write more on this topic, it might not be a taboo subject but generally people are not enough to speak on such topics. To the next. Cheers

  23. urus rental malaysia says:

    Great website. A lot of useful information here. I am sending it to several buddies ans additionally sharing in delicious. And certainly, thanks to your effort!

  24. seo specialist malaysia says:

    Pretty section of content. I just stumbled upon your site and in accession capital to assert that I get actually enjoyed account your blog posts. Any way I’ll be subscribing to your augment and even I achievement you access consistently fast.

  25. Louças, Pedras e Metais says:

    Hello There. I found your blog the usage of msn. This is an extremely neatly written article. I’ll be sure to bookmark it and return to learn more of your useful information. Thanks for the post. I’ll definitely comeback.

  26. Judi Slot says:

    Thanks, I’ve just been searching for info about this topic for a long time and yours is the greatest I’ve came upon so far. But, what in regards to the bottom line? Are you certain concerning the source?

  27. Auto Diagnosegeräte kaufen says:

    A powerful share, I just given this onto a colleague who was doing a little bit evaluation on this. And he in truth bought me breakfast because I found it for him.. smile. So let me reword that: Thnx for the deal with! But yeah Thnkx for spending the time to discuss this, I really feel strongly about it and love studying more on this topic. If possible, as you grow to be expertise, would you mind updating your blog with more particulars? It is extremely helpful for me. Massive thumb up for this blog put up!

  28. solar system malaysia says:

    I’ve been absent for some time, but now I remember why I used to love this website. Thanks, I will try and check back more often. How frequently you update your site?

  29. pussy888 says:

    I’ve read some just right stuff here. Definitely worth bookmarking for revisiting. I surprise how so much effort you set to make any such excellent informative website.

  30. comprar stimerex says:

    When I initially commented I clicked the “Notify me when new comments are added” checkbox and now each time a comment is added I get several emails with the same comment. Is there any way you can remove people from that service? Thanks a lot!

  31. megafon has decided on the plan of work in tatarstan says:

    I know this if off topic but I’m looking into starting my own blog and was wondering what all is needed to get set up? I’m assuming having a blog like yours would cost a pretty penny? I’m not very web smart so I’m not 100 certain. Any tips or advice would be greatly appreciated. Thanks

  32. buy runtz pack online says:

    Pretty section of content. I just stumbled upon your web site and in accession capital to assert that I get in fact enjoyed account your blog posts. Any way I will be subscribing to your feeds and even I achievement you access consistently rapidly.

  33. honda empregos says:

    Your style is so unique compared to many other people. Thank you for publishing when you have the opportunity,Guess I will just make this bookmarked.2

  34. hop over to here says:

    Valuable info. Fortunate me I found your site accidentally, and I’m shocked why this twist of fate didn’t happened earlier! I bookmarked it.

  35. pacote de vs says:

    Hola! I’ve been following your weblog for a while now and finally got the bravery to go ahead and give you a shout out from Austin Texas! Just wanted to say keep up the excellent work!

  36. LeonelPMewes says:

    Greetings! I’ve been reading your web site for quite some time now and lastly got
    the courage to go ahead and offer you a
    shout from Houston Tx! Just wanted to mention keep up the good
    work!

    Here is my web page :: LeonelPMewes

  37. car battery delivery near me says:

    I have recently started a blog, the information you provide on this web site has helped me greatly. Thank you for all of your time & work. “The only winner in the War of 1812 was Tchaikovsky” by Solomon Short.

  38. car battery delivery pj says:

    Thank you for the auspicious writeup. It actually used to be a amusement account it. Glance advanced to far introduced agreeable from you! By the way, how can we keep in touch?

  39. aiot companies says:

    F*ckin’ awesome things here. I’m very glad to see your post. Thanks a lot and i’m taking a look forward to contact you. Will you kindly drop me a e-mail?

  40. SMS says:

    Very good article! We are linking to this particularly great content on our site. Keep up the great writing.

  41. espumante says:

    Generally I do not read post on blogs, however I would like to say that this write-up very pressured me to try and do it! Your writing style has been surprised me. Thank you, quite great article.

  42. Spa Com Hidro says:

    I like what you guys are usually up too. Such clever work and reporting! Keep up the wonderful works guys I’ve incorporated you guys to blogroll.

  43. blog da muda solucoes says:

    I’ve recently started a web site, the information you offer on this site has helped me tremendously. Thanks for all of your time & work. “The inner fire is the most important thing mankind possesses.” by Edith Sodergran.

  44. คาสิโน says:

    I’ve been surfing online greater than three hours these days, yet I never discovered any interesting article like yours. It’s pretty value enough for me. In my view, if all webmasters and bloggers made just right content material as you did, the internet will probably be a lot more useful than ever before. “Oh, that way madness lies let me shun that.” by William Shakespeare.

  45. Curso data studio says:

    Hi! I know this is kinda off topic but I was wondering which blog platform are you using for this website? I’m getting tired of WordPress because I’ve had issues with hackers and I’m looking at options for another platform. I would be fantastic if you could point me in the direction of a good platform.

  46. Wasserbett Leintuch says:

    Hi there! This post couldn’t be written any better! Reading through this post reminds me of my previous room mate! He always kept talking about this. I will forward this article to him. Pretty sure he will have a good read. Thank you for sharing!

  47. Seowebsiterank language id says:

    There are definitely a lot of details like that to take into consideration. That could be a great level to deliver up. I supply the thoughts above as basic inspiration but clearly there are questions like the one you convey up where a very powerful thing will be working in sincere good faith. I don?t know if best practices have emerged around issues like that, but I am certain that your job is clearly recognized as a fair game. Both boys and girls feel the influence of only a moment’s pleasure, for the remainder of their lives.

Trackbacks & Pingbacks

  1. buy generic viagra online

    EAV database for Magento (1.9) in practice (frontend) – aionhill.com

  2. chloroquine otc

    EAV database for Magento (1.9) in practice (frontend) – aionhill.com

  3. albuterol inhaler

    EAV database for Magento (1.9) in practice (frontend) – aionhill.com

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published.