Ruby symbols instead of blocks

by Ryan on August 6, 2011

Every wonder why this works? It’s straight forward and easy to read, but how does it work internally in Ruby?

[1, 2, 3].inject(&:+)
# => 6

Meet &

The & operator in Ruby lets us go from Proc to block and vise-versa, but only in certain places.

In fact, there are two two places where we can use &

In a method definition &blk will turn the blk argument into a proc, allowing it to be called.

def block_to_proc &blk
  blk.call
end
block_to_proc { "hello" }
# => "hello"

In a method call it coverts the argument into a block.

def proc_to_block
  yield
end
proc_to_block(&proc { "hello" })
# => "hello"

To Proc

Ruby has a lot of to_X methods. They are designed to express their receiver as another type.

"1".to_i + 2
# => 3

Well, to_proc exists too. Expressing non proc objects as procs? When and why would we ever do that? An example is our [...].inject(:+) piece. A quick, simple, shorthand way to express a block without having to write it all out.

Anytime we are trying to express an object as a proc Ruby will check to see if that object responds to to_proc. If it does it will use the return value to express the object as a proc. Since &object can covert procs to blocks the & is going to want the object to be a Proc before it does anything. So &object is going to really be &object.to_proc.

Symbol’s To Proc

Symbol’s to_proc is what allows us to pass it in place of a block. It might look a little strange at first, but once you see it used it becomes pretty cool.

class Symbol
  def to_proc
    proc { |obj, *args| obj.send(self, *args) }
  end
end

This returns a proc that takes 2 parameters

  • First is an object that will receive the method.
  • The second is the arguments that will be passed into the method.

And when that proc is called

  • Sends the original symbol to the object with the arguments.

So, :methods.to_proc basically builds this method.

# :methods.to_proc
def methods_to_proc_when_called obj, *args
  obj.send(:methods, *args)
end

Lets play with :symbol.to_proc in some funny ways.

my_little_proc = :methods.to_proc
# my little proc is ready to call :methods on any object
 
my_little_proc.call(String)
# => returns an array all of String's methods

The Setup

We’re basically creating a proc from a symbol that can be used to send that symbol into any object. In fact, a more fitting name for my_little_proc would be something like call_my_symbol_on.

class String
  def introduce
    puts "Hi I'm #{self}"
  end
 
  def introduce_to name
    puts "Hi #{name}, I'm {self}"
  end
end
 
call_my_symbol_on = :introduce.to_proc
call_my_symbol_on("ryan")
# => "Hi I'm ryan"

Since the proc that to_proc returned is setup to take arguments.

call_my_symbol_on = :introduce_to.to_proc
call_my_symbol_on("ryan", "steve")
# => "Hi steve, I'm ryan"

If you think about it, this is really simple. call_my_symbol_on is just going to call introduce (because we used :introduce to create it) on the first parameter. It is going to send the 2nd+ parameters in as arguments.

With Map

Ok, lets get to the real world examples. We often see to_proc commonly used with enumerable. Lets say we want to introduce a bunch of names.

['ryan', 'steve', 'jill'].map(&:introduce)
# => Hi I'm ryan
# => Hi I'm steve
# => Hi I'm jill

Is really

['ryan', 'steve', 'jill'].map(&:introduce.to_proc)

Which can be expressed as

['ryan', 'steve', 'jill'].map( & proc{ |obj, *args| obj.send(:introduce, *args) } )

And & is now going to covert that proc into a block. That line can now become

['ryan', 'steve', 'jill'].map{ |obj, *args| obj.send(:introduce, *args) }

And since map only passes one argument, the element, to its block there is really no need to express the additional arguments.

['ryan', 'steve', 'jill'].map{ |obj| obj.send(:introduce) }

Which is sending the message introduce our object, which we know is the same as

['ryan', 'steve', 'jill'].map{ |obj| obj.introduce }

You can see that by expanding and reducing the &:symbol notation we can end up with a very familiar call map with block.

Now with some *Args

So what about *args? We were able to drop it, because map only expects a block that will yield to one element. We need to find a common ruby method that yields more than one thing to a block.

How about inject? It’s block expects 2 parameters, result and element.

Enumerable.inject(start) { |result, element| … }

Lets do what we did above. But this time get from

# turn
(1..10).inject(&:+)
 
# into
(1..10).inject do |result, element| 
  result + element
end

Here we go

(1..10).inject(&:+)
(1..10).inject(&:+.to_proc)
 
# can be expressed as
 
(1..10).inject( &proc{ |obj, *args| obj.send(:+, *args) } ) 
 
# which & will covert into
 
(1..10).inject( |obj, *args| obj.send(:+, *args) } ) 
 
# which we can convert to
 
(1..10).inject do |obj, *args| 
  obj.send(:+, *args) 
end
 
# and then we can just rename our parameters to something more friendly
 
(1..10).inject do |result, element| 
  result.send(:+, element) 
end
 
# => 55

Map If in Ruby and an Introduction to Ruby’s Inject

by Ryan on July 25, 2011

When I first got into Ruby I kept hearing the saying: “There is more than one way to do it.” At first, this really freaked me out. I thought it meant that learning Ruby was going involving reading lots of code golf samples where developers come up with tricky, cleaver, and mind boggling ways to accomplish small problems. That original thought could not have been more false. Over the past year I’ve discovered that Ruby’s “There is more than one way to do it” really means that the best way to do something is generally the most readable and understandable way.

Map if

Here is a little example of multiple ways to do the same thing, what I like to call the “Map if” problem.

Map if involves taking an array (or any enumerable object) and returning a manipulated version of every element for which a certain condition is met. So, lets write a piece of code that takes an array of integers and returns an array of those integers multiplied by two if the integer is an even number.

given [1, 2, 3, 4, 5, 6] return [2*2, 4*2, 6*2] or [4, 8, 12]

Select/Map

A very straight forward way to solve this problem is just chaining two array methods together.

[1, 2, 3, 4, 5, 6].select { |elm| elm % 2 == 0 }.map { |elm| elm * 2 }
# => [4, 8, 12]

First select will filter the array but the condition defined in the block. Then map will apply its block onto each element in the array that select built.

Inject

A better way is to solve this problem is to use Enumerable’s inject, which is somewhat foreign to new ruby programmers. It’s syntax is a little off putting at first, it takes 2 parameters: a starting object and a block. The block then takes another 2 parameters: an element and the result. Before I explain this method any further here is an the above map/if done with inject.

[1, 2, 3, 4, 5, 6].inject([]) do |result, elm|
  result << elm * 2 if elm % 2 == 0
  result
end
# => [4, 8, 12]

So what is this doing? Inject in english is:

Start with some object (our empty array) and then pass each element in our caller ([1, 2, 3, 4, 5, 6]) to the block. Provide a result object that the block can freely change. The result starts out as our first parameter (the empty array) and then becomes whatever the block evaluates last.

So why is inject better? There are a number of reasons

One method with one block
Our select/map example above was straight forward, but it involves multiple method calls and multiple blocks. The longer our method chain becomes the less readable our code is. Inject is readable because the block is just a block, that is to say, if you write readable Ruby in the block then the inject method is going to be very easy to follow.

Part of Enumerable
Any object that extends enumerable is going to have inject. This makes it very reusable. I find myself using inject on a daily bases for all sorts of different use cases.

Powerful
The real power of inject lies in it’s ability to build new objects while looking at every element in the caller individually. Since inject can draw values from any enumerable object it makes it an ideal method for many common uses such as filtering, grouping, summing and everything else related to building. The map if example showed how inject can be used to filter and build.

Grouping

Grouping a list of words by the first letter of the word:

["alpha", "bravo", "charlie", "bark", "almond"].inject({}) do |result, elm|
  result[elm[0].to_sym] ||= []
  result[elm[0].to_sym] << elm
end
# => {:a=>["alpha", "almond"], :b=>["bravo", "bark"], :c=>["charlie"]}

Summing

Inject is used in many common ruby idioms. The next code line will look like absolute garbage to anyone not familiar with Ruby. However, to someone that knows inject it is a very clear and readable code.

Sum up all the numbers between 1 and 10 inclusive.

(1..10).inject(:+)
# => 55

Short and simple, but what happened to our parameters and block?

No Starting Value
When you call inject without a starting value (the first parameter) the starting value will default to the first element inside your enumerable. So in the above example result would be 1 for the first pass.

No Block
In Ruby 1.9 all symbols have a to_proc method. Instead of passing a block where a block is required, you can pass a symbol and that symbol will create a proc that then calls itself on the object. The object in this case is our result. So :+ will turn into result + *args, where *args is our element.

PHP Dependency – A PHP Dependency Injection Framework

by Ryan on September 9, 2010

PHP-Dependency (Pd) is a dependency injection framework and container written in PHP. One of the main features of PHP-Dependency is that it supports class reflection, which means you do not have to maintain ANY configuration files.

Class MyExample() {
 
    private $_database;
 
    /**
     * This is the constructor, the database is automatically injected
     * due to the PdInject DocBlock.
     *
     * @PdInject database
     */
    public function __construct($database) {
        $this->_database = $database;
    }
 
}

That’s it. No configuration other than that one line Doc Block.

Documentation

Download

PHP-Dependency.tar.gz
PHP-Dependency on GitHub

Setup

You need to make sure that the Pd library is on your include path.

set_include_path(
    get_include_path() . PATH_SEPARATOR .
    '/path/to/php-dependency/library/'
);

Autoloader
If you are using a PHP framework with an autoloader then just make sure the library/Pd is on the include path and tell the autoloader to use ‘Pd’ as the class prefix/namespace.

No Autoloader
If you are not using an autoloader then you can just require the class. All classes follow the naming conventions from Zend Coding Standards. See Below.

require_once 'Pd/Container.php';
$container = Pd_Container::get();

The Container

The container holds all of your dependencies. Adding dependencies to the container is very simple.

$database = new Database("mysql://user:password@server/database");
 
$container = Pd_Container::get();
$container->dependencies()->set('database', $database);

You can put anything into the container. Objects, arrays, strings, and even anonymous functions.

Your Classes

Class dependencies are defined by PHP DocBlocks. Every Pd command begins with @PdInject and is followed by a key:value type syntax. The most common command will be injecting a dependency by name, which just requires the dependency name.

Class Book {
 
    private $_database;
 
    /**
     * @PdInject database
     */
    public function setDatabase($database) {
        $this->_database = $database;
    }
 
}

Key:Value Commands and Examples

Key:Value commands can be used with the @PdInject DocBlock.

new:ClassName – This will create a brand new instance of ClassName and inject it into the object. Example

method:MethodName – This will use MethodName to inject the dependency. Example

property:PropertyName – This will inject the dependency as PropertyName. Example

constructor:number – Used for constructor injection. Example

force:true – Used to force injection. Example

Creating Objects

To create objects use the Pd_Make class.

/* @var $book Book */
$book = Pd_Make::name('Book');

This is the same as doing

$book = new Book();
$book->setDatabase($database);

Note: Use the @var doc line above the Pd_Make command. This will tell your IDE that $book is an instance of the Book class, which will allow the IDE to auto complete any calls/usages of $book in your code.

Non Reflective Map Building

If you do not want to use class reflection the Pd library contains a map builder that works off arrays. The commands are somewhat different from the key:value syntax, but they are self explanatory and easy to follow. Here is an example:

$builder = new Pd_Map_Builder_Array();
 
$builder->add(array(
    'dependencyName' => 'database',
    'injectWith' => 'method',
    'injectAs' => 'setDatabase',
));
$builder->add(array(
    'dependencyName' => 'apple',
    'injectWith' => 'constructor',
    'injectAs' => 1
));
$builder->add(array(
    'injectWith' => 'property',
    'injectAs' => 'theService',
    'force' => true,
    'newClass' => 'Service_Class',
));
 
Pd_Container::get()->maps()->set('MyClass', $builder->map());

This type of map building should only be used when needed.

Unit Testing

Pd includes a test suite that will unit test the library. Running this test is simple:

[ryan@localhost]$ cd /path/to/php-dependency/tests/
[ryan@localhost]$ phpunit AllTests
PHPUnit 3.4.11 by Sebastian Bergmann.
 
....................................................
 
Time: 0 seconds, Memory: 7.00Mb
 
OK (52 tests, 59 assertions)

Testing within your application
If you would like to test the library within your application, then inside of your test suite you can include the Pd test suite. To do this your AllTests file should look something like this:

require_once '/usr/share/php/php-dependency/tests/AllTests.php';
 
class AllTests extends PHPUnit_Framework_TestSuite {
 
    public static function suite() {
 
        $suite = new AllTests();
 
        // your unit test suites here
 
        // test php-dependency
        $suite->addTestSuite('PdTests_AllTests');
 
        return $suite;
    }
}

Vegas, Wifi, and Internet Poker

by Ryan on June 14, 2010

I am in Vegas for the World Series of Poker, which means 30 days of living out of a suitcase in a hotel room. After using the internet connection in the hotel for less than a few hours there is one thing that really stands out: this is the worst connection ever. Constant disconnections, tons of lag, and I have no idea how secure/unsecure the network is. These things all make it impossible to play online poker.

I did some research on wifi cards and came across Clear, which currently has 4g network infrastructure in Las Vegas as well as a month-to-month payment plan. Jackpot!

Clear USB Wifi Card for Poker

Clear's 4g USB Wifi Card

They have two options, buy online or buy in one of their Vegas stores, which are about five minutes off the strip. I choose to do an in-store buy because I wanted the connection right away. Purchasing the plan/card was really easy. I was somewhat hesitant because I never heard of this provider before, but I was really impressed with their store and knowledge. All-in-all I paid about $170 dollars for the modem, activation, and one month of coverage. I was also in and out of the store in 15 minutes, which is unbelievable when you think of average time spent in cell phone stores.

Since buying the card I have played six sessions of online poker on just about every single site. My average session is about five hours. I have had one disconnect, after four hours during the first session. Since then it has been flawless, including an eight hour session.

I am in one of these mega hotels in Vegas and my connection is usually one or two bars out of 10. The connection manager rates this as a ‘weak signal’. This is somewhat worrisome, but like I said, I was able to play a couple of big sessions without a single disconnect.

The speed seems pretty solid, it is not your cable modem, but for browsing webpages its perfectly fine.

Clear Wifi 4g Speed Test

Clear Wifi 4G Speed Test in Las Vegas, NV

I would easily recommend this to any online poker player spending the month in Vegas. Especially when you consider the $14.95/day fee for using the hotel’s unstable internet, this card becomes a no brainer.

My Development Environment

by Ryan on May 5, 2010

For the last two years I have been developing applications by using a virtualized development server as main my development environment. This process has worked out extremely well since a virtualized environment is always accessible, easy to replicate, easy to access, and is able to mimic production down to every last detail.

Always accessible

Since the development server is running on my computer, it’s always available. It does not matter if I am disconnected from the Internet, or the internal network at work, I am always able to access my development server. This is especially nice when taking long flights, because I able to write and test code with no external network dependencies.

Easy to Replicate

Virtual Machines are just files on the hard drive, which means they can easily be copied and shared. The size of the files are roughly the same size as the hard drive size that was chosen during the setup. Giving the development server a smaller hard drive is going to make sharing the environment much easier.

I use an 8gb hard drive for my machines. I find this generally gives me enough space and is easy enough to share. Sharing a development environment comes in handy when the development server takes a while to configure. If the development OS requires a lot of third party software or tweaking before it is able to run any code then saving and reusing the virtual machine will save a ton of time.

I recommend setting up a virtual environment, installing the OS and all of the required services/tweaks. Before you write any code backup the the virtual machine files. This will give you a good base system (restore point) if you ever need to setup the same environment on another computer.

The development environment will running on each developers computer, so developer A can break his environment without affecting any of developer B’s work. This is really nice when it comes to experimenting with operating system and software upgrades.

Easy to Access

Virtualized environments allow you to easily share files between your computer and the virtual machine. This means you can edit your code through your favorite desktop IDE and save it right to your development environment without having to move or transfer the files. This makes accessing your project or code repositories really easy from any virtual machine installed on your computer.

You can also share folders by using Samba, SSHFS, or FTP. However, those services are generally a lot slower and require some sort of configuration.

Mimic Production

Being able to have your development mimic your production environment is a must. It eliminates bugs, makes testing more effective, and makes coding a lot easier. Virtual machines are a great way to have your development environment be an exact replica of your production server. You can setup your development machine to have the same OS/PHP/MySQL/Apache/etc versions as production.

I have a Macbook Pro laptop, a Windows desktop, and an Ubuntu desktop that I write code from. Without virtualization I would never be able to code from all three of these machines. Some of the projects that I have worked on have deep dependencies (down to the OS version). Even with a pretty universal language like PHP you would be surprised to learn the number of functions/extensions that only work on certain operating systems. Using a virtual development environment instantly solves these problems.

One project per Machine

Aside from hard drive space, there is no limit to the number of virtual machines you can have. Most applications, especially web apps, start out as simple projects with little or no dependencies. However, over time these projects grow and start to rely on a specific database or language version. This creates the need to have each project have its own virtual machine.

I try to develop every project on a virtual machine that closely mimics that project’s production environment. This means a lot of different development environments, which really is not a problem. It’s a good rule to follow and it’s a necessary rule when dealing with complex projects.

Getting Started

I would recommend Oracle’s VirtualBox for running your development environment. It’s free and takes minutes to install, setup, and configure. I also wrote a guide for installing CentOs with VirtualBox.

How to Setup CentOs in VirtualBox

by Ryan on May 5, 2010

My primary development environment is generally a CentOS install through VirtualBox. Although the examples here are all CentOS, this guide can be used to install any operating system through VirtualBox.

What is a Virtual Machine

A virtual machine provides a platform for your machine to execute and support a complete operating system. In other words, it is like having an operating system installed on your computer that can be accessed as if it were just another program. Need to test something in Windows, just open up the Windows virtual machine and close it when done. With Sun/Oracle’s VirtalBox platform, installing and maintaining these virtual machines are easier than ever.

Getting Started

Setting up a virtual machine is actually really easy. It may seem intimidating at first, but if you can install Firefox on your computer then you can handle installing a virtual machine. The first thing to do is to download the operating system as well as the VirtualBox platform.

Download the Os

Download the operating system and save it somewhere on your computer. Generally, this is going to be an ISO file. CentOs has three ways to install. The first is by downloading seven (yes, seven!) different iso files. Avoid this at all costs, because mounting and unmounted seven different files during an OS install is quite annoying. The other options are a DVD or a net install. I prefer having a copy of the DVD, but the net install is approximately 10mb so it is really easy to download.

Download and Install VirtualBox

Head over to the VirtualBox download area and pick the version that matches your computer. You are selecting the version that will be installed on your computer. So if your computer is a Windows computer, select the Windows version.

Installing the Virtual Machine

VirtualBox’s setup wizard makes it really easy to install a Virtual Machine. Really easy. So easy, that this guide is pretty much useless.

Naming

Open VirtualBox and click the ‘New’ button in the top right. This will pop up the wizard.

For the name enter something really simple that describes the box. I usually enter the box’s host name such as ‘development1′.

Choose the best operating system/version that matches your install. For CentOs choose Operating System: Linux and Version: Red Hat.

Memory

The next step will be memory. Understanding how the virtual machine uses your systems memory is pretty important. Whenever the virtual machine is on it will immediately take up all the memory it was given. For example, if your computer has 2gb of memory and your virtual machine is set to use 1gb of memory then as soon as your virtual machine turns on 50% of your memory is in use. Assigning too much memory or leaving unnecessary virtual machines turned on is a great way too eat up your computer’s resources and make your system crawl.

VirtualBox shows a slider with the bounds for safe memory. Stay within the green and you will be fine. The amount of memory can always be changed later on.

virtualbox-memory

Hard Disk

Next we have the hard drive, which I generally keep small, around 8gb for CentOs. I find that this is more than enough space. VirtualBox also allows your virtual machines to access files on your computer’s hard drive, so sharing files that already exist on your computer is very easy.

Setup

Your machine is all setup, but right now it is a bare machine with no operating system installed. Before booting the machine, go into the settings (right next to the ‘New’ button). These are settings that can be changed whenever your virtual machine is off. I’d recommend browsing each of these sections and tweaking with the settings. It’s pretty hard to break anything here, so experiment and do whatever you think is best. Remember that you can always change these things later.

Network

One setting I recommend changing right away is the network. By default, VirtualBox uses a NAT network type. I like to use the bridge adapter network, because it will make the virtual machine act more like a computer on the network. With a bridged network the virtual machine will actually contact the router through your computer’s network card and obtain a new IP address. This makes accessing the machine services, like httpd, extremely easy.

Installing the Os

If we try to start the virtual machine we will get an error telling us that no bootable medium was found. This is because there is no OS installed. To install an OS start (boot) the virtual machine.

On the bottom right of the virtual machine’s window you should see a grayed out CD. Right click this CD and click ‘more CD images’.

Virtual Machine Options

Click the Add button and find the ISO file for the operating system you downloaded. Select that and then reboot the machine. Easiest way to reboot is to use the Menu Bar -> Machine -> Reset. Also Right Ctrl + R works.

Once your machine reboots you should be able to install the OS from the ISO you mounted. After your OS has installed you can use your new virtual machine as if it were a new computer.

PHP Seo – Sitemap and Robots.txt

by Ryan on March 19, 2010

PHP-Seo is a module that can plug into any application or framework to make SEO life a bit easier. Specifically, it provides an object oriented way of generating sitemap.xml and robots.txt files.

Download

php-seo.tar.gz
Github

Documentation

  1. Installation
  2. Creating a Sitemap
  3. Creating Robots.txt
  4. Unit Testing

Installation

After you have downloaded PHP-Seo you will need to add the library to the global include path. This can be done by:

set_include_path(
    get_include_path() . PATH_SEPARATOR .
    '/path/to/php-seo/library/'
);

Creating A Sitemap

Creating a sitemap is easy.

require_once 'PSeo/Sitemap/Xml.php';
 
$sitemap = new PSeo_Sitemap_Xml();
$sitemap->addUrl('http://www.potstuck.com');
$sitemap->addUrl('http://www.potstuck.com/category/programming/');
 
echo $sitemap->content();

Will output:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.potstuck.com</loc>
</url>
<url>
<loc>http://www.potstuck.com/category/programming/</loc>
</url>
</urlset>

When building a sitemap the only required field is a Url. However, there are other optional fields that you may wish to pass.

  • loc – The Url. (required)
  • lastmod – Last modification date.  In ISO 8601 or YYYY-MM-DD.
  • changefreq – How often the document changes: never, monthly, daily, always, etc.
  • priority – Range from 0.0 to 1.0, 1 being the most important

For the most part, only passing the Url (by using $sitemap->addUrl()) is sufficient. However if you would like to take advantage of the additional fields you can use addUrlData function by passing it an array. Example:

require_once 'PSeo/Sitemap/Xml.php';
 
$sitemap = new PSeo_Sitemap_Xml();
$sitemap->addUrlData(array(
    'loc' => 'http://www.potstuck.com',
    'lastmod' => '2010-03-15',
    'changefreq' => 'monthly',
    'priority' => '1.0'
));
 
echo $sitemap->content();

Will output:

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.potstuck.com</loc>
<lastmod>2010-03-15</lastmod>
<changefreq>monthly</changefreq>
<priority>1.0</priority>
</url>
</urlset>

You can generate a plain text sitemap by using the PSeo_Sitemap_Txt() class. A plain text sitemap is just a list of Urls.

// old
// require_once 'PSeo/Sitemap/Xml.php';
// $sitemap = new PSeo_Sitemap_Xml();
 
// new
require_once 'PSeo/Sitemap/Txt.php';
$sitemap = new PSeo_Sitemap_Txt();

Creating Robots

Creating a robots.txt is simple. By default, the User-Agent will be *, the path / will be allowed, and nothing will be disallowed. See the following code/output for a clearer picture.

require_once 'PSeo/Robots/Txt.php';
 
$robots = new PSeo_Robots_Txt();
 
echo $robots->content();

Will output:

User-Agent: *
Allow: /

You can of course change all of these settings by using the built in functions of the Robots class.

$robots->setUserAgent(‘User Agent’)
Use any string as a user agent

$robots->setSitemap(‘Url To Sitemap’)
Use the full domain and path to the sitemap, http:// included

$robots->allowUrl(‘Url’)
Allow a single url

$robots->blockUrl(‘Url’);
Block a single url

An Example

require_once 'PSeo/Robots/Txt.php';
 
$robots = new PSeo_Robots_Txt();
 
$robots->blockUrl('/private');
$robots->blockUrl('/wp-admin');
$robots->setSitemap('http://www.potstuck.com/sitemap.xml');
 
echo $robots->content();

Will output:

User-Agent: *
Disallow: /private
Disallow: /wp-admin
Allow: /
Sitemap: http://www.potstuck.com/sitemap.xml

Multiple User Agents

You may need to block and allow certain Urls for different User Agents. The best way to do this is by creating multiple robot objects for each agent. Example:

require_once 'PSeo/Robots/Txt.php';
 
$robotsBotA = new PSeo_Robots_Txt();
$robotsBotA->setUserAgent('Bot A');
$robotsBotA->blockUrl('/blockAAA');
 
$robotsBotB = new PSeo_Robots_Txt();
$robotsBotB->setUserAgent('Bot B');
$robotsBotB->blockUrl('/blockBBB');
 
echo $robotsBotA->content();
echo $robotsBotB->content();

Will output:

User-Agent: Bot A
Disallow: /blockAAA
Allow: /
User-Agent: Bot B
Disallow: /blockBBB
Allow: /

Unit Testing

PHP-Seo includes a test suite that will unit test the library. Running this test is simple:

[ryan@localhost]$ cd /path/to/php-seo/tests/
[ryan@localhost]$ phpunit AllTests
PHPUnit 3.3.17 by Sebastian Bergmann.
 
....................
 
Time: 0 seconds
 
OK (20 tests, 29 assertions)

Testing within your application
If you would like to test the library within your application, then inside of your test suite you can include the PHP-Seo test suite. To do this your AllTests file should look something like this:

require_once '/usr/share/php/php-seo/tests/AllTests.php';
 
class AllTests extends PHPUnit_Framework_TestSuite {
 
    public static function suite() {
 
        $suite = new AllTests();
 
        // your unit test suites here
 
        // test php-seo
        $suite->addTestSuite('PseoTests_AllTests');
 
        return $suite;
    }
}

Once this is done whenever you test your application the PHP-Seo library will be tested as well.

Zend Framework View Helpers

by Ryan on May 11, 2009

Zend Framework View Helpers allow developers to easily maintain view code, but many existing helpers are coded in very poor form. A few simple guidelines can vastly improve the way developers approach these helpers.

What is a View Helper

A view helper is simply an additional method added to the view object. The Zend Framework includes are number of very simple and easy to use view helpers.

<!-- Inside the View -->
<?= $this->partial('sidebar.phtml'); ?>

This partial view helper does exactly what you would expect it to, it displays the contents of sidebar.phtml onto the page.

Why Use a View Helper

Imagine having to include a bunch of files on a page without using the partial() view helper. The code would get messy pretty quickly since it would be filled with random file opens. The view helper makes it easier since it cuts down on copy-and-paste code and centralizes all logic specific to a certain process in one place. In other words, it keeps code DRY.

All developers have heard of “Fat Model Skinny Controller”, but when it comes to views there is no catch phrase rule of thumb. Many believe that views can be fat (lots of code).  Its perfectly fine for views to contain many lines of code, but high line count in views is often an indicator to add in view helpers.  Think of views in the skinniest way possible by putting every modular part of a page into a custom view helper.

View helpers should exist for any content that could possibly go onto more than one page. For example, a social networking site would have a page that lists all of your friends. The site would also want to display a user’s top ten friends on another page. This is the perfect use a view helper, which we will call friends().

What does a Zend Framework View Helper Look Like?

class My_View_Helper_Friends extends Zend_View_Helper_Abstract {
 
 public function friends() {
  return "hello friends!"
 }
 
}

This is a view helper in its simplest form. Adding this helper to an applicated can be done by calling Zend_View::addHelperPath().

To call this method from a view:

<h1>My Friends</h1>
<?= $this->friends() ?>
<!-- this will output 'hello friends!' -->

Use Chaining

The biggest problem with View Helpers in the Zend Framework Community is that most developers treat them as methods/functions rather than objects. Since they are defined in their own class developers really have no excuse for ignoring the added benefits that come with object oriented programming. Using methods and setters of an class is always going to be more maintainable than passing parameters to a function.

Parameters are messy. The friends helper could take a ton of parameters, such as: The number of friends to display, recent friends, old friends, male friends, female friends, friends in a certain city, it goes on-and-on-and-on. Does this look fun?

<h1>My Female Friends in Boston</h1>
<?= $this->friends(10, 'recent', 'female', $city120) ?>

The function is ugly, it’s impossible to remember the order of parameters, and what happens if another parameter is needed in the function in a few months from now. Refactoring this code is going to be painful.

More important, that function is going to be nearly impossible to unit test. All of the if statements, extra parameters, and default parameters are going to cause nightmares for any coder. The test cases are going to be filled with so much junk in order to test each little section of the function.

This code on the other hand is much easier to read, extremely easy to refactor, and simple to test:

<h1>My Bro Friends</h1>
<?= $this->friends()->show(12)->gender('Male') ?>

Write a render method, Don’t Call it

Its good practice to write a render() method that returns the HTML/final output to the view, but it sure is a pain to have to keep writing “->render()” at the end of each view helper call.

To avoid this use PHP’s magic method __toString().

public function render() {
 return "some html";
}
 
public function __toString() {
 return $this->render();
}

Now every time the helper is called with a short tag it will automatically be displayed.

Things to remember about View Helpers

  1. When chaining an object, the setter methods will have to return instances of the object.
  2. The Zend View object will retain all instances of view helpers. So all default values will have to be reset whenever the helper is called for a 2nd time. See method _defaultValues() below for an example.
  3. The render() method returns HTML/text/output.

Here is what the final friends() helper would look like:

class My_View_Helper_Friends extends Zend_View_Helper_Abstract {
 
 private $_show;
 private $_gender;
 
 public function friends() {
  $this->_defaultValues();
  return $this;
}
 
 private function _defaultValues() {
  $this->show(null);
  $this->gender(null);
 }
 
 public function show($show) {
  $this->show = $show;
  return $this;
 }
 
 public function gender($gender) {
  $this->gender= $gender;
  return $this;
 }
 
 public function render() {
  // .. replace with a method call to gather data based on whats been set
  return "these are my friends: " . $this->_finalOutput;
 }

My Experience

I pretty much put just about everything I can inside a view helper. I have no view that is over 100 lines of code. In fact, most of my pages are just a couple of lines, there are probably very few that contain more than 20 lines. There is a huge benefit here that has nothing to do with DRY principles or the object oriented properties I have mentioned in this article. In fact, it has very little to do with development, but everything to do with team flow:

When a view is skinny and has a majority of its ‘code’ moved into helpers the only thing that remains is text. Views with mostly text allow non technical people to easily edit (and even commit) the pages of your application.

More

Zend Framework View Reference
Devzone Article on Views

PHP Dependency Injection

by Ryan on January 8, 2009

Dependency injection is the answer to more maintainable, testable, modular code.

Every project has dependencies and the more complex the project is the more dependencies it will most likely have.  The most common dependency in today’s web application is the database and chances are if it goes down the application will all together stop working.  That is because the code is dependent on the database server, which is perfectly fine.  Not using a database server because it could one day crash is a bit ridiculous.  Even though the dependency has its flaws, it still makes life for the code, and thus the developer, a lot easier.

The problem with most dependencies is the way that code handles and interacts with them. What I really mean is the problem is in the code and not the dependency.  If you are not using dependency injection, chances are your code looks something like this:

class Book {
 
	public function __construct() {
 
		$registry  = RegistrySingleton::getInstance();
		$this->_database = $registry->database;
 
		// or
 
		global $databaseConnection;
		$this->_database = $database;
	}
 
}

The book object now is given full access to the database once it is constructed.  That is good, the book needs to be able to talk to the database and pull data.  The problem lies in the way the book gained its access.  In order for the book to be able to talk to the database the code must have an outside variable named $database, or worse, it must have a singleton pattern class (registry) object containing a record for a database connection.  If neither of these exist the book fails, making the code far from modular.

This raises the question, how exactly does the book get access to the database?  This is where inversion of control comes in.

In Hollywood a struggling actor does not call up a director and ask for a role in his next film.  No, the opposite happens.  The director calls up the actor and asks him to play the main character in his next movie.  Objects are struggling actors, they do not get to pick the roles they play, the director needs to tell them what to do.  Objects do not get to pick the outside systems they interact with, instead, the outside systems are given to the objects.  Remember this as Inversion of Control.

This is how a developer tells his objects how to interact with outside dependencies:

class Book {
 
	private $_databaseConnection;
 
	public function __construct() { }
 
	public function setDatabaseConnection($databaseConnection) {
		$this->_databaseConnection = $databaseConnection;
	}
 
}
$book = new Book();
$book->setDatabase($databaseConnection);

This code allows for the book class to be used in any web application.  The Book is no longer dependent on anything other than the developer supplying a database shortly after object creation.

This is, at its finest, dependency injection.  There are two common ways of injecting dependencies.  The first being constructor injection and the second being setter injection.  Constructor injection involves passing all of the dependencies as arguments when creating a new object.  The code would look something like this:

$book = new Book($databaseConnection, $configFile);

There are some issues with constructor injection. First, the more dependencies a class has the messier the constructor becomes. Passing in three or four dependencies all in a constructor is extremely hard to read. Also, the less work a constructor does the better.

This leaves us with our second method of dependency injection, setter injection. A dependency is set by using a public method inside the class.

$book = new Book();
$book->setDatabase($databaseConnection);
$book->setConfigFile($configFile);

This is easy to follow, but it leads writing more and more code for your application.  When a book object is created three lines of code are required.  If we have to inject another dependency, a 4th line of code is now needed.  This gets messy quickly.

The answer to this problem is a container, which is class that is designed to hold, create, and inject all the dependencies needed for an application or class.  Here is an example:

class Container {
 
	public static $_database;
 
	public static function makeBook() {
 
		$book = new Book();
		$book->setDatabase(self::$_database);
		// more injection...
 
		return $book;
	}
 
}

And then:

$book = Container::makeBook();

All dependencies should be registered into the container object during run time.  This object is now the gateway that all dependencies must pass through before they can interact with any classes.  This is the dependency container.

The reason makeBook is a public static function is for ease of use and global access.   When I started this article off I made a reference to the singleton pattern and global access being a poor choices of code.  They are, for the most part.  It is bad design when they control access, but it is perfectly ok when they control creation.  The makeBook function is only a shortcut for creation.  There is no dependency what-so-ever between the book class and the container class.  The container class exists so we can contain our dependencies in one location and automatically inject those dependencies with one line of code creation.

The container class removes all of the extra work of dependency injection. 

Before injection:

$book = new Book();

And now:

$book = Container::makeBook();

Hardly any extra work, but tons of extra benefits.

When test code is run, specifically unit tests, the goal is to see if a method of a class is working correctly.  Since the book class requires database access to read the book data it adds a whole layer of complexity.  The test has to acquire a database connection, pull data, and test it.  All of a sudden the test is no longer testing a single method in the book class, it is now also testing database.  If the database is offline, the test would fail.  This is far from the goal a unit test.

A way of dealing with this is just using a different database dependency for the unit tests.  When the test suite starts up a dummy database is injected into the book.  The dummy database will always have the data the developer expects it to have.  If a live database was used in a unit test the data could potentially change causing tests to unnecessarily fail. 

The code is more modular because it can dropped into any other web application.  Create the book object and inject a database connection with $book->setDatabase().  It does not matter if the database is in Registry::Database, $database, or $someRandomDatabaseVarible.  As long as there is a database connection the book will work inside any system.

The code is more maintainable because each object is given exactly what it needs.  If separate database connections are required between different instances of the same class then there no extra code needed inside the class what-so-ever.  Give book1 access to database1 and book2 access to database2.

Container::$_database = $ourDatabaseVarForDB1;
 
$book1 = Container::makeBook();
$book2 = Container::makeBook();
$book2->setDatabase($database2);

Dependency injection really is the answer to more maintainable, testable, modular code.


I titled this article PHP Dependency Injection, but there is really nothing in here that is specific to PHP.  The reason I choose to include PHP and write all of the code examples in PHP is because I constantly see PHP projects not using DI.  I believe the best place to teach good coding practices is in popular frameworks by forcing the users of the framework to develop within the guidelines of a certain pattern.  Take MVC for example, nowadays all developers understand it and most of the  underlying principles that accompany it.  This is because the frameworks they use force them to use MVC.

Also, please note that the code samples used in this article are just really simple examples to show the nuts and bolts of dependency injection and inversion of control. If you wish to implement injection into your project please take a look at an already built dependency injection framework.

Oh yeah, that would work

by Ryan on November 30, 2008

I came across Social History (code) today. In a nutshell, its a javascript plugin that allows you to see what social bookmarking sites each of your users visit. It removes the need of having to display a link to every social site on each of your pages. If a user doesn’t visit digg, don’t waste his screen space with a digg icon. Its a simple idea, it makes sense, and its genius.

More interesting, is how it works. It builds a list of links and puts them on the page somewhere, hidden, so the user cannot see them. Links that you have not visited are in blue, and links you have visited are in purple. The javascript then loops through all the links, and if a social bookmark site has a purple link, it knows you have visited it in the past.

Its nice to see this code being used in a productive way, but there is a pretty large privacy flaw that this code can easily start to abuse. Instead of tracking social bookmarking sites, it could be used to track sites you wouldn’t want anyone tracking, for example online banking sites, facebook pages, porn sites, and whatever else you want to keep private.

The good news is that it can only find the pages you have visited by asking your browser if you have visited a specific page. So in order for it to grab your entire history, it would have to ask your browser about each web page on the Internet, one by one. The bad news is that someone could pretty easily compile an extensive list of private web pages.

Personally, I say we patch this flaw. Lets stop displaying visited links in purple, unvisited links in blue. In other words, kill off a:visited. This is a pretty bold statement to make, but the security benefit outweighs the usability benefit in this scenario for me personally. It probably does for you too, when was the last time you went to a website and 1) saw the blue/purple links, and 2) thought ‘Oh good, I know which links of this site I’ve clicked and which ones I haven’t'? For me, that would be somewhere around 1999.

So yes, remove the a:visited property.