Tag: cakephp 2.0

“Error: Database connection “Mysql” is missing, or could not be created”. CakePHP 2.0 — cake bake trouble

CakePHP 2.0

Nothing like coming back from a hiatus with a WTF? post.
My favorite “cake bake” started failing with the message in the subject; as well it seems that I am not the only one who had suffered from the problem… (just give it a quick check on google).

After a little research here’s a summary of issues and steps to check:

The problem is caused the the fact that the PDO drivers are not available when you run php5 in cli mode (i.e. “cake bake”).

  1. First thing you’d want to check is which php.ini file is being used by your php (in cli mode!).
  2. In your terminal (or command prompt), run: php –ini. This will show the location of the currently used files. In many cases it is possible that your system php is not the same as your web server php, which you might have installed with something like XAMPP. If this is the case you need to change your path to use the correct install of php, which should have the necessary drivers available.
  3. Next step would be to check your php.ini (which is sometimes broken into a few config files). Check the PDO settings to make sure you have the correct extension enabled (might be as simple as un-commenting a line). For example, I am using MySQL therefore I needed to have MySQL PDO extension available (when running in cli!). It was working perfectly well “on the web”.
  4. Turns out I needed to run: sudo apt-get install php5-mysql

That was unexpected a little since CakePHP had no connection problems to MySQL, but there you go. This should cover all possible cases.
If you find other solutions not outlined here, please share.

Setting up Nginx and CakePHP 2.0

Nginx is a pretty awesome web server (fast, and easy to configure… at least I prefer the syntax over some other popular web servers).

I figured to share the installation process of both CakePHP 2.0 and Nginx on Ubuntu 11.04 (Natty).

Let’s fire up the terminal…

(I presume you have some basic knowledge of *nix so I won’t go into details about the commands, etc.)

sudo apt-get install git

Next, let’s get a fresh version of cake 2:

cd /cake
sudo git clone https://github.com/cakephp/cakephp.git
sudo git checkout 2.0
sudo git pull

Git should tell us that we are “up-to-date”.

Alright, now we have to setup our environment.
The best way I found of going about it (after trying quite a few methods out there) is by the running the excellent set of scripts, which you can find here.
Pull the scripts from the git repo, in the similar way as shown above, into some reasonable local destination. Once you have the files locally, simply run:

sudo ./install.sh

After answering a few questions… our LEMP environment is ready!

Let’s see if Nginx is working as expected…
In the browser head over to localhost, at least at the time of this writing, you get a phpinfo() page served up by default.

So we are satisfied that Nginx is serving up PHP and now it’s time to setup a CakePHP 2.0 app.
When we’ve pulled CakePHP in the very beginning, it came with a skeleton app, which we will use for growing our new one.

Let’s copy it someplace easily accessible (assuming we are in the root of cake… you should see “app”, “vendors”, “lib” directories):

sudo cp -r app /web/

In order not to move cake anywhere, we’ll create a symbolic link to our lib.
(Presuming we are now in the “/web” directory):

sudo ln -s /cake/cakephp/lib lib

So at this point we have php, web server, cake core, skeleton app, mysql all ready to go.
The only remaining part is to tell the web server about our cake app. Similarly to Apache we can setup virtual hosts and rewrite rules in Nginx. I don’t know many details about setting up Nginx and all the rewrite rule tricks available, but as mentioned before, from the examples the syntax looks quite simple and one should be able to decipher the directives relatively easily.

… Being lazy and not wanting to go through the docs, I googled around and thanks to this post it was quite fast to setup a virtual host for the app.

After the installation Nginx will have a setting file in:
/etc/nginx/sites-available/default
(This particular set of installation steps is applicable to Ubuntu, but hopefully you’ll know how to achieve the same procedure in your own OS).

If we review the file quickly it seems like a solid starting point, but we need to have some rewrite rules for cake to make pretty-urls work.
Well, once again thanks to aforementioned post, all we have to do is add the snippet below to our default config (hey, at least it’s working for me):

# rewrite rules for cakephp
  location / {
    root   /web/app/webroot;
    index  index.php index.html;
    try_files $uri $uri/ index.php;

    # If the file exists as a static file serve it
    # directly without running all
    # the other rewite tests on it
    if (-f $request_filename) {
      break;
    }
    if (!-f $request_filename) {
      rewrite ^/(.+)$ /index.php?url=$1 last;
      break;
    }
 }

The root setting is pointing to our app’s webroot, of course… which in trun becomes the root of the virtual host (let’s just use localhost for now, otherwise you’d need to take a few additional steps, but that’s beyond the scope of this post).
Hopefully the code of the setting is not too hard to figure out.

So at this point we have a virtual host pointing to our app and all the settings in place, let’s restart the web server:

sudo /etc/init.d/nginx restart

… and if all goes well, once you visit localhost in your browser, you should see the CakePHP 2.0 welcome page.

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 ;)