Made of Everything You're Not

Personal blog of PHP programmer Eric Lamb.
  • Blog
  • Portfolio

Stand Alone ExpressionEngine Authentication

Posted in Code, Programming on August 08th, 2011 by Eric Lamb – 1 Comments

I had a small task come to me recently wherein a site needed to allow for verification of ExpressionEngine credentials but couldn't use the normal controllers for access. The challenge was in how ExpressionEngine encrypts the passwords and replicating that behavior. Taking a look at the Login controllers made things very clear though; as usual ExpressionEngine was very well written.

Here's an example of how to do it (note that this will only work within the CP):

<?php
$user = 'test';
$pass = 'test';
$this->EE->db->select('members.password, members.unique_id, members.member_id, members.group_id, member_groups.can_access_cp');
$this->EE->db->where('username', $user);
$this->EE->db->where('member_groups.site_id', $this->EE->config->item('site_id'));
$this->EE->db->where('members.group_id = '.$this->EE->db->dbprefix('member_groups.group_id'));
$query = $this->EE->db->get(array('members', 'member_groups'));
if ($query->num_rows() != 0)
{
	$password = do_hash($pass);
	if ($query->row('password') == $password)
	{
		//good user credentials <img src="http://blog.ericlamb.net/images/smileys/smile.gif" width="19" height="19" alt="smile" style="border:0;" />
	}
	else
	{
		//bad password/good username
	}
}
else
{
	//bad username
}
 
?>

According to the site admin who passed this my way the above won't work outside the CP. He was kind enough to send along an example that worked fine for their situation:

<?php
$this->EE->load->library('auth');
$this->EE->lang->loadfile('login');
$authorized = $this->EE->auth->authenticate_username($this->EE->input->post('username'), $this->EE->input->post('password'));
if ( ! $authorized)
{
	set_status_header(500);
	exit(lang('unauthorized_request'));
}
?>

Customizing ExpressionEngine 2.x Message Pages

Posted in Brain Dump, Code, Programming on June 07th, 2011 by Eric Lamb – 0 Comments

An unfortunate issue with ExpressionEngine is how internal messaging is handled. It's really unfortunate that such a nice platform like ExpressionEngine shows such a wart when it comes to managing system pages and templates. Anyone who's ever had to modify the message pages can tell you; it's a dirty and counter intuitive deed requiring a lack of best practices that will leave you feeling pretty gross.

Customizing ExpressionEngine 2.x Message Pages

The current method of modifying the message pages works as you would expect; this being an ExpressionEngine site you just go to the Design section and you'll find them under "Message Pages" . There are 3 different types of message pages you can edit (Email Notifications, User Messages and Offline Template) and while it would seem logical on how what to do to get going you'd probably be wrong (if you hadn't ever tried before). There are a couple problems here...

First, you can't use EE template tags within those templates. It's the damnedest thing too because some of those templates (User Messages and Email Notifications) do allow specific tags; they just don't parse any others. So, if you're a good little programmer and you build your site using global embeds for building your templates (head & footer for example) you're hosed. Your only option is to hard code your HTML which, if you've built even a simple site, you'll instantly be filled with remorse and guilt over creating such a maintenance nightmare.

Second, and after the above it's a minor issue though if you're good enough for the above to be an issue this'll probably piss you off too; you can't save those templates as files. This means version control is going to be a bit of a problem. After nearly 10 years of having version control beat into me this hurt pretty bad. To be honest, because of tight deadline and even tighter budgets I could have lived with the guilt and shame of hard coding just to finish the project but taking away my version control was like adding insult to injury.

It's quite the head scratcher when you get right down to it; a smart and clever company redesigns their entire product from the ground up and completely drops the ball when it comes to the messaging system. It's a shame...

There is another option though it does require money; a really nice extension called Custom System Messages. The extension was written by Brian Litzinger and is available for $12 through the ExpressionEngine marketplace Devot:ee.

Custom System Messages

Custom System Messages works exactly as you would expect ExpressionEngine to work; through a nice interface you choose custom templates for specific messages. You can set a different template for both message scenarios (General Error and Form Submission Error) as well as change the behavior of the {link} template tag so it doesn't use the lame ass JavaScript "back link".

The best part though is that Custom System Messages allows you to set special templates based off of all the actions your site has (even those from other modules and extensions). So, for example, if you have a CartThrob site you can set a special template for when adding an item to your cart fails and separate template for when updating an item within a cart fails. It's really quite slick and for only $12 it's very reasonable. Priced just enough to dissuade any developer from rolling their own solution.

I do have to say how disappointing it is to see ExpressionEngine lacking this built in. To me, it's reminiscent of buying a car and being charged extra for the gas cap. Sure, I can just go buy a gas cap for a couple bucks but it really should be a part of the car to begin with.

Connect to Multiple Databases with Zend Framework

Posted in Brain Dump, Code, Programming on May 31st, 2011 by Eric Lamb – 3 Comments

I recently had a project where there would be 2 databases being used together; one locally and the other hosted externally by the client. Using traditional PHP this wouldn't be a problem (just pass a link to the database I want to use on a per query basis and I'm done), but, since this project was to use the Zend Framework and I'd never attempted this sort of thing before with it, I was in quite the pickle.

Doing some quick Googling turned up an article that seemed to fit the bill: Zend Framework: Connecting to 2 databases written by Wenbert Del Rosario. Unfortunately though, while it was a good read and very informative, my circumstances were a little different. The database I had to connect to was hosted on an external network that I wouldn't have local access to. I had to go over the wide Internet to connect. Using Wenbert's tutorial would entail a constant connection on every request whether it needed it or not and that just wouldn't do.

Anyone who's ever had to connect to an external database can tell you it's far from an ideal scenario. The latency involved with this strategy is noticeable and caching is pretty much required for any sane strategy. Still, Wenbert's article was definitely helpful for developing my strategy.

As in Wenbert's article I started with putting the connection information into my config.ini file

//config.ini
resources.db.adapter = PDO_MYSQL
resources.db.params.host = localhost
resources.db.params.username = ****
resources.db.params.password = ****
resources.db.params.dbname = local_db 
 
externaldb.adapter = PDO_MYSQL
externaldb.params.host = example.com
externaldb.params.username = ****
externaldb.params.password = ****
externaldb.params.dbname = external_db

Then, I created a standard Zend_Db_Table class that handled the connection:

<?php
//Model/DbTable/External.php
//name made up to protect the client but do yourself a favor and name your shit logically
class Model_DbTable_External extends Model_DbTable_Abstract
{
   /**
     * Doesn't matter for use but ZF demands a $_name variable
     * @var string
     */
	protected $_name = "content";
 
	public function init()
	{
		$settings = Zend_Registry::get('settings');
		$this->db = Zend_Db::factory($settings, $settings);
 
	}
}
?>

With the above out of the way I can now connect to the external database. I just have to pipe all my SQL through the above class. To that end, and to provide a nice wrapper for the caching, I create a Model that has methods for all the SQL my app will need:

<?php
class Model_External extends Model_Abstract
{
	/**
	 * The key to use for the cache items
	 * @var string
	 */
	public $cache_key = 'external_db';
 
	public function __construct()
	{
		parent::__construct();
		$db = new Model_DbTable_External;
		$this->db = $db->db;
	}
 
	public function testSystem($id)
	{
		$key = $cache_key.__FUNCTION__.$id;
		if(!$data = $this->cache->load($key))
		{
			//just a random query with joins and whatnots to show  it's possible <img src="http://blog.ericlamb.net/images/smileys/smile.gif" width="19" height="19" alt="smile" style="border:0;" />
			$sql = $this->db->select()->from(array('e' => 'example_table1'), array('e.id', 'e.title'))->where('e.id = ?', $id)->limit('6');
			$data = $this->db->fetchAll($sql);
			$this->cache->save($data, $key, $this->cache_key));
		}
		return $data;
	}
}
?>

So, using the above class I've abstracted out the SQL and provided caching through the below class Model_Abstract:

<?php
//models/Abstract.php
abstract class Model_Abstract
{
	/**
	 * The database object
	 * @var object
	 */
	public $db;
 
	/**
	 * The Cache Object
	 * @var object
	 */
	public $cache;
 
	/**
	 * The stored cache name
	 * @var string
	 */
	public $cache_key = null;
 
	public function __construct()
	{
		$c = new Model_Cache;
		// getting a Zend_Cache_Core object
		$this->cache = Zend_Cache::factory(
	                    'Core',
	                    'File',
	                    array('lifetime' => 720, 'automatic_serialization' => true),
	                    array('cache_dir' => '/path/to/cache/')
		);
	}
}
?>

Putting it all together I now have a mechanism to connect to an external database, perform queries against said database and can cache the results pretty easily and with minimal code. One of the advantages of this approach is that connections to the database only happen when needed instead of on every page request as in Wenbert's article. So, for example, so long as the cached items exist then no database connection is created and no latency (outside of hitting the filesystem of course) is created.

Still though, there are ways to improve on this approach. For example, using APC instead of the file system for the caching would help as would increasing the cache lifetime from 2 hours to something more but, overall, the above should be a good starting point.

CartThrob 2.0 Beta Fun

Posted in Brain Dump, Code, Programming on May 26th, 2011 by Eric Lamb – 1 Comments

About a year ago I reviewed various shopping cart platforms for what was to be an "upcoming" project. After numerous delays and client hand holding (with the requisite back and forth) one year later that project finally began. And, as has lately become a trend in my professional life, the client's spec combined with a drastically shortened and accelerated deadline forced us to go with something completely unknown and with only cursory inspection; the 3rd party e-commerce ExpressionEngine module CartThrob 2.0 (beta at the time of this review BTW).

CartThrob

Of course this presented the problem of actually using an unknown package to build a site with. Thankfully though, while CartThrob has a steep learning curve and is most certainly missing key functionality, it's an overall nice package that allowed us to do what we needed. Sure, there's pain involved (lots of configuration, testing and set up) but with a little elbow grease it all worked out.

As mentioned, CartThrob is an ExpressionEngine module for managing an online store. It's available for both ExpressionEngine branches (1.x and 2.x) and was voted Module of the Year by Devot:ee in 2010 (for the 1.x version only). This being an ExpressionEngine project CartThrob would, in theory, be a nice fit.

One of the really nice things about using CartThrob is that it uses the ExpressionEngine admin panel for managing your store. This meant there wouldn't be a second administration site that the client would have to learn. (Personally, I always found dual admins to be janky at best and sloppy/lazy at worst so this was a definite bonus in favor CartThrob.)

But this is also double edged because, well, pretty much everything about your store is saved into the entries system within ExpressionEngine. This, of course, causes your Entries panel to become an eye sore whenever you have to do anything there. Instead of having a dedicated section to manage products you use the Entries section. Instead of a dedicated section to manage your orders you use the Entries section. Instead of a dedicated section to manage... well, you get the idea; everything is managed through the entries. This makes sense for the product management but when you have to dig through entries to find orders and coupons and discounts (etc) things get a little jarring for some people (even internally with my team) so it's a concern.

Still, single freaking admin so it was kind of a lesser evil compromise.

The unusual thing though is that, for how thoroughly the management of items was punted (though, to be fair, it looks to be a feature versus bug debate more than "punting"), CartThrob has an extremely deep configuration section where you can customize CartThrob to function just right. CartThrob has all the basic customization functionality one would expect from any modern shopping cart platform (tax, shipping, payments with lots of merchant options, etc) plus a bunch of settings just to get CartThrob working (CartThrob is NOT an out of the box solution). It's all presented in an easy to use interface that's designed to mesh with the ExpressionEngine administration panel design which makes for an easier experience.

As far as merchant accounts go (for accepting payments through your site) there's the usual suspects of Authorize.net, Paypal and SagePay built right in but also some offline solutions for pay by check and credit accounts. For this project we used Authorize.net which went smooth for the most part but I can't speak for the other options though if they're anything like the Authorize.net one they're probably cool. CartThrob also includes some extensions and hooks so writing your own payment gateway is possible if you need.

CartThrob can also hook into the ExpressionEngine member module so your customers can be registered internally. Like pretty much everything else with CartThrob there's a bit of configuration involved to get it up and working though. Unfortunately though, there's not really any out of the box functionality for your members to take advantage of. For example, there isn't any way for your customers to view their past orders when logged in and when using the control panel and viewing a member's profile there's no relationship with CartThrob. You're gonna have to write all that stuff yourself but, and I don't know why, but CartThrob doesn't store any relationships between ExpressionEngine members and it's customers so expect a challenge.

In terms of the user side, the actual storefront, everything is done using ExpressionEngine templates and template tags. There are lots of module methods available and even though it's far from a complete package of the expected functionality. In fact, on our team, we got into a habit of thinking of CartThrob as a Lego set for creating what we want instead of having what we want already.

For example, to view the details about a users cart you'd use the template code below:

&#123;exp:cartthrob:cart_info&#125;
	{total_items} 
	{total_unique_items} 
	{cart_entry_ids} 
	{cart_shipping} 
	{cart_tax_rate} 
	{cart_tax} 
	{cart_subtotal} 
	{cart_total} 
&#123;/exp:cartthrob:cart_info&#125;

On the surface this appears to be nice because it keeps things within the core ExpressionEngine development process. And it would be except, well, CartThrob isn't abstract enough. Too many times I would try to do something that seemed obvious, like checking for shippable items within a users cart, and would come up short; that functionality doesn't exist.

Still though, don't get me wrong. Yes, some of the above sucks. Absolutely. But CartThrob is still under development. Plus, since it's a commercial script ($99) there's financial incentive to improve it. And, truth be told, for as painful as certain points were it's still way more fun to build a site with CartThrob than most of the other options I've used or reviewed like OpenCart or Avactis.

Plus, again, single freaking admin!

ExpressionEngine and the Mystery of 00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr

Posted in Brain Dump, Code, Programming on May 03rd, 2011 by Eric Lamb – 2 Comments

Recently, I came across a weird issue while developing an ExpressionEngine 2.0 module. The issue was that, for some reason, my module would output a random string instead of the intended content. For example, instead of displaying the HTML, that the module created, the module would display the string M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr instead. Tracking down this issue was symptomatic of the proverbial needle in a haystack but I learned a lot about how ExpressionEngine's internals work and was once again reminded to be pragmatic about my development strategies.

random, the lion

My first and automatic reaction when coming up against some random and meaningless output string is to just Google it and see what happens. Unfortunately though, this particular search, at the time at least, returned around 35,000 sites that were outputting the string and only 1 that had a reference to the issue with a possible explanation. All of a a sudden this became an actual thing.

Putting aside the fact that there are around 35,000 sites with the string within Google for the moment (and that's really a problem to be discussed) it took a bunch of digging but I finally found a few things:

First, this is an issue that has been within ExpressionEngine for years. Doing a search on the ExpressionEngine site lists the first entry of this string at 2007 (sorry for the lack of a link; ExpressionEngine search is cached so old search URLs don't work sometimes). My initial reaction was that this was kind of sloppy; EllisLab updated ExpressionEngine to 2.0 recently, from the ground up to use CodeIgniter I believe, yet this issue got ported over?

After doing further research though, I came to believe the above is more to do with the design of ExpressionEngine than anything else like copying code. Turns out, there's some logic to that random and oblique string.

Basically, that string (M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr) is a template holder for the content you want to output. It's a little complicated in how it works but thanks to Derek Jones over at the ExpressionEngine forums there's a succinct, though still a little complicated but less complicated than I could explain it, explanation of what's going on.

...

The template parser is an extremely complex gizmo, so let me try to explain it stripped of what techno mumbo jumbo I can. This will still be long, so bear with me.

The template parser intelligently saves on resources by only processing a given tag once, no matter how many times it occurs on the template. This means that if your tag is exactly the same, including its tagdata, EE only execute’s that modules code once, and replaces all copies of that tag with the output.

So first, when the template parser goes through the template finding tags, it replaces them all with temporary markers (the gibberish), and adds each tag to a list of tags to be parsed, in the order they are encountered on the template, top down. Each marker starts with the letter “M” followed by the number (starting at 0) that tag is sitting in on The List.

Second, the parser goes down its list of tags. It parses tag #0, and then replaces all of #0’s marker with that tag’s output.

——————-

Ok that’s the setup. Here’s why it affected you, and why this side effect is not a problem (and also extremely, extremely rare). Remember, top down, tags will be assigned 0, 1, 2, etc. So I’m abstracting it out to show the nesting and the positioning only. Just focus on the numbers.

&#123;exp:tag0&#125;foo&#123;/exp:tag0&#125;
&#123;exp:tag1&#125;
    bar
    &#123;exp:tag0&#125;foo&#123;/exp:tag0&#125;
&#123;/exp:tag1&#125;

Step 1, the tags are grabbed and replaced with markers. The first tag encountered is replaced first.

M0
&#123;exp:tag1&#125;
    bar
    M0
&#123;/exp:tag1&#125;

And then the next tag:

M0
M1

All tags have been collected and put on The List, so step 2, the parser goes down The List, and parses tag #0:

foo
M1

See the problem? The second M0 is sitting protected inside the marker for tag #1, so it doesn’t get replaced. Then tag #1 gets parsed.

foo
    bar
    M0

And the marker is left in the output. EE doesn’t go back and parse tag #0 again, it’s already done that once, and will not do it again.

So the circumstances required for this problem to exist each are uncommon, and combined, very very rare:

1) Multiple exact copies of a given tag
2) One or more copies nested inside another tag (tag nesting itself is also rare, and usually not recommended)
3) The tag of which there are copies must sit at a position in the template above any occurrences of it being nested in another tag.

From the above it was easy to conclude that the template parsing stuff was breaking down in my module. Why, I had no idea, but at least I had a known starting point. While it was easy to conclude that my issue lay with the template parsing though, it was 100% off point for my particular issue which had to do with, of all things, the case of the module name. But, I digress.

The point is that for years now, and through multiple versions and rewrites, ExpressionEngine has consistently carried the same "issue". Understanding the intent of the design for the template parsing helps put some perspective on things: it's definitely a side effect of the particular approach. It bugged, and surprised, me that ExpressionEngine would have such oblique and useless output on such a widespread basis (35,000 site's with that string within Google is a bit much in my opinion) but the more I thought about it the more I came to understand the complexity of what was involved in being helpful when the issue cropped up. Aside from abandoning the approach what could really be done?

It's a nice reminder that development is often a balancing act between getting what you want and dealing with a counter issue. The ExpressionEngine team developed a strategy to enable them to effectively and efficiently meet their requirements but there's sometimes an issue; a random string gets output instead of the template data. Plus, since the cause could be for anything from bad module installation data (as I had) to an issue within a template there's no real way to provide helpful error messages when the template parsing does fail. But, on the other hand, the template parser does exactly what it was designed to do (and it does it well).

Which would you choose?

Custom Routes With Zend Framework

Posted in Brain Dump, Code, Programming on April 08th, 2011 by Eric Lamb – 3 Comments

When I first started using the Zend Framework I didn't give much thought into the way it handles routing URLs to the controllers/action combo. Honestly, while I had become used to so called search engine friendly, or pretty, URLs, I grew up on query strings where the idea of URLs was more about function than form. So when I moved over to Zend Framework as a framework I didn't give a damn how the URLs were parsed and routed to which controller/action. I just accepted the natural order of things.

Road Signs by orudge

Recently though, I took on a project to build a sort of quick and dirty CMS with a couple unique requirements:

  1. It had to use the Zend Framework
  2. URLs would be broken down into a /category/page/subpage scheme.

This was the first time I've ever had a client demand a project use the Zend Framework. Pretty cool. But, this presented a problem because, as mentioned above, by default the Zend Framework has URL schemes based on the controller and action you're looking to access like /controller/action/. This just wouldn't work.

Since the clients URLs would mostly be based on user generated strings, what we were calling URL slugs, the default routing scheme just wouldn't do. I say mostly because there were other areas of the project that would use the normal scheme for a couple modules. Either way, thankfully, using Zend_Controller_Router_Route made this pretty much a snap (a little head bashing but not too much).

First though, a little background. Because of the above requirement from the client on URL schemes, I was thinking the best thing to do was to route all user generated URLs to to a single controller and handle the rest from there. I looked but there didn't seem to be any easy way to route all URLs except the specific modules I wanted to exclude which meant I had to pull out the categories and iterate over them to create each route individually. (If anyone knows of a way to reverse the design and create a route for everything but certain strings let me know.)

To do this, in my bootstrap class I just created a new _init function like the below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//bootstrap
public function _initRoutes()
{
	$url_data = $this->cat->getCategoryUrls();
	$frontController = Zend_Controller_Front::getInstance();
	$router = $frontController->getRouter();
	foreach($url_data AS $url)
	{
 
		$route = new Zend_Controller_Router_Route (
			$url.'/*',
			array('controller' => 'pages',
			'action' => 'index')
		);
 
		$router->addRoute($url, $route);
	}
}

In a nutshell, all the above is doing is looping over an array of category URL slugs and adding a custom route for each category that sends all requests to the Pages controller and the Index action. From there I parse the URL and proceed accordingly for the rest of the module.

For this example I'm doing a couple thing; using the Zend_Controller_Router_Route class and using wild cards (*). The Zend_Controller_Router_Route class takes two parameters, the first being the route and the second being an array of options (I'm only passing the controller and action but it's possible to send others). For the route, and because it's using the wildcard (*), I'm basically saying take any requests for the "url_slug" and anything after it and use the controller "Pages" and the "Index" action to handle everything.

After passing the Zend_Controller_Router_Route object to the $router, passing the unique name for the route as the first parameter, I was good to go.

That said, there's a lot more that can be done with the custom routing stuff within the Zend Framework above what's outlined above. There's a pretty good article by Jason Gilmore that goes into some detail into how to create default URL parameters to make the URLs look even prettier. Definitely worth checking out.

Practical PHP Reflection

Posted in Brain Dump, Code, Programming on March 01st, 2011 by Eric Lamb – 13 Comments

The Reflection API in PHP is one of those language features that can kind of creep up on you; it's just not needed for a vast majority of projects. In fact, I'd wager there are a bunch of professional developers who have never had to make use of the Reflection API. Hell, I spent 8 years writing code professionally before I ever had to use it (though, because of some unrelated .NET research I was peripherally aware of it). It's just not something that really comes up all that often in the day to day coding tasks.

Then, one day, out of nowhere, it comes up. The perfect problem where the Reflection API appears to be the perfect solution. For me this came up a couple months ago while I was working on a European zip code radius project that had to be built using one of those obfuscated and ill documented 3rd party commercial programs (nothing worse than when the platform is forced on you). So, I had to use this program that was intentionally encoded to prevent me from doing what I wanted to do. I couldn't even look at the code; it was completely obfuscated.

Before getting into things it should be noted that the Reflection API is capable above and beyond what I'm outlining; usually for the kind of high level stuff like core Zend Framework components and anything you'd want way abstracted.

So, yeah, weird problem.

This is where reflection comes in for me. It was made for problems like the above; according to the manual:

PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions, methods and extensions. Additionally, the reflection API offers ways to retrieve doc comments for functions, classes and methods.

So, the theory was that I could use the Reflection API to look into the obfuscated code and get some insight into what was going on and what I had to work with. I figured that, at the least, if I could see what methods, properties and comments the code had; maybe I'd get some clue about what the code was about. Using, for example, the internal PHP class "SimpleXMLElement" it's real simple to get a nice map of the class by calling the class ReflectionClass and passing the name of the class you want to get details on as a parameter like the below:

1
2
3
4
<?php
$reflector = new ReflectionClass("SimpleXMLElement");
echo $reflector;
?>

The above outputs an eye gouging but verbose class map:

Class  {
 
  - Constants  {
  }
 
  - Static properties  {
  }
 
  - Static methods  {
  }
 
  - Properties  {
  }
 
  - Methods  {
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
 
    Method  {
    }
  }
}

As you can see, the above lists every property, method and constant about a class along with any parent classes and interfaces. If there were any variables the methods accepted it would also list those as well but SimpleXMLElement doesn't have any.

It's also possible to get the individual elements on a one by one basis while using the ReflectionClass object; for example the below methods returns the class name, any comments (if they're in docblock format), the constants, parent class, constructor and default properties for the class DateTime.

<?php
$reflector = new ReflectionClass("DateTime");
echo "Class name: ".$reflector->getName()."\n";
echo "Doc Comment:".var_dump($reflector->getDocComment())."\n";
echo "Contants: ".var_dump($reflector->getConstants())."\n";
echo "Parent Class: ".var_dump($reflector->getParentClass())."\n";
echo "Constructor: ".var_dump($reflector->getConstructor())."\n";
echo "Default Properties: ".var_dump($reflector->getDefaultProperties())."\n";
?>

Outputs

Class name: DateTime
Doc Comment: bool(false)
Contants: array(11) {
  =>
  string(13) "Y-m-d\TH:i:sP"
  =>
  string(16) "l, d-M-y H:i:s T"
  =>
  string(13) "Y-m-d\TH:i:sO"
  =>
  string(16) "D, d M y H:i:s O"
  =>
  string(16) "l, d-M-y H:i:s T"
  =>
  string(16) "D, d M y H:i:s O"
  =>
  string(16) "D, d M Y H:i:s O"
  =>
  string(16) "D, d M Y H:i:s O"
  =>
  string(13) "Y-m-d\TH:i:sP"
  =>
  string(16) "D, d M Y H:i:s O"
  =>
  string(13) "Y-m-d\TH:i:sP"
}
 
Parent Class: bool(false)
Constructor: object(ReflectionMethod)#2 (2) {
  =>
  string(11) "__construct"
  =>
  string(8) "DateTime"
}
Default Properties: array(0) {
}

Check out the documentation; there are a bunch of other details you can get from other methods.

This is really just the tip of the iceberg though. There are other classes that allow even deeper insight into functions, methods, extensions and much more. Definitely worth checking out.

The Lesson of Adobe Reader

Posted in Programming, Rant on February 25th, 2011 by Eric Lamb – 0 Comments

One of my favorite parts about programming is the design part of a project. No, not the pretty sparkly pretty design; I know I suck ass at that and it's just a bad idea for me to even attempt. Instead, I like the part where the program itself gets designed; the part where the order of things gets worked out and you, the programmer, gets to be creative and connect A to B to C on all the parts that were left out of the scope.  Sure, you know you need to add, for example, a form to a webpage but unless anyone told you how it should be written it's entirely up to you how to do it; that's the good stuff.

There are all sorts of places people go to sharpen their program design skills, which, and let's not kid ourselves here,  is a way subjective but difficult specialty; personal favorites of mine are sites like Gamasutra, which has a great postmortem section, and The Daily WTF, books about projects like Dreaming in Code and Showstopper! and, to look at how other programs function and what other people like or dislike about that program, Reddit (of all places).

One of the better posts I've seen on Reddit, in regards to insight, was for Adobe Reader. On Reddit the question of why Adobe Reader is constantly updated is often asked but, what with the hive mind and all coming to the proper conclusions, is almost always linked to the "correct" answer:

Ok.. here is a comment from somebory who knows his shit:

the adobe reader you have isnt a simple PDF reader.

TL;DR: Adobe Reader is a huge system and reading PDFs is one of its many functions. If all you care is reading PFDs only then you should ditch it and get Sumatra or Foxit.

Long version:

lets follow the rabbit..

There is a reason its not called "Adobe PDF reader" but "Acrobat reader" or "Adobe reader". It is a monster of a system.
reading PDFs is one of many functions.
For a project i had to read into adobe acrobat and heck its a real monster: it has

a complete mail server, document lifecycle management system, DRM client, full fledged document tracking system, form capabilities, statistics for your docs (imagine sending a survey and tracking the collected data), video AND audio playing capabilities (yes you can embed audio and video in pdf) as well as capabilites for other formats (such as displaying CAD(!) data in its own 3Dviewer).

all in all the full acrobat SDK is like 500 MB and its manual a couple tousand pages long.

merely displaying PDFs is one function out of like 100.
To you as the consumer its the bait... but the full fledged system behind it is what Adobe sells to its corporate consumers.

they basically say: "You want a full fledged content tracking system? we got it... and the best part is all your customers have the clients already installed! in form of the acrobat reader".

Its like a monster sleeping in every computer.

see this link. Its the function comparisson of the acrobat family..

and here comes the scoop: all functions you see are supported by acrobat reader... but you cant use them. They are there so you can provide them to the guys who paid for "pro extended".

Basically the pro extended package can create all that shit and all drones using acrobat reader will support the functionality. wheter they want it or not.

And here is the screamer: being a normal guy you will most likely never need all that crap. You know what does it mean when i say " document tracking system"? its just a fancy word for the dream of every adverstiser : Corporate customers can track how succesful their
newsletter, advertising and customer Polls are.

Yup.. they can track how efficient their spam is. And all you sheeples who over the years keep complaining "omg i just want to read pdfs why is the install file soo big" never cared to actually read what is included.

My advice: if all you care for is reading PDFs (and im sure 99% of Acrobat reader users are in this group) install Foxit or Sumatra.

That's just poor design right there; forcing a large percentage of your users to suffer a poor experience for the benefit of a smaller portion of users is just flat out dumb and one of those decisions I'm fairly certain couldn't be made by a team that's dogfooding their project. It's just basic math; make life easier on the majority.

The ExpressionEngine Caching Solution

Posted in Code, Programming on January 03rd, 2011 by Eric Lamb – 0 Comments

I've been hard at work on a dynamic navigation system for an ExpressionEngine project this last week. The project has been a lot of fun in all the right ways; complicated, technical and way outside my comfort zone. Basically, the project was to build a suckerfish style navigation bar using jQuery, superfish (a jQuery implementation of suckerfist) and ExpressionEngine. And therein lies the issue...

I had anticipated making the nav all efficient-like with a single query to pull out all the items and build the nav using unordered lists. I started doubting this as a good idea though when I came to learn how complicated the data model was for this particular project. Now, don't get me wrong, ExpressionEngine by itself is a blank slate when it comes to the data model for a project and, technically, they have a good and normalized structure for everything. Which was the problem.

An ExpressionEngine site is traditionally (at least as far as the sites I've seen and learned from) broken up like the below:

Weblogs
    Categories
        Entries
            Sub-Entries...

So, weblogs have categories which have entries attached to them which, in turn, can have sub-entries. Pretty straightforward I think but when you consider that this all represents around 6 tables that would require some pretty complex joins it's one of those cases where the "right" way isn't the ideal way. On the other hand, breaking the SQL up into multiple queries done in a loop is usually a pretty bad idea especially when you don't know how many times the loop is going to occur.

So, I was fucked with 2 crappy choices and needed to pick the least evil; I settled on looping queries with the caveat of caching. This was ideal because the cache could be set to a pretty large interval so the nasty SQL wouldn't execute but once a week or so. Having never worked with the native caching mechanism within ExpressionEngine learning about it became the new problem.

To be honest, I'm a little embarrassed that I didn't delve into learning about this sooner; it turns out ExpressionEngine has a few different caching options available built right in. I'm pretty new to ExpressionEngine, having only been developing with it for a few months, but it was pretty lame that I didn't immediately look into this option. There are so many problems the built in caching would have solved :/

Query Caching in ExpressionEngine stores the output of certain database queries to a flat file (in fact, all the caching mechanisms store the cache as a flat file). It has to be manually turned on in the administration panel but once it is turned on you're good; all the queries that can be cached will be cached in (what else?) the cache directory. It should be noted that EllisLab doesn't recommend using Query Caching because it's much more effective to just turn on the native caching in MySQL itself.

Tag Caching is useful for storing the output of ExpressionEngine tags on a tag by tag basis. Tag Caching allows for very granular caching so you can have certain portions of a page cached while leaving others completely dynamic. It should noted that Tag Caching only works on ExpressionEngine tags and, unless it's coded for caching, won't have any effect on plugins or extensions.

To enable Tag Caching all you have to do is add "caching='true' refresh='60'" to any ExpressionEngine tag like the below:

&#123;exp:channel:entries cache="yes" refresh="30"&#125;

The first parameter just tells ExpressionEngine to turn caching on for the tag; the second is the amount of time, in minutes, to keep the cache active before it is refreshed. Pretty simple really though depending on how many tags you're trying to cache it could be a bitch to implement I think.

Template Caching is what I think of as the most effective caching mechanism ExpressionEngine has to offer. Essentially, ExpressionEngine saves the entire output of a template to a flat file. The really cool thing is that ExpressionEngine caches not only most of the output for most EE Tags used (like the above) but also any php you may have added as well.

It's a little misleading to say that it's perfect though; there are a quirk to how it works. The entire, processed, template doesn't get cached just the heavy database or PHP stuff does; any EE Tag for conditional logic and URLs are still processed after the fact. Not a thing that's initially worrisome though that may depend on the circumstances of the project.

jQuery HoverIntent

Posted in Code, Programming on December 06th, 2010 by Eric Lamb – 2 Comments

I had a project recently to build a custom tooltip for a client site. The spec called for something the opposite of out of the box so it would have to be done as a custom job; no single off the shelf plugin would work here. There was one in particular that I was really stoked I could use to make development a lot easier; hoverIntent.

When I started thinking about how to approach this project an immediate worry I had was how to bypass the snappiness of the default jquery hover behavior. As you'd probably expect it's perfect, which sums up my problem; the project requirements called for an ajax tooltip which means every time it was activated a call to the server would happen. This would SUCK if it happened too much for basic performance reasons so it was important that there wasn't any unnecessary server calls. Using the default behavior a user just dragging their mouse over the links would make a server call. This was no good.

Off the top of my head the best way to handle this situation was to write in some timers to delay the server call and add in some checks. Frankly though, I'm much too lazy for all that so I hit up my goto source for all code related head scratchers: StackOverflow. There I heard about hoverIntent; a great plugin which handles all of the above and then some.

In a nutshell, hoverIntent works by replacing the normal calls to "hover" with "hoverIntent" with the same parameters as "hover". A basic example of both techniques would be:

//default jquery hover usage
$("#demo1 li").hover( overCallBack, outCallBack );
 
//default jquery hover usage
$("#demo1 li").hoverIntent( overCallBack, outCallBack );

Note that there are 2 parameters that can be passed and they're the same regardless of whether you're using "hover" or "hoverIntent"; both are functions with the first being the over state (when the user mouses over the item) and the second being the out state (when the user moves their mouse off the item).

The above is the easiest and fastest way to use hoverIntent but there's another, better, method that allows for much more customization. By passing hoverIntent and single object you can customize how the plugin behaves. hoverIntent allows for customization of the sensitivity and the interval, which according to the official site means:

timeout:
A simple delay, in milliseconds, before the "out" function is called. If the user mouses back over the element before the timeout has expired the "out" function will not be called (nor will the "over" function be called). This is primarily to protect against sloppy/human mousing trajectories that temporarily (and unintentionally) take

sensitivity:
If the mouse travels fewer than this number of pixels between polling intervals, then the "over" function will be called. With the minimum sensitivity threshold of 1, the mouse must not move between polling intervals. With higher sensitivity thresholds you are more likely to receive a false positive. Default sensitivity: 7

interval:
The number of milliseconds hoverIntent waits between reading/comparing mouse coordinates. When the user's mouse first enters the element its coordinates are recorded. The soonest the "over" function can be called is after a single polling interval. Setting the polling interval higher will increase the delay before the first possible "over" call, but also increases the time to the next point of comparison. Default interval: 100

The below example illustrates how the object should be created and passed.

var settings = {
    sensitivity: 4,
    interval: 75,
    over: overCallBack,
    out: outCallBack
};
$("#demo1 li").hoverIntent( settings );

And there you go; a better way to handle hovering over elements with jquery.

« Older Entries
  • Subscribe: Entries | Comments
  • About Me

    Email Email
    Twitter Twitter
    310.739.3322
  • Categories

    • Brain Dump
    • Business
    • Code
    • IT
    • Programming
    • Rant
    • Servers
  • Archives

    • February 2012
    • October 2011
    • August 2011
    • July 2011
    • June 2011
    • May 2011
    • April 2011
    • March 2011
    • February 2011
    • January 2011
    • December 2010
    • November 2010
    • October 2010
    • September 2010
    • August 2010
    • July 2010
    • June 2010
    • May 2010
    • April 2010
    • March 2010
    • February 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • September 2009
    • August 2009
    • July 2009
    • June 2009
    • May 2009
    • April 2009
    • March 2009
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008
  • Advertisement

Copyright © 2008 - 2018 Eric Lamb - All rights reserved