How i use Vagrant

VagrantWhat is Vagrant?

Vagrant describes it’s self as:

Create and configure lightweight, reproducible, and portable development environments.

Vagrant is a simple tool that works on top of VMWare or VirtualBox to provide you with the ability to spin up development environments with as minimal time as possible. On their website you’ll find alot of prepared images of various Linux distros that are Vagrant-ready!

Usually, as a web developer, you tend to work on various projects which need various tools & platforms. You might work on project X which needs to have Apache, PHP, MySQL, Memcached. While project Y needs a whole set of different stuff installed and running. Using your own device, you’ll have all these tools installed and running which consume the device’s resources in addition to making you fall into the mess of all the dependencies installed.

Vagrant comes to the rescue. You can use vagrant simply to spin up VMs that contain the specific project you’re working on which will have the tools project X requires. Once you’re done and want to context-switch to a different project, you halt the current VM and spin up Project Y’s machine to start working on it there.

Why use a tool on top of a virtualization platform? you ask. Simply because of the following:

Point one, vagrant provides you with a set of features that make your life easy. Once you initialize a machine, a file called “Vagrantfile” which is a ruby script is generated on the directory you initialized the file one.

1) You can simple configure port-forwarding with 1 line of ruby code which forwards all network requests on a specific port to another specific port on your VM. It is as simple as:

config.vm.network :forwarded_port, guest: 80, host: 8080

Using this port-forwarding rule, all your web requests to localhost:8080 will redirect the request to the guest machine on port 80.

2) You can setup folder sharing. This feature is extraordinary! When you setup to sync a folder to the guest machine, you can do the development on your own device using your code editor / IDE while running the code on the guest machine. This happens as each time you edit a file, this file is automatically synced to the guest machine so you don’t feel like you have to transfer the code after each change.

Synced folders rule looks as follows:

config.vm.synced_folder "/dir/to/local/project/", "/dir/to/project/on/guest"

The points above have been mainly features that are already available in either VMWare or VirtualBox. What vagrant does is making you’re life easier figuring out how to configure these platforms to activate the features. Which leads us to point #3

3) Last and foremost, provisioning. Machine provisioning is a Vagrant-specific feature which lets you automatically install all of your project’s dependencies, configure these tools and fire them up if necessary once the VM is booted.
Vagrant let’s you provision your machines using Fabric, Chef or Puppet. This very specific feature, enables you to write provisioning scripts once, and use them multiple times across different machines you spin up.

If you’re working in a team environment, you can simple write the provisioning scripts that will  enable you to generate images that are consistent among your team members which they can use to write the code along with their unit tests which eventually will pass/fail on all devices consistently because the machines themselves are consistent.

 

As for myself on how i use Vagrant. I don’t run a VM per project but rather, per language. I currently run 3 VMs using vagrant.

1) Python VM which has all my python/django projects. Having that python itself has virtualenv, i wrap my projects inside a virtualenv to separate their dependencies. However, this VM has python 2.7 installed along with pip, virtualenv, virtualenv wrapper, MySQL-python, PIL which are required by almost all of my projects.

2) PHP VM: this has apache, mysql, php5 along with anything that my php project’s require. Since i don’t have many projects in PHP other than those i do at the company i work for, this is only for checking our new PHP stuff every now and then.

3) Work VM: which has the code for the platform(s) i am working on for the company i work for. This is exactly like the PHP VM but with more tools installed.

This way, i keep my laptop free of any language/platform dependent tools and i don’t waste time getting different dependencies of different versions to install, as well as provisioning machines on the fly if needed to bootstrap any given project.

I find Vagrant a great bless, i am interested to see what different use cases you guys do in vagrant to be even more productive? If you’ve never used vagrant, i believe you should. Simple head to http://vagrantup.com

 

Have a great one.

Rakan

Leave a Comment

support unicode in Magento product url key

Magento is one of the best E-Commerce platforms currently on the internet. However, it doesn’t seem to take into account one of the most important SEO rules which states that the URL key which is used to create the product’s URL should be SEO-friendly. We can still write the url key in english for our arabic products but this won’t exactly match this rule to have the arabic keywords of the product’s title in the product url as well.

I rolled up my sleeves and got to work. What i did was a 2 stage tracing / debugging session. I will also be writing this in a magento module to group this functionality all together into a reusable component.

Let’s start preparing for the module we’re going to create. All you have to do, assuming you name your company “XYZ” is the following:

1) Create a folder called “XYZ” in your app/code/local directory.

2) Inside XYZ, create a folder called “etc” and another folder called “Model”.

3) Inside XYZ/etc create a file called config.xml and add the following:

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

Now… here’s what i’ve done.

1) The first problem was that when entering the product key in arabic, the product got saved with an empty url key. Using Zend Studio and xdebug’s remote debugging, i found out that product entity attributes were being filtered. One of the filters passed on the url_key field was “Mage_Catalog_Model_Product_Url”. The method being called in that filter is “formatUrlKey” which takes the URL key as a string:

public function formatUrlKey($str)
{
    $urlKey = preg_replace('#[^0-9a-z]+#i', '-', Mage::helper('catalog/product_url')->format($str));
    $urlKey = strtolower($urlKey);
    $urlKey = trim($urlKey, '-');
 
    return $urlKey;
}

As you can see from the regex in the first line of the function’s body. All characters are being removed apart from 0 to 9 and a – z (small case). All we had to do here is override the function to become:

public function formatUrlKey($str)
{
    $urlKey = Mage::helper('catalog/product_url')->format($str);
    $urlKey = strtolower($urlKey);
    $urlKey = trim($urlKey, '-');
 
    return $urlKey;
}

So the final model code should become:

<?php
class XYZ_UnicodeUrls_Model_Product_Url extends Mage_Catalog_Model_Product_Url
{
    public function formatUrlKey($str)
    {
        $urlKey = Mage::helper('catalog/product_url')->format($str);
        $urlKey = strtolower($urlKey);
        $urlKey = trim($urlKey, '-');
 
        return $urlKey;
    }
}

Make sure you add the following to your config.xml so that magento can rewrite the original model with your one.

<global>
    <models>
    ....
        <catalog>
            <rewrite>
                <product_url>N2Vlabs_UnicodeUrls_Model_Product_Url</product_url>
            </rewrite>
        </catalog>
    .....
    </models>
</global>

2) Even if you’ve solved the problem of adding a unicode url key. Now we have to make sure magento was finding a record for this URL inside table “core_url_rewrite” when looking for it.

After digging a bit deep into what is going on, i also found out that “Mage_Core_Model_Resource_Url_Rewrite” was looking up the database for this URI in a method:

public function loadByRequestPath(Mage_Core_Model_Url_Rewrite $object, $path)

When having an arabic URI, the URI is captured url encoded inside this method’s loop that looks as follows:

foreach ($path as $key => $url) {
    $pathBind['path' . $key] = $url;
}

All we had to do here is to make sure we url decode $url to become:

foreach ($path as $key => $url) {
    $pathBind['path' . $key] = urldecode($url);
}

The whole code looks as follows:

<?php
class XYZ_UnicodeUrls_Model_Resource_Url_Rewrite extends Mage_Core_Model_Resource_Url_Rewrite
{
    public function loadByRequestPath(Mage_Core_Model_Url_Rewrite $object, $path)
    {
        if (!is_array($path)) {
            $path = array($path);
        }
 
        $pathBind = array();
        foreach ($path as $key => $url) {
            $pathBind['path' . $key] = urldecode($url);
        }
        // Form select
        $adapter = $this->_getReadAdapter();
 
        $select = $adapter->select('*')
            ->from($this->getMainTable())
            ->where('request_path IN (:' . implode(', :', array_flip($pathBind)) . ')')
            ->where('store_id IN(?)', array(Mage_Core_Model_App::ADMIN_STORE_ID, (int)$object->getStoreId()));
 
        $items = $adapter->fetchAll($select, $pathBind);
 
        // Go through all found records and choose one with lowest penalty - earlier path in array, concrete store
        $mapPenalty = array_flip(array_values($path)); // we got mapping array(path => index), lower index - better
        $currentPenalty = null;
        $foundItem = null;
        foreach ($items as $item) {
            $penalty = $mapPenalty[$item['request_path']] << 1 + ($item['store_id'] ? 0 : 1);
            if (!$foundItem || $currentPenalty > $penalty) {
                $foundItem = $item;
                $currentPenalty = $penalty;
                if (!$currentPenalty) {
                    break; // Found best matching item with zero penalty, no reason to continue
                }
            }
        }
 
        // Set data and finish loading
        if ($foundItem) {
            $object->setData($foundItem);
        }
 
        // Finish
        $this->unserializeFields($object);
        $this->_afterLoad($object);
 
        return $this;
    }
}

And you have to add the following to your config.xml to override the original model.

<global>
    <models>
        ....
        <core_resource>
            <rewrite>
                <url_rewrite>XYZ_UnicodeUrls_Model_Resource_Url_Rewrite</url_rewrite>
            </rewrite>
        </core_resource>
        ....
    </models>
</global>

If you’d like to get the whole extension code from github… here’s the link

That’s all folks… see ya next time.

, , , ,

7 Comments

PHP getting difference between two arrays

Is it me? or is array_diff and array_diff_assoc don’t really cover the requirements of getting the actual difference between two arrays ?

I am currently working on a project using Yii Framework. What i am trying to do, is get the list of fields that have changed after saving data within my model (CActiveRecord).

According to the documentation of array_diff, it Returns an array containing all the entries from array1 that are not present in any of the other arrays. Which is not what i needed. What i really needed is a function that checks the difference between two arrays and returns all entries from array1 which are not in array2 and all entries from array2 which don’t exist in array1 in addition to checking if the actual values have changed.

 

Here’s my attempt at solving this problem:

protected function getChangesBetweenArrrays($oldArr, $newArr) {
    $changedFields = array();
 
    foreach($oldArr as $key => $value) {
        if(!isset($newArr[$key])) {
            $newArr[$key] = '';
        }
    }
 
    foreach($newArr as $key => $value) {
        if($key == 'id') continue;
 
        $item = false;
        if(!isset($oldArr[$key]) && isset($newArr[$key])) {
            $item = array('field'=>$key, 'value'=>$newArr[$key]);
        }
        elseif(isset($oldArr[$key]) && $newArr[$key]=='') {
            $item = array('field'=>$key, 'value'=>'removed');
        }
        elseif($oldArr[$key] != $newArr[$key]) {
            $item = array('field'=>$key, 'value'=>$newArr[$key]);
        }
        if($item) {
            $changedFields[] = $item;
        }
    }
 
    return $changedFields;
}

I would love to hear your feedback on this solution and if you’ve been facing such a case, what was your implementation?

Leave a Comment

If This Then That (ifttt)

A very nice service which can let you trigger certain actions when updates are found from a certain channel. For this example, i am writing this blog post and telling ifttt that when i post a new blog, share it on my facebook account!

Leave a Comment

The Lean Startup, What it is and What it is NOT

At least of what my conception of the methodology of Lean Startups.

The Lean Startup methodology suggests that you go about building your startup in simple steps:

  1. Problem / Solution Fit, this is where you suggest the problem your product (startup) solves for your customer segment. You end up by answering ONE simple question. Do i have a problem WORTH solving?
  2. Product / Market Fit, It is after you prove that your product solves an actual problem that you go about on validating whether your product users are willing-to-pay customers.
  3. Scale, when you’ve figured out that you’re doing a decent job at building, measuring and learning about your customers you know that when you scale, you’re acquired customers will be engaged into using, buying.. etc your product.

 

In all of the above steps, you simply follow a simple three-steps formula: Build, Measure, Learn.

  1. Build: Develop an minimal-viable-product (MVP) of your suggested solution. Your MVP should provide the core solution.
  2. Measure: Specifying what metrics you want to consider when you’re analyzing customer behavior when using the product.
  3. Learn: You build conclusions and optimize your product based on your analysis in the measuring step.

 

This day, Jan 12th 2012, CEO of N2V Labs Rami Alkarmi gave a session Lean Startup 101 which was a great brief introduction on how to follow the methodology. The session was a great one and i suggest you click on the link to check the slides available at Rami’s blog.

Having that i’ve attended the session as part of N2V Labs and being an Entrepreneur-in-Residence at the Labs and also with a hands-on experience on following the lean startup methodology; i found that there was a small misconception by the crowd that Lean Startup is THE secret sauce to a successful startup and nothing else.

Uhhm,  NO!

Lean startup is NOT a super mathematic formula that if you follow your startup is going to be the next big thing. Lean Startup is basically a major player in the game and is also a factor of the success of any startup.

So what is all about?

Well, my conception is that it is all about the Entrepreneur! Simply put, each one of us has his/her own way of logical thinking. His/her way of understanding and implementing. The Lean Startup is only successful if the entrepreneur following the methodology is a good one.

They say that you can never succeed if you don’t fail. Good Entrepreneurs fail fast, learn from failures, adapt and pivot based on those experiences.

 

Correct me if i am wrong :), feel free to drop a comment if you’re in the mood to discuss.

Links:

1) Rami Alkarmi’s blog

2) The Lean Startup

Rakan

 

1 Comment

The weakness of PHP frameworks

A programming language framework is meant to decrease the development time and increase the productivity of software developers. However, i still find the frameworks built for the PHP language still concentrate on building the lower-level features of the frameworks while disregarding the importance of higher level ones.

Example, Zend framework provides the set of class chains which provide the functionality to implement the login mechanism. This includes authentication (Zend_Auth) and Authorization (Zend_Acl). But in reality, these components still require me to write integration codes to be able to have this whole membership feature.

My point is, having a framework that provides plug-and-play components just like Django’s middleware which you can just drop into your framework-based application and have the feature working with almost zero efforts.

Is lacking this plug-and-play feature because framework developers prefer implementing the low-level code patterns such as MVC, or is implementing customizable functional out of the box components really hard?

http://www.phpframeworks.com/top-10-php-frameworks/

Leave a Comment

1 Reason why PHP exception handling is full of crap!

As a long-time PHP developer, i find exception handling to be an option that PHP supports just because other languages do or because OOP in PHP started to emerge in the 5.x series of the language.

I’ve developed many systems in the past and present days… from small simple to high scalability applications and to be honest, i found that i can easily write code with no exception handling whatsoever and that application will do just fine. I know i know, “will do just fine” is the normal behavior of any well-written application, but book and tutorials writers always tend to emphasize on the importance of using exception handling in code to make sure the application does not crash in case some exception is thrown. But this is the point, PHP rarely throws exceptions, it mainly triggers errors which can be handled by set_error_handler.

The only thing that ever forced me to use exception handling was when i used well designed OOP 3rd party libraries which throw exceptions instead of triggering errors… which is exactly what PHP is supposed to be doing as far as am concerned.

 

Have YOU ever used exception handling in any other case than the one i just mentioned? please enlighten me :)

 

Rakan

7 Comments