Tag: cake 2.0

Quick comparison of Nginx and Apache

This was a quick test as I was playing around with Nginx and CakePHP 2.0.

The numbers were interesting, however.
What I did:
- Setup a virtual box with Windows host
- OS: Ubuntu (Natty)
- PHP 5.3.8
- CakePHP 2.0-beta (freshly pulled)
- apache2 (2.2.17)
- nginx (1.0.5)

Nothing was tweaked or tuned. I’ve setup both servers to use virtual hosts and simply load the default CakePHP page (i.e. fresh install).
There is no app behind any of this, but we are touching pieces of the framework and some PHP logic.
(Comparison is about the web servers anyway)…

Anyway, start apache and run:

ab -kc 10 -t 30 http://localhost/

So we’ll use apache benchmark to beat the localhost a little (for 30 seconds) and get some numbers:

Benchmarking localhost (be patient)
Finished 839 requests

Server Software:        Apache/2.2.17
Server Hostname:        localhost
Server Port:            80

Document Path:          /
Document Length:        4481 bytes

Concurrency Level:      10
Time taken for tests:   30.009 seconds
Complete requests:      839
Failed requests:        0
Write errors:           0
Keep-Alive requests:    839
Total transferred:      4109432 bytes
HTML transferred:       3759559 bytes
Requests per second:    27.96 [#/sec] (mean)
Time per request:       357.679 [ms] (mean)
Time per request:       35.768 [ms] (mean, across all concurrent requests)
Transfer rate:          133.73 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.7      0       7
Processing:   203  355 121.7    352    2931
Waiting:      202  355 121.7    352    2931
Total:        203  355 122.0    352    2938

Percentage of the requests served within a certain time (ms)
  50%    352
  66%    360
  75%    365
  80%    368
  90%    377
  95%    385
  98%    393
  99%    404
 100%   2938 (longest request)

Now, shutdown apache, start nginx and repeat the above test:

Benchmarking localhost (be patient)
Finished 4451 requests

Server Software:        nginx/1.0.5
Server Hostname:        localhost
Server Port:            80

Document Path:          /
Document Length:        4481 bytes

Concurrency Level:      10
Time taken for tests:   30.001 seconds
Complete requests:      4451
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      21367368 bytes
HTML transferred:       19972014 bytes
Requests per second:    148.36 [#/sec] (mean)
Time per request:       67.403 [ms] (mean)
Time per request:       6.740 [ms] (mean, across all concurrent requests)
Transfer rate:          695.53 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.3      0       7
Processing:    18   67  11.6     67     204
Waiting:        5   40  22.1     42     198
Total:         18   67  11.6     67     204

Percentage of the requests served within a certain time (ms)
  50%     67
  66%     71
  75%     73
  80%     75
  90%     80
  95%     85
  98%     93
  99%    102
 100%    204 (longest request)

OK, let’s see:
Total requests served: Apache – 839, Nginx – 4451
Requests per second: Apache – 27.96, Nginx – 148.36

The other numbers are quite unbelievable as well.

What’s the point of all this? Tutorial on CakePHP 2.0 + Nginx is coming soon here ;)

Under the hood of CakePHP 2.0

Thanks to excellent Mr. jrbasso for putting together this list for me.
In case one wonders, yes he does know a few things about cake ;)

So, without further ado here’s a couple of things to enjoy in CakePHP 2.0…

__() now works like sprintf()

There were a few complaints about this in the past, as well as the fact that __() used to echo by default.

Now the problem is fixed and the default usage is as follows:

echo __("some %s var", $myVar);

Improved file structure and lazy loading of files

The naming convention is much better and simpler now. No more messing about with underscore’s, etc.
Whatever you have for your class name is what you have for your file name (+”.php”).
Misspelling of model file names ESPeciaALLY (e_s_pecia_a_l_l_y.php) in extreme cases was a common mistake for cake not being able to find the model.
Therefore none of the model specific rules for validation, methods and other logic could be executed.
(The simple debugging and good ol’ copy/paste should be much easier now).

New CakeRequest and CakeResponse

First, CakeRequest gathers all information about the request (in a way like $this->params does, but with a lot more juice).
For example, some responsibilities of the RequestHandler component have been shifted to CakeRequest.
Mark Story has an excellent write-up about this if you wish to learn about
the details.

The counterpart, of sorts, to CakeRequest is CakeResponse… which, as you’ve guessed, works to handle responding to requests.
It consolidates the work, which was previously spread across various components of the system.
Again, I will refer you to Mark Story’s blog to get detailed description about CakeResponse.

The whole idea is to decouple and better organize related tasks from various places in the framework. Good organization helps with maintainability of the framework code, and, in turn, your own.

CakeEmail is a Library now

This change should stop 99% of the questions about how to send email from the model.
Yaayy! You don’t have to break MVC anymore (in your User model):

App::uses('CakeEmail', 'Network/Email');
class User extends AppModel {
  public function afterSave($created) {
    if ($created) {
      $email = new CakeEmail();
      $email->from('me@example.com')->to('new.user@example.com')->subject('Welcome')->send('Hello! This is my message to the new user.');
    }
  }
}

You don’t have to chain the methods as above…

HTML5 methods in Form/Html helper

Even though HTML5 is still a bit infant more and more web applications are beginning to apply its elements. This is especially true in the mobile market.
CakePHP 2.0 has a clever way for the HTML5 implementation, by using the magic __call() method,
to create simple inputs.

Let’s look at the test case to better understand this:

/**
 * test that some html5 inputs + FormHelper::__call() work
 *
 * @return void
 */
	function testHtml5Inputs() {
		$result = $this->Form->email('User.email');
		$expected = array(
			'input' => array('type' => 'email', 'name' => 'data[User][email]', 'id' => 'UserEmail')
		);
		$this->assertTags($result, $expected);

		$result = $this->Form->search('User.query');
		$expected = array(
			'input' => array('type' => 'search', 'name' => 'data[User][query]', 'id' => 'UserQuery')
		);
		$this->assertTags($result, $expected);

		$result = $this->Form->search('User.query', array('value' => 'test'));
		$expected = array(
			'input' => array('type' => 'search', 'name' => 'data[User][query]', 'id' => 'UserQuery', 'value' => 'test')
		);
		$this->assertTags($result, $expected);
	}

PDO and database access performance

In 2.0 CakePHP is switching to the PDO. PDO drivers are stable, native and well-supported. They obviously provide faster and better data access.

Auth is more flexible and supports different authentication methods like “Digest”

Authentication and Authorization are now properly decoupled from one another.
In both cases an app developer has the ability to extend BaseAuthenticate or BaseAuthorize to add new authentication and authorization methods.
CakePHP 2.0 comes with a few core methods (at least at the time of writing this):

  • ActionsAuthorize — Provides the ability to authorize using the AclComponent
  • BasicAuthenticate — Provides Basic HTTP authentication support for AuthComponent
  • ControllerAuthorize — Provides the ability to authorize using a controller callback
  • CrudAuthorize — best explanation is taken from the code doc:

    For example, taking `/posts/index` as the current request. The default mapping for `index`, is a `read` permission check. The Acl check would then be for the `posts` controller with the `read` permission. This allows you to create permission systems that focus more on what is being done to resources, rather than the specific actions being visited.

  • DigestAuthenticate — Provides Digest HTTP authentication support
  • FormAuthenticate — Authenticates the identity contained in a request (i.e. the good ol’ login form)

So much cleaner :)

No more PHP4

Nuff’ said. This makes Cake 2.0 much faster (oh let’s say twice as fast), and no I don’t have evidence to support this claim, by removing a lot of uncessary code to support PHP 4 and 5, not to mention additional logic which would lead on one path or another depending what version of PHP you have installed.
To be more specific, CakePHP 2.0 will support PHP 5.2+ (so it may not be utilizing some of the newer features of PHP 5.3).

Using collections to load Helpers, Behaviors, Components

From CakePHP lighthouse page:

Helpers, behaviors, components, and tasks were restructured for 2.0. After examining the various things these objects did, there were some striking similarities. All the object types except Tasks provided callbacks and custom methods. However, the loading and usage of callbacks was slightly different in each case. For 2.0 these different loading/callback triggering API’s were simplified and made uniform. Using BehaviorCollection as the base of how things should work. Each object type now has a Collection object. This collection object is responsible for loading, unloading and triggering callbacks.

After examining the responsibilities of each class involved in the View layer, it became clear that View was handling much more than a single task. The responsibility of creating helpers, is not central to what View does, and was moved into HelperCollection. HelperCollection is responsible for loading and constructing helpers, as well as triggering callbacks on helpers. By default View creates a HelperCollection in its constructor, and uses it for subsequent operations. The HelperCollection for a view can be found at $this->Helpers.

Components were refactored in 2.0 to solve a number of inconsistencies and provide a more uniform API. In the past Component was the loader and manager of Components for a Controller. In 2.0 ComponentCollection takes over that responsibility and Component is now a base class for components. This unifies the API between Helpers and Components as a collection.
Inside a controller $this->Component has been renamed to $this->Components this makes it more uniform with Behaviors and Helpers.

Custom class names (aliasing) for your Helpers, Behaviors, Components

pulic $helpers = array(
    "Html" => array(
        "className" => "CustomHtml"
    )
);

Plugins are not auto-loaded

You will need to load them in your class or bootstrap.

Models are now lazy loaded

With all this talk about Lazy Loading, this is probably the one that deserves a lot of attention.
Besides, models will not attempt a DB connection until find() (or other DB-actionable) method is called.

p.s. CakePHP 2.0 could be here sooner than people expect. I have a feeling we’ll have RC4 come CakeFest. So, if you have not started thinking about migrating your app to 2.0, now is a good time ;)