About Jamie on Software

Jamie on Software is the online journal of web developer and writer Jamie Rumbelow.

Jamie likes books, guitars, programming, open source and food. He writes about these things too. This is where he puts the things he writes.

My Books

Tags
Tweets
Feeds
We Love
Powered by Squarespace

Entries in php (15)

Tuesday
Feb122013

Catapult into PyroCMS

Yesterday, Efendi Books released our latest title - Catapult into PyroCMS. PHP guru Phil Sturgeon has written a rather brilliant book about the popular open-source CMS, PyroCMS, that he created and develops.

The content is superb - it's a great introductory guide to a very good CMS, with enough in there for developers and designers to get used to building and developing applications and websites using it. It also looks gorgeous, with some wonderful illustrations by the amazing Jenny Thorne.

Here's some text from the introduction:

In this book - from PyroCMS creator Phil Sturgeon - you’ll learn the core concepts underpinning Pyro, create malleable templates and themes, utilise Streams for powering content-heavy sites and examine the basics of writing addons for the Pyro platform. You’ll learn the theory behind the CMS, how to mould the system around your content and how to use the powerful, designer-friendly template layer.

It's a fantastic title and it's already getting some great reviews, so be sure to grab your copy now!

Friday
Oct052012

My Ideal Framework

My ideal framework would be easy to set up. Simply git clone ... new_project && cd new_project and away I go

My ideal framework would be built around Composer modules. Any component can be loaded or disabled at my whim.

My ideal framework would be totally autoloaded. I hate include. I never want to write it again.

My ideal framework would have application testing setup from day one. I should be able to run phpunit from base directory - or vendor/bin/phpunit, to be more precise - and have all the tests across my application run.

My ideal framework's app folder structure could/would look like this:

modules/
    authentication/
        assets/
        controllers/
        models/
        templates/
        routes.php
    profiles/
        assets/
        controllers/
        models/
        presenters/
        templates/
        routes.php
templates/
    application.lex
vendor/
composer.json
phpunit.xml
routes.php

My ideal framework would have a clever template heirarchy. Template files would be loaded into layouts (that cascade) automagically.

My ideal framework wouldn't ever generate code for me, because, ew.

My ideal framework would use Sherlock for assets, obviously.

My ideal framework would treat HTTP as a first-class citizen.

My ideal framework's modules would be tested in isolation from one another. Using dependency injection to stub/mock out dependencies, I could write blazingly quick unit tests to ensure the stability of each small module.

Sounds a bit like Laravel 4.

Friday
Oct052012

The Trick to Writing Large PHP Applications

The trick to writing large-scale, stable PHP applications? Don't. Write lots of small ones. Test each component in isolation with unit tests. Use Composer. Lots. Get it on GitHub and use Travis + a master / pull request flow model to handle collaboration. Listen to Jeff Buckley loudly. Rock out.

Thursday
Oct042012

Using Composer on (gs)

I love using MediaTemple for my simple sites. When I don't have complex hosting requirements, I know I can get my PHP applications up and running really quickly. Their support is great, their hosting fast and feature-rich and their prices competitive.

...but there's one problem. (gs), their shared hosting platform, has a limited PHP CLI binary. You can't configure it through a php.ini (see this tweet for more). This makes it impossible to use Composer. Since Composer is the future of PHP, this is quite worrying.

There is, however, a solution. We can use the -d flag to set the runtime config variables required to get Composer running.

Installing Composer:

curl -s https://getcomposer.org/installer | php -d allow_url_fopen=1 -d suhosin.executor.include.whitelist=phar

...and then to run composer.phar:

php -d memory_limit=512M -d allow_url_fopen=1 -d suhosin.executor.include.whitelist=phar composer.phar

This is ugly, so let's clean it up. We'll add an alias to the bash profile:

$ vim ~/.profile

We'll alias get_composer to our install command and composer to our composer.phar file. This way we can set up new subdomains and such easily:

alias get_composer="curl -s https://getcomposer.org/installer | php -d allow_url_fopen=1 -d suhosin.executor.include.whitelist=phar"
alias composer="php -d memory_limit=512M -d allow_url_fopen=1 -d suhosin.executor.include.whitelist=phar composer.phar"

Save, and reload the profile (this will be done automatically next login):

$ source ~/.profile

Now, we can use Composer to our hearts' content:

$ get_composer
All settings correct for using Composer
Downloading...

Composer successfully installed to: /blah/domains/efendibooks.com/composer.phar
Use it: php composer.phar

$ composer -V
Composer version cb2a0f4
Tuesday
Sep112012

MY_Model 2.0.0 At A Glance

Hot off the presses is the news that version 2.0.0 of my MY_Model base model for CodeIgniter has been released. 2.0.0 brings a huge range of new features, as well as a bunch of internal code changes, that I'll go through here.

Relationships

By far the biggest addition to MY_Model is support for basic relationships. Better relationship / JOIN support has been a widly requested feature pretty much from day one; I feel like I've come up with a simple and elegant solution to the problem.

It's not particularly performant and only supports one-to-many relationships, but for the occasions when you need a really simple and speedy way of associating rows, it's perfect.

Relationships are defined in the $belongs_to and $has_many instance variables:

class Post_model extends MY_Model
{
    public $belongs_to = array( 'author' );
    public $has_many = array( 'comments' );
}

You can then use the with() scope method to add any of the defined associations to the result:

$post = $this->post_model->with('author')
                         ->with('comments')
                         ->get(1);

echo $post->author->title;
echo count($post->comments);

Under the hood, this adds a new $after_get observer that calls the related model. This means that the result is embedded in the object, but that it suffers from the n+1 problem. If performance is important, or n+1 is biting you, it's still recommended to manually write a join in a custom method.

You can also customise the name of the loaded model and used primary key. These are sensible defaults, but can be overridden, so check out the relationships section of the documentation for more on this.

Serialisation / Serialization

If you've got some arbitrary data to insert--a data matrix, for instance--that you don't wish to set up in a traditional relational format, but doesn't require a non-relational database, you can use serialisation.

MY_Model now contains two new built-in observers, serialize() and unserialize(). Simply add them in $before_create and $after_get and watch as you seamlessly pass in complex data structures with ease:

class Event_model extends MY_Model
{
    public $before_create = array( 'serialize(matrix)' );
    public $after_get = array( 'unserialize(matrix)' );
}

$this->event_model->insert(array(
    'matrix' => new RandomMatrixObject
));
get_class($this->event_model->get(1)->matrix) == 'RandomMatrixObject' // TRUE

You can pass in absolutely anything you like and it'll be serialised appropriately. Customise the serialisation behaviour of classes by using __sleep and __wakeUp.

Soft Delete

Sometimes you don't want to destroy the row in the table, just remove it from the context of the application. Soft delete comes to the rescue. Simply set $soft_delete to be TRUE and rows will magically be marked as deleted:

class Account_model extends MY_Model
{
    public $soft_delete = TRUE;
}

Protected Attributes

I've been very lazy and have been throwing data straight into most of my models from the HTML form. This is, as I'm sure you can imagine, unimaginably dangerous and rather stupid.

Not to worry! Protect those attributes you care most about and then be reckless worry-free!

class Post_model extends MY_Model
{
    public $protected_attributes = array( 'id', 'hash' );
}

$this->post_model->insert(array(
    'id' => 2,
    'hash' => 'aqe3fwrga23fw243fWE',
    'title' => 'A new post'
));

Much More

There are tonnes of other changes under the hood and new features that I've not talked about here. A few more bits I've not explained but are worth a quick mention nonetheless:

  • The removal of Composer support. I love Composer but it was causing problems inside CI and until CI starts treating Composer properly I'll leave it out.
  • Massive internal change to the way callbacks work. Might break existing code.
  • Built-in timestamps (created_at and updated_at)
  • Manual DB override
  • A bunch of bugfixes

Contributors

Getting to a powerful, stable 2.0 has been an almighty challenge, and is the summation of a lot of people's contributions and time. A massive, Eric Pickles-sized thank you to the following people (in no particular order):

Want To Contribute?

Get onto GitHub, fork away, branch, write the code and unit tests(!) and submit a pull request. It'd be awesome to get even more contributions. Together we can build a really great base model for CodeIgniter.

Thanks again to everyone who's helped out with their feedback, support and coding skillz, and get over to GitHub now and grab a copy of MY_Model 2.0.0!

Love you all. Peace out.