Custom Magento EAV Attributes

Magento has an Entity Attribute Value system in the db, neaning you can easily add custom stuff by adding rows and not columns! But that’s all done for us, so here’s how we set it up. In this example I’m wanting a home page image radio button.

In the config.xml you’ll see something like

<version>0.2.0</version>

So in this example we would bump that up to 0.3.0. Also, check you have a setup key in the xml:

<resources>
    <madskull_homepage_setup>
        <setup>
            <module>Madskull_HomePage</module>
            <class>Mage_Catalog_Model_Resource_Setup</class>
        </setup>
    </madskull_homepage_setup>
</resources>

Next, in the sql folder of your module, create a file called madskull_homepage_setup/upgrade-0.2.0-0.3.0.php (thats upgrading from v0.2.0 to v0.3.0) and I put the following:

<?php

/* @var $installer Mage_Catalog_Model_Resource_Setup */
$installer = $this;

$installer->startSetup();

$installer->addAttribute(
    Mage_Catalog_Model_Product::ENTITY,
    'homepage_image',
    array(
        'frontend'                      => 'catalog/product_attribute_frontend_image',
        'global'                        => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
        'visible'                       => true,
        'used_in_product_listing'       => true,
        'filterable'                    => false,
        'filterable_in_search'          => false,
        'used_for_price_rules'          => false,
        'searchable'                    => false,
        'comparable'                    => false,
        'visible_on_front'              => true,
        'used_for_sort_by'              => false,
        'is_visible_in_advanced_search' => false,
        'type'                          => 'varchar',
        'input'                         => 'media_image',
        'group'                         => 'Images',
        'label'                         => 'Homepage Image',
        'user_defined'                  => true,
        'is_configurable'               => false,
        'required'                      => false
    )
);

$installer->endSetup();

When you next visit any page, Magento will see the version has changed, and attempt to upgrade it. If successful, it will appear in the eav_attribute table. Clear your caches,  and reindex. Now if you go into your products in the admin panel, and select any product to edit, click on the Images option, and you should see our new attribute in there as a radio button! 🙂

Now you can use your variable by doing things like $collection->addAttributeToSelect([‘name’, ‘price’, ‘special_price’, ‘homepage_image’]);  and so on! 😀

Advertisements

Setting Magento to use SMTP

In my new work we run a Magento eCommerce store. As such, I’ve set up a fresh Vagrant Box through http://www.puphpet.com (try it!) and installed Magento into one of the vHosts. Stupidly, I forgot my password almost immediately, which highlighted a problem! Mail wasn’t sending out.

Of course, Zend_Mail defaults to using Zend_Mail_Transport_Sendmail and not Zend_Mail_Transport_Smtp, so I looked around for how to set this in Magento. Everyone on IRC told me to use 3rd party software! I checked it out, and the thing is totally insecure! https://github.com/aschroder/Magento-SMTP-Pro-Email-Extension/issues
So I decided against that.

The real answer lies in the way that Magento overrides existing classes. I told the guys in the #magento IRC channel that I refused to use the above insecure library, and would rather just hack the core ZF class.

It turns out that you can create a local directory in /app/code. So for a completely customised Zend_Mail without touching third party vendor files (ie. the ZF lib), you create /app/code/local/Zend/Mail.php, and tweak away to your liking!

line 1175 is the culprit . Change

$transport = new Zend_Mail_Transport_Sendmail();   // the ZF default
to
$transport = new Zend_Mail_Transport_Smtp();

Lastly, if you need to set a custom port (on my dev box, I wanted all my mail going through port 1025 so that Mailcatcher would stop development mails going out), then run the following SQL query on your DB:

INSERT INTO `core_config_data` (`config_id`, `scope`, `scope_id`, `path`, `value`) VALUES (NULL, 'default', 0, 'system/smtp/port', '1025');

If you set a  db prefix then tweak the above table name to suit. That should be you ready to rock! Have fun!

Install Varnish Caching on CentOS with or without cPanel interference

Without messing with cPanel or Apache’s setup, we can still install Varnish to cache our pages a lot quicker, via the iptables firewall!

The problem was that changing the apache httpd.conf didnt work as expected, as cPanel does a lot of auto generating and tweaking of system files. yuk. i much prefer a terminal any day. Anyway! Lets have a look:

yum install varnish
nano /etc/sysconfig/varnish

comment out configuration 1, 3, and 4, uncomment config 2 and set as follows:

DAEMON_OPTS = " -a :8080 \                                          
                -T localhost:6082 \             
                -f /etc/varnish/default.vcl \              
                -S /etc/varnish/secret \             
                -s malloc,256m"

The -a line is the port varnish will run on. In a normal configuration, Varnish will take over port 80, so make it port 80. In the case of a server using cPanel, if you cant change your apache port to 8080, then you can set varnish to 8080 instead.

nano /etc/varnish/default.vcl

backend default {
    .host = "127.0.0.1";
    .port = "80";
}

The backend is Apache. In a normal varnish setup, this port should be 8080.  Using a reverse system using iptables, apache stays as port 80. Also, the host should become the external IP in this configuration.

Now, depending on your setup, depends what happens next.

Without cPanel, under a standard setup, you will have set Varnish to port 80 and Apache to port 8080. In this case, you must edit your apache httpd.conf, searching and replacing :80 with :8080. Then just stop and start the services as below, skipping the iptables stuff.

With cPanel, we can leave that alone and instead use an iptable rule to send all port 80 requests to varnish at port 8080. Edit ~/.bashrc, pasting this in:

alias varnishon='iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080'
alias varnishoff='iptables -t nat -D PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080'
alias varnishstatus='iptables -L -t nat |grep -q 8080; if [ "test$?" = "test0" ]; then echo "Varnish On"; else echo "Varnish Off"; fi'

 

You can now call, varnishon, varnishoff, and varnishstatus next login. So logout and login.

Restart Apache and start up varnish:

service httpd restart
service varnish start

You should be able to access your site on port 80 AND port 8080. The difference? Run a curl command to see the headers:

curl -I http://mysite.com
curl -I http://mysite.com:8080

You’ll see the port 8080 mentions varnish.

Last thing to do is enable the iptables rule: Type in your alias command you put in bashrc:

varnishon

Now port 80 is routing to port 8080, and you have varnished pages, and haven’t touched your cPanel setup!

Considerations: the header shows the page in this weird cPanel workaround setup as 301 moved permanently. Also, the site i was using captured IP addresses, but due to the proxy nature of this setup, the ips captured belonged to the server! The actual way should be to have Apache on 8080 and varnish on 80, and no ip rules at all. If you have access to WHM or cPanel, you are looking for tweak settings, and change the default apache port to 8080 in there! Good luck!

Moving a Live Magento Site to a Local Server

Hi!

This job seems to get more interesting and fun by the day!

Today, it’s Magento! The mission? To move an existing Magento Store from Live hosting out there to another hosting provider, and then reskin it. And inbetween we’re going to miove it onto my local apache install.

Download the files, and setup your hosts and vhosts as per usual. However! localhost or whatever you call it will not be enough apparently, it likes a FQDN (fully qualified domain name.), so I called mine http://magentolab.del

Export the MySQL DB. Apparently the best way to do that is through the admin section of the magento site, as PHP MyAdmin does not bother with the Foreign Key Constraints of InnoDB, and you may get import errors if you do it that way. Your mileage may vary.

Import your SQL dump into MySQL, then run this command (your tables may or may not have the ‘mage_’ prefix, delete as appropriate)

select * from mage_core_config_data where path like "%base_url%"

Change the url to your local address. Put a trailing slash on the end of it!! Restart Apache, browse to your site, and watch it FAIL! Ok, now to set it up some more. Open it up in your favourite IDE, and look for app/etc/local.xml.
That’s where you’ll find settings regarding your DB connection. Edit to suit.

Now, you’ll probably not be getting to see your exceptions on screen. You’ll find them hidden away in var/report.

In my case, I was getting an exception that stated: Illegal scheme supplied, only alphanumeric characters are permitted

Again, the FQDN issue I described was part of this, but not all. We need to comment some other stuff out.
Dig into the app/code/core/Mage/Core/Model/Session/Abstract/ folder and open Varien.php. Jump to line 85 (as of v1.6.1)
Comment out some of the array like so:

  // session cookie params
        $cookieParams = array(
            'lifetime' => $cookie->getLifetime(),
            'path'     => $cookie->getPath(),
          /*  'domain'   => $cookie->getConfigDomain(),
            'secure'   => $cookie->isSecure(),
            'httponly' => $cookie->getHttponly() */
        );

If you’ve done everything correctly, you should have your live site running on your development machine! I’m guessing reverse that process to get it to my new live server! Have Fun