Made of Everything You're Not

Professional(?!?!) blog of Eric Lamb.
  • Home
  • Projects
  • Portfolio
  • Resume

Posts Tagged ‘php’

Stand Alone ExpressionEngine Authentication

Posted in Code, Programming on August 8th, 2011 by Eric Lamb – 1 Comment

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 :)
	}
	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'));
}
?>
Bookmark and Share

Importing Legacy Users Into ExpressionEngine

Posted in Brain Dump, Code on July 21st, 2011 by Eric Lamb – 2 Comments

Fuck. We spent all this time convincing one of the oldest clients with the agency into upgrading their old and kludgy, PHP 3 era, nightmare website into a snazzy ExpressionEngine 2.2 gem of modern technology. But, like the assholes we are, we didn’t quite think through the fact that they have a complicated data structure (having been built when PHP really sucked) that we’d have to import into ExpressionEngine. So, you know, fuck…

But then, after the pants come on and a moment to reflect is had and the obviousness of the overreaction becomes clear. This is ExpressionEngine after all; there’s bound to be some utility available to handle this with the least amount of pain possible. And there is: the Member Import Utility and, even better, it’s included into the core of ExpressionEngine so it’s already there.

And in traditional ExpressionEngine fashion its built in much the same and logical way most would design an import system. There are two different modes to work with: one to import an ExpressionEngine Member XML file and another to create said file from a CSV formatted file.

The CSV format conversion wasn’t really all that for the purposes of this project (mostly due to conditional rewriting of specific column entries) but it does have it’s uses. For instance, with smaller, self contained, exports it should be a snap to easily hand over the export straight from phpMyAdmin and convert it into an ExpressionEngine Member XML file. One big drawback though is that the CSV import doesn’t appear to create new custom member fields on import so manual mapping is required per import.

The flip side of the CSV format convertor is the straight ExpressionEngine Member XML import utility. The big drag with this, and only if you don’t use the CSV convertor, is that a script has to be written to handle the conversion. Not too big a deal but, considering most installations will vary, this is going to require manual intervention every time a new system is imported. But, unlike the CSV convertor, the Member XML importer does actually create missing custom fields so updating the system shouldn’t be too big  a drag.

For my purposes I wrote a dirty little script to create the XML file for me so it was simply a matter of importing. I’m lazy, in the long term, so keeping as much of this as simple as possible is always a priority for me. But, since it’s a throw away thing cleanliness and best practices is less important than getting me more time to do real work. A word of caution though; the XML parser within ExpressionEngine isn’t very helpful when it comes to error messages and telling you what went wrong. You will curse.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
$sql = "SELECT * FROM users";
$result = mysql_query($sql);
if(!$result)
{
	echo mysql_error();
	exit;
}
$ee = "<members>\n";
while($row = mysql_fetch_assoc($result))
{
	$ee .= "\t<member>\n";
	$ee .= "\t\t<username><![CDATA[".$row['first_name']." ".$row['last_name']."]]></username>\n";
	$ee .= "\t\t<screen_name><![CDATA[".$row['first_name']." ".$row['last_name']."]]></screen_name>\n";
	$ee .= "\t\t<legacy_subscriber_id><![CDATA[".$row['subscriber_id']."]]></legacy_subscriber_id>\n";
	foreach($row AS $key => $value)
	{
		if($value == '')
		{
			continue;
		}
		$ee .= "\t\t<".$key."><![CDATA[".$value."]]></".$key.">\n";
	}
	$ee .= "\t</member>\n";
}
 
$ee .= '</members>';
 
echo $ee;
exit;
?>

The above code is fine if your existing database is cool but, and this is weird, ExpressionEngine goes full retard when it encounters anything it doesn’t like in the XML and won’t let you proceed. It’s really quite stunning. The XML importer knows that duplicate email addresses are bad in the database but instead of, say, allowing you to skip or force things the importer will just die and scream about a duplicate leaving you the only option of then manually pruning your data. Why they couldn’t be bothered with a checkbox or something allowing you to skip bad entries is beyond me but it makes the experience really, really, painful if your data sucks.

Still though, if your data is good to begin with the importer is a nice touch.

Bookmark and Share

CartThrob 2.0 Beta Fun

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

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

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:

{exp:cartthrob:cart_info}
	{total_items} <br />
	{total_unique_items} <br />
	{cart_entry_ids} <br />
	{cart_shipping} <br />
	{cart_tax_rate} <br />
	{cart_tax} <br />
	{cart_subtotal} <br />
	{cart_total} <br />
{/exp:cartthrob:cart_info}

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!

Bookmark and Share

ExpressionEngine and the Mystery of M00o93H7pQ09L8X1t49cHY01Z5j4TT91fGfr

Posted in Brain Dump, Code, Programming on May 3rd, 2011 by Eric Lamb – 1 Comment

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

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.

{exp:tag0}foo{/exp:tag0}
{exp:tag1}
    bar
    {exp:tag0}foo{/exp:tag0}
{/exp:tag1}

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

M0
{exp:tag1}
    bar
    M0
{/exp:tag1}

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?

Bookmark and Share

Custom Routes With Zend Framework

Posted in Brain Dump, Code, Programming on April 8th, 2011 by Eric Lamb – Be the first to comment

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

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['url_slug'].'/*',
			array('controller' => 'pages', 
			'action' => 'index')
		);
 
		$router->addRoute($url['url_slug'], $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.

Bookmark and Share

Practical PHP Reflection

Posted in Brain Dump, Code, Programming on March 1st, 2011 by Eric Lamb – 8 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 [ <internal:SimpleXML> <iterateable> class SimpleXMLElement implements Traversable ] {
 
  - Constants [0] {
  }
 
  - Static properties [0] {
  }
 
  - Static methods [0] {
  }
 
  - Properties [0] {
  }
 
  - Methods [14] {
    Method [ <internal:SimpleXML, ctor> final public method __construct ] {
    }
 
    Method [ <internal:SimpleXML> public method asXML ] {
    }
 
    Method [ <internal:SimpleXML> public method saveXML ] {
    }
 
    Method [ <internal:SimpleXML> public method xpath ] {
    }
 
    Method [ <internal:SimpleXML> public method registerXPathNamespace ] {
    }
 
    Method [ <internal:SimpleXML> public method attributes ] {
    }
 
    Method [ <internal:SimpleXML> public method children ] {
    }
 
    Method [ <internal:SimpleXML> public method getNamespaces ] {
    }
 
    Method [ <internal:SimpleXML> public method getDocNamespaces ] {
    }
 
    Method [ <internal:SimpleXML> public method getName ] {
    }
 
    Method [ <internal:SimpleXML> public method addChild ] {
    }
 
    Method [ <internal:SimpleXML> public method addAttribute ] {
    }
 
    Method [ <internal:SimpleXML> public method __toString ] {
    }
 
    Method [ <internal:SimpleXML> public method count ] {
    }
  }
}

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) {
  ["ATOM"]=>
  string(13) "Y-m-d\TH:i:sP"
  ["COOKIE"]=>
  string(16) "l, d-M-y H:i:s T"
  ["ISO8601"]=>
  string(13) "Y-m-d\TH:i:sO"
  ["RFC822"]=>
  string(16) "D, d M y H:i:s O"
  ["RFC850"]=>
  string(16) "l, d-M-y H:i:s T"
  ["RFC1036"]=>
  string(16) "D, d M y H:i:s O"
  ["RFC1123"]=>
  string(16) "D, d M Y H:i:s O"
  ["RFC2822"]=>
  string(16) "D, d M Y H:i:s O"
  ["RFC3339"]=>
  string(13) "Y-m-d\TH:i:sP"
  ["RSS"]=>
  string(16) "D, d M Y H:i:s O"
  ["W3C"]=>
  string(13) "Y-m-d\TH:i:sP"
}
 
Parent Class: bool(false)
Constructor: object(ReflectionMethod)#2 (2) {
  ["name"]=>
  string(11) "__construct"
  ["class"]=>
  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.

Bookmark and Share

Care About What Matters

Posted in Code, Programming on October 22nd, 2010 by Eric Lamb – Be the first to comment

It’d been a while since I’ve had the free time to write something and I really didn’t think it’d be a bitch post but it is and here we are. But, as I sit here at midnight browsing Reddit, and, yes, a little drunk, I find myself raging about the idea of the dumb stuff we care about and why we probably shouldn’t.

Case in point, an article called “PHP require vs. include vs. require_once vs. include_once Performance Test” written by Arin Sarkissian way back in 2007. Forgiving the obscenely long and verbose title, Arin goes over the process and code he created to test which of 4 statements (require, include, require_once, includes_once) was the most efficient in terms of performance. It’s definitely a good read if for no other reason than the insight into how to test and benchmark code but I think there’s more to the article than that.

That said, the article left me unsettled for a couple reasons. First, with the amazement and appreciation that someone had taken the initiative to test a theory instead of just drawing conclusions (something that’s pretty rare in my experience). Second though, well the second thing bothered me because of the other more applicable and meaningful question I couldn’t shake. Why do we care about this nonsense?

For years I’ve read articles about how best to handle certain circumstances to improve performance. Some are good. Things like how to use the dir() function to iterate over directories or how to properly write SQL are great and definitely worthwhile reads. On the other hand though, there are tons of articles talking about the advantages of using single quotes over double quotes or, as Arin wrote, which function is better suited for file inclusion; scenarios that matter so minimally that the effort in thinking about the issue is far greater than the gains of switching techniques.

As my friend Caroline would say, “Rubbish; all of it.” (she’s British).

Care about your SQL. Care about your file system interaction, your loops and your math. Care about your logic. And, because it’s so important it demands repeating, care about your SQL.

I promise you, there are zero circumstances where whether you used include_once over require_once is going to be the bottleneck. It will never matter one bit if you concatenate with single quotes rather than use double quotes with nested variables. Hand to fucking god; it will not matter nearly enough to spend any time debating which approach is better.

So before you start spending all your time wondering what is the best technique or method for a specific scenario as yourself how much does it matter.

SQL
Bookmark and Share

Developing ExpressionEngine 1.6x Extensions

Posted in Code, Programming on September 30th, 2010 by Eric Lamb – Be the first to comment

I recently had a project come up that could have gone one of two ways from a  strategic design stand point; either as a straight up script custom built for the occasion or, time warranting, I could build an extension for ExpressionEngine. As I’d already looked into writing an ExpressionEngine plugin the idea of writing an extension was pretty enticing regardless of the added time costs I would have to swallow (can’t bill the client for my fun now can I?).

Developing ExpressionEngine 1.6x Extensions

Developing ExpressionEngine 1.6x Extensions

The only problem is that the project in question was built on ExpressionEngine 1.6.7 and ExpressionEngine, having recently released 2.0 with all new bells and whistles and ways of doing things, updated their documentation as well. I couldn’t find any documentation for writing extensions for 1.6x though there’s a really nice help center for 2.0. A little advice third party developers; don’t just remove documentation and replace it with the new stuff because, as shocking as this may sound, people still use the old stuff.

To ExpressionEngine an extension is a script built to modify how ExpressionEngine works as opposed to adding additional functionality like a plugin would do. For example, a plugin would be good for adding a drop in template tag while an extension would be good for changing how ExpressionEngine parses all template tags. If you’re used to the WordPress development paradigm think of extensions as hook filters in WordPress plugins.

Those aren’t the only distinction though; extensions can also have a settings section, language files and database tables too so you’re really going  to need at least an extension for any deep functionality or customizations (there are also ExpressionEngine modules and expansions but that’s for another day).

Codewise, ExpressionEngine extensions are pretty similar to plugins insofar as structure and elements. At the core an extension is a PHP class that follows the same naming structure for both the class and the file as a plugin except the prefix changes and where you store the file. ExpressionEngine extensions should be named with a prefix of “ext.” and the class name, include a couple class variables for information about the extension, a couple methods to activate, deactivate and remove the extension and, ideally, a method to be called when the “hook” is executed.

As an example let’s put together an extension stub for a demonstration of how things should be setup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
class Pissoff_client
{
	/**
	 * Name of the extension
	 * @var string
	 */
	public $name = 'Enrage The Client';
 
	/**
	 * Version of the extension
	 * @var string
	 */
	public $version = '1.0';
 
	/**
	 * The description of the extension
	 * @var string
	 */
	public $description = 'Replaces every instance of one word with another from all entries';
 
	/**
	 * Flag for whether this extension has settings 
	 * @var string
	 */
	public $settings_exist = 'n';
 
	/**
	 * URL to the documentation for the extension
	 * @var stirng
	 */
	public $docs_url = 'http://url_to_documentation.com';
 
	/**
	 * The available settings for the extension
	 * @var array
	 */
	public $settings = array();
 
	/**
	 * Constructor
	 *
	 * @param 	mixed	Settings array or empty string if none exist.
	 */
	function Pissoff_client($settings = '')
	{
		$this->settings = $settings;
	}
 
	/**
	 * Activate Extension
	 *
	 * This function enters the extension into the exp_extensions table
	 *
	 * @see http://codeigniter.com/user_guide/database/index.html for
	 * more information on the db class.
	 *
	 * @return void
	 */
	function activate_extension()
	{
		global $DB;
 
		// default settings
		$settings =	array();
		$hook = array(
				'extension_id'	=> '',
				'class'			=> __CLASS__,
				'method'		=> 'run',
				'hook'			=> 'hook_to_process_extension_on',
				'settings'		=> serialize($settings),
				'priority'		=> 1,
				'version'		=> $this->version,
				'enabled'		=> 'y'
		);
 
		$DB->query($DB->insert_string('exp_extensions',	$hook));
	}
 
	/**
	 * Update Extension
	 *
	 * This function performs any necessary db updates when the extension
	 * page is visited
	 *
	 * @return 	mixed	void on update / false if none
	 */
	function update_extension($current = '')
	{
		global $DB, $EXT;
 
		if ($current < $this->version)
		{
			$query = $DB->query("SELECT settings FROM exp_extensions WHERE class = '".$DB->escape_str(__CLASS__)."'");
 
			$this->settings = unserialize($query->row['settings']);
			$DB->query($DB->update_string('exp_extensions', array('settings' => serialize($this->settings), 'version' => $this->version), array('class' => __CLASS__)));
		}
 
		return TRUE;
	}
 
	/**
	 * Disable Extension
	 *
	 * This method removes information from the exp_extensions table
	 *
	 * @return void
	 */
	function disable_extension()
	{
		global $DB;
		$DB->query("DELETE FROM exp_extensions WHERE class = '".__CLASS__."'");
	}
 
	/**
	 * Method to execute when hook is called
	 * @param mixed $data
	 */
	public function run($data)
	{
 
		//process
	}
}

Most of the above should be self explanatory but just in case what’s going on is that most of the class variables are used for extension details and there are 3 methods for activating, deactivating and removing the extension. The methods for activation management are important, especially the activation method “activate_extension” which contains the details about the extension including the hook to execute on along with the method name to execute when the hook is called. In the above example, the extension will execute the method “run” when the hook “hook_to_process_extension_on” is called. Thankfully, ExpressionEngine hasn’t done away with the list of hooks available in the 1.x branch.

Obviously, the above extension is pretty useless, what with not doing anything, but that’s all you’re gonna need to have the extension listed in the Extension Manager. To further personalize and customize (huh… I’m a poet) the details of your extension you can add settings and, if you want people to have the ability to change those settings, you can add a settings page by.

To add a settings page to your extension things get a little complicated at first but it’s not so bad. All you have to do is set the class variable $settings_exist to “y”, create a new method called “settings()” that EE uses and modify your extension language file (should be created inside the “lang” directory using the convention of “lang.extension_name”). The settings() function should contain an associative array with the key being the name of the setting and any default value for that setting like the below:

<?php
function settings()
{
	$settings = array();
	$settings['pissoff_find']		= '';
	$settings['pissoff_replace']	= 'this is the default value';
	return $settings;
}

Using the above will simply display a form with 2 text boxes for input. If no value is provided for the second item then there’ll be a default used. Simple. But, if you want to use, say, radio buttons or select boxes you have to make a couple modifications like the below:

<?php
function settings()
{
	$settings = array();
 
	$settings['pissoff_find'] = array('t', 'Default!!');
	$settings['pissoff_replace'] = array('r', array('nothing' => "Nothing", 'something' => "Something"), 'something');
	return $settings;
}

The above will create a new setting form with a textarea for the first option and a radio fieldgroup for the second. Make sure you add the radio option text to your language file though; it won’t do that automatically. Also, you’re not locked into just radio and textareas; you can also have select boxes (s) and multi-select boxes (ms) by updating the relevant array key.

Bookmark and Share

WP-Click-Track 0.7.2 Released

Posted in Code, Programming on August 3rd, 2010 by Eric Lamb – 1 Comment

Today I finally found the time to release an update to wp-click-track with a few bugs that some users have been encountering. This release is purely a bug fix release so there won’t be any new bells or whistles but if you run IIS 6 or want to clear out some links or reset your system you’re in luck. The only “interesting” bug that was fixed was the IIS6 HTTPS issue.

WP-Click-Track 0.7.2 Released

WP-Click-Track 0.7.2 Released

Because of how IIS6 and PHP populate the $_SERVER['HTTPS'] value some users were experiencing issues with their stats page. Turns out that IIS6 will return a value of “off” if the request wasn’t made through HTTPS instead of the default behavior of returning a boolean. So, while the below code will work with Apache and newer versions of IIS, IIS6 creates a bit of a false positive:

<?php
if(isset($_SERVER['HTTPS']))
{
     //server has HTTPS but IIS6 will always think it's on
}
?>

Instead, it’s better to check the value along with the existance check like:

<?php
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
{
    //server has HTTPS and IIS6 is being account for
}
?>

Go Microsoft :)

Bookmark and Share

ExpressionEngine White Screen Fix

Posted in Brain Dump, Code, Programming on July 29th, 2010 by Eric Lamb – Be the first to comment

The more I work with ExpressionEngine the more I keep running into the same issues. ExpressionEngine hides most error messages, especially those related to configuration, probably for security, but this doesn’t make debugging any easier. To be fair, I don’t know if this is how ExpressionEngine works out of the box or if this is a configuration setup done by the projects original developers but it does make fixing the issue that much harder.

ExpressionEngine White Screen

ExpressionEngine White Screen

Admin White Screen

I’ve only come across the administration area throwing a white screen when using ExpressionEngine 1.67 on a PHP 5.3 server and only if extensions are enabled. I’m not sure if the newer versions of the 1.x branch have this fixed so this might not work for you.

The issue has to do with how the variables are being passed and called; PHP 5.3 changed how references were handled so the method ExpressionEngine 1.67 uses no longer works. To fix you have to modify “/system/core/core.extensions.php” with the below changes that are on the ExpressionEngine forums:

<?php
//system/core/core.extensions.php around line 115 modify:
if (sizeof($args) == 1)
{
    $args = array($which, '');
}
 
if (version_compare(PHP_VERSION, '5.3') >= 0)
{
    foreach ($args as $k => $v)
    {
        $args[$k] =& $args[$k];
    }            
}  
?>
 
<?php
//and likewise around line 174 modify:
{
    $php4_object = FALSE;
    $args = array_slice(func_get_args(), 1);
}
 
if (version_compare(PHP_VERSION, '5.3') >= 0)
{
    foreach ($args as $k => $v)
    {
        $args[$k] =& $args[$k];
    }            
}  
?>

Front End White Screen

Then there’s the front end white screen; so far I’ve encountered this type of white screen in both the 1.6 and 2.0 branches of ExpressionEngine. Luckily, whenever I’ve ran into a white screen on the front site it’s always due to various path configurations which is easily fixed by over riding the configuration file.

Expression Engine is one of those programs that stores as much as possible in the database including file and path directory paths. To get around this permanently I’ve gotten in the habit of using a default config.php file for all any Expression Engine site I work on; it’s the first thing I do before anything else.

This new configuration file uses the $_SERVER super global to dynamically determine the paths and makes allowances for development, staging and production environments.

<?php
if ( ! defined('EXT')){
	exit('Invalid file request');
}
 
$conf['app_version'] = "167";
$conf['license_number'] = "";
$conf['debug'] = "0";
$conf['install_lock'] = "1";
$conf['db_hostname'] = "";
$conf['db_username'] = "";
$conf['db_password'] = "";
$conf['db_name'] = "";
 
if('dev.site.com' == $_SERVER['HTTP_HOST'])
{
	$conf['db_hostname'] = "";
	$conf['db_username'] = "";
	$conf['db_password'] = "";
	$conf['db_name'] = "";
}
elseif('stage.site.com' == $_SERVER['HTTP_HOST'])
{
	$conf['db_hostname'] = "";
	$conf['db_username'] = "";
	$conf['db_password'] = "";
	$conf['db_name'] = "";	
}
 
$conf['avatar_url'] = "http://".$_SERVER['HTTP_HOST']."/images/avatars/";
$conf['avatar_path'] = $_SERVER['DOCUMENT_ROOT']."/images/avatars/";
$conf['photo_url'] = "http://".$_SERVER['HTTP_HOST']."/images/member_photos/";
$conf['photo_path'] = $_SERVER['DOCUMENT_ROOT']."/images/member_photos/";
$conf['sig_img_url'] = "http://".$_SERVER['HTTP_HOST']."/images/signature_attachments/";
$conf['sig_img_path'] = $_SERVER['DOCUMENT_ROOT']."/images/signature_attachments/";
$conf['prv_msg_upload_path'] = $_SERVER['DOCUMENT_ROOT']."/images/pm_attachments/";
$conf['theme_folder_url'] = "http://".$_SERVER['HTTP_HOST']."/themes/";
$conf['site_url'] = "http://".$_SERVER['HTTP_HOST'];
$conf['captcha_url'] = "http://".$_SERVER['HTTP_HOST']."/images/captchas/";
$conf['captcha_path'] = $_SERVER['DOCUMENT_ROOT']."/images/captchas/";
$conf['emoticon_path'] = "http://".$_SERVER['HTTP_HOST']."/images/smileys/";
$conf['theme_folder_path'] = $_SERVER['DOCUMENT_ROOT']."/themes/";	
$conf['db_type'] = "mysql";
$conf['db_prefix'] = "exp";
$conf['db_conntype'] = "0";
$conf['system_folder'] = "system";
$conf['cp_url'] = "http://".$_SERVER['HTTP_HOST']."/".$conf['system_folder']."/index.php";
$conf['doc_url'] = "http://expressionengine.com/docs/";
$conf['cookie_prefix'] = "";
$conf['is_system_on'] = "y";
$conf['allow_extensions'] = "y";
$conf['multiple_sites_enabled'] = "n";
?>

The above config is for the 1.x branch though most values should work for the 2.x branch with the addition of $config['tmpl_file_basepath'].

Hopefully, this should take care of those white screens.

Bookmark and Share
« 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

Copyright © 2008 - 2012 Eric Lamb - All rights reserved