RSS
 

Posts Tagged ‘Migration’

CakePHP Tips 2015

13 Sep

Most tips are for 2.x and 3.x as they have been applied to both versions.

Complex radio inputs

A while back I posted a tip about deep array options for select input form fields.
With my recent path for 2.6 and 3.0 (>= 3.0.8) this is now also possible for radio() fields:

echo $this->Form->input('Model.field', [
	'type' => 'radio',
	'legend' => false,
	'div' => false,
	'options' => [
		'1' => ['name' => 'Option A', 'title' => 'A Title'],
		'2' => ['name' => 'Option B', 'data-foo' => 'bar']
	]
]);

Filtering

As of now, there is no way to directly disallow sort fields of pagination views.
There is a hack in 2.x to workaround this, though. Just set the whitelist to a non-existent field:

['foo']

This way the whitelisting is triggered and no valid field can be found. Mission accomplished.

In 3.x (>= 3.0.8), finally, we have an easy way of doing this, by passing an empty array for sortWhiteslist:

'sortWhitelist' => []

Not passing any whitelist will just not trigger the whitelisting at all.

Using the 3.x Migrations plugin for your 2.x app

I have some rather large 2.x apps that will not be migrated any time soon. But I at least want to leverage some of the 3.x stuff already where possible.
So I can include subsplits of the 3.x version via composer.
But for CLI console scripts and the migrations plugin this does not work.
I don’t want to use plain SQL upgrade files, though. And for any other migration solution I would probably also need some third party tool.
Why not going with what CakePHP 3.x seems to be perfectly bundled with? The Migrations plugin 🙂

So inside my 2.x app I create a subfolder upgrade where I put a very basic composer.json:

...
"require": {
	"cakephp/cakephp": "dev-master",
	"cakephp/migrations": "dev-master",
	"cakephp/bake": "dev-master"
},
"require-dev": {
	"cakephp/debug_kit": "2.*"
},
"autoload": {
	"psr-4": {
		"App\\": "src"
	}
},
"autoload-dev": {
	"psr-4": {
		"App\\Test\\": "tests",
		"Cake\\Test\\": "./vendor/cakephp/cakephp/tests"
	}
},
...

I basically check out the 3.x version in a subfolder along with the 2 plugins I need.
I also make sure, the cli folder and the config folder are present and working.

Then I modify the app.php to automatically pull the DB credentials from my root Config/database.php.
Since I don’t want to duplicate the configs.

$file = dirname(dirname(__DIR__)) . DS . 'Config' . DS . 'database.php';
if (!file_exists($file)) {
	throw new \Exception('Cannot find database.php');
}
$content = file_get_contents($file);
preg_match('/\'database\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$database = !empty($matches[1]) ? $matches[1] : '';
preg_match('/\'login\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$username = !empty($matches[1]) ? $matches[1] : '';
preg_match('/\'password\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$password = !empty($matches[1]) ? $matches[1] : '';
preg_match('/\'host\'\s*=\>\s*\'(.*)\'/i', $content, $matches);
$host = !empty($matches[1]) ? $matches[1] : 'localhost';
return [
	...
	'Datasources' => [
		'default' => [
			'host' => $host,
			'username' => $username,
			'password' => $password,
			'database' => $database,
		],
	],
	...

I can verify if it all works by running bin/cake bake migration_snapshot Init to make a snapshot of the current DB schema in the new migration code.
This will also automatically mark this migration file as migrated.
Now I can simply add more migration files with bin/cake migrations create {Name} and then migrate the DB via bin/cake migrations migrate.

Voila!

 
No Comments

Posted in CakePHP

 

Migrating SVN apps to Git and Composer

23 Jul

Just recently I had to move a few remaining legacy CakePHP2.x apps from SVN to Git+Composer.
This serves as a short how-to.

You can also use this post if you are migrating a git app to a composer based git app.

Note: Installing a new CakePHP 2.x app with Git and Composer right away is dead easy and explained quite well in the cookbook. This post is more about migrating existing ones.

SVN + Composer/Git?

They can actually work side-by-side. For a migration process this can be useful, especially when migrating huge apps.
Then doing it piece by piece helps to avoid chaos.

For this little how-to the main repo will stay a SVN one until the very end for this very same reason.

First steps

We have our SVN repo – up to date thanks to svn update.
Download composer.phar in your APP dir. This file should be added to your excludes. Set up a composer.json file in there, as well, and commit it.

CakePHP Core

You might have hard-coded the core files in ROOT/lib/Cake – or used an svn:externals on ROOT/lib.
Either way, remove that and add CakePHP2.x as Composer dependency.

Update index.php and webroot.php

As per documentation, we now need this in those files:

define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib');

Resolve global vendors folder

In case you used a global vendors folder it will now not automatically be included anymore.
To quick-fix this, add this to your bootstrap.php (at the beginning probably):

App::build(array('Vendor' => array(ROOT . DS . 'vendors' . DS)));

This will load your App::import()ed classes again from that folder.
Same goes for the plugins folder, by the way.

In a second step you can then start moving those to the APP/Vendor folder – either as Composer dependency or hard-coded.

When all are transferred, you can remove the global vendors folder and also remove the additional App::build() call.

Resolve svn:externals for plugins

Most plugins will probably be hard-coded or included via svn:externals.
Remove the svn:externals and add them as Composer dependency.
Do the same for any plugins in your ROOT/plugins folder. If they are hard-coded there, move them to the APP/Plugin folder.

Almost done

At this point we already have a fully functional application again that loads all dependencies via composer – even though it is still a SVN repo.
All it needs is

cd .../root && svn update
cd app && composer install

If some global vendor libs are harder to migrate or the "svn to git" conversation is troublesome, you can take your time get it up and running again on this level just fine.
At some point you will have finished the migration though, then proceed to the final step.

Move SVN to Git

When all externals have been resolved, the root vendor and plugin folders have been cleaned and their content moved to the APP pendents, we can now start migrating
the application to Git.
For this we drop the usual /trunk/... folder structure and directly copy the APP folder from your SVN repo into the root of your new Git repo.
The ROOT folder itself serves no purpose anymore, and we can have APP as root folder now.
Therefore in root, you should now have the composer.json file.
For an example, see cakephp-sandbox.

As for "copy": You can either directly copy-and-paste your repo (quick and dirty), or use git-svn tools to preserve your changelogs/history.
The latter is the cleaner approach, of course. See this guide on how to do that. Some services like GitHub might also offer a git-svn push access or link useful tools. Those approaches usually need a folder move of the APP folder content to the root level then on top.

Either way, the more you composer and the less you hard-code your libs, the quicker and easier the svn…git transformation will go.

Now updating app + core + plugins + vendors is just:

cd .../root
git pull
composer install

Since the APP folder is now the root folder, no need to further cd deeper.

Sugar

You may add

require_once dirname(__DIR__) . '/Vendor/autoload.php';

at the top of your bootstrap.php file to add autoloading via PSR for new namespaced repos (on top of the still working App::import() and App::uses() methods).

That means, that you can now use namespaces and third party packages via composer quite easily.
Let’s say we want to use the MediaEmbed lib in our project.
We then simply add it to our composer.json:

"require": {
	"dereuromark/media-embed": "dev-master"
}

In our CakePHP classes, e.g. an EmbedHelper, we can now use it right away:

<?php
use \MediaEmbed\MediaEmbed;
App::uses('AppHelper', 'View/Helper');
class EmbedHelper extends AppHelper {
	/**
	 * @param string $url Absolute URL of the video/audio.
	 * @return string|null HTML snippet or null on failure.
	 */
	public function media($url) {
		$MediaEmbed = new MediaEmbed();
		if ($MediaObject = $MediaEmbed->parseUrl($url)) {
			return $MediaObject->getEmbedCode();
		}
	}
}

Isn’t that awesome? You now have the full PHP5.3+ (GitHub) lib variety out there at your disposal. You might want to check out this list of cool libs.

Private repos

With the externals, it was quite easy to pull from your own repo URLs. Composer makes this a little bit more difficult.
To overcome the issue for GitHub private repos, for example, you can use vcs:

"require": {
	...
	"your-username/cakephp-some-private-plugin" : "*"
},
"repositories" : [{
		"type" : "vcs",
		"url" : "git@github.com:your-username/cakephp-some-private-plugin"
	},
	...
],

Note that this will prompt once for your username and password and create a token for re-use:

Your GitHub credentials are required to fetch private repository metadata.
The credentials will be swapped for an OAuth token stored in …/Composer/auth.json, your password will not be stored.

Last tips

This tutorial assumes that you are properly using the current master (2.5.3 at this time) version of CakePHP. Always upgrade to the current master – never use anything older.

Make sure you have a current index.php/test.php file as well as a current APP/Console dir including those cake scripts (current as in master/2.5.3 at least).
You can just copy them over from the CakePHP source folder (Cake/Console/Templates/...) if you are unsure.
Especially for console this is quite important. Otherwise Console/cake might not work out of the box with the new composer approach – even though it would if you had up-to-date files.

Also, don’t forget to .gitignore all included dependencies (both Vendor and Plugin ones). And also the ones from SVN, composer.phar etc.

 
No Comments

Posted in CakePHP

 

More great news: CakePHP 2.0 stable is out!

18 Oct

After 1.5 years of development, Cake catches up with other frameworks.
It is now as modern as most of the others while remaining the most powerful of all.
Almost none if its automatic got lost during the process of rewriting.

Some of the important aspects of 2.0

  • Faster (20-40% depending on the application)
  • Modern (>=PHP5.2 and state of the art functionality)
  • More Flexible and extensible (almost every class can be switched out with own ones)
  • Exceptions as error handling
  • PHPUnit as test suite
  • Hundreds of fixes which had to stay in 1.3 due to compatibility issues
  • Lots of enhancements and new functionality like “aliasing” – details

If you start a new project dive right into 2.0. That’s the future 🙂

For all those who like to assimilate the changes as online video:
tv.cakephp.org/video/CakeFoundation/2011/10/06/ch-ch-anges_cakephp_2_0_-_by_mark_story

Radical changes

There will be radical changes. For once the file names now match the class names. This needs quite some getting used to, but once you do, you wouldn’t want it any other way.
Also, the framework paths changed to allow more customization and overwriting.

In 1.3 the normal cake setup was:

/app/
/plugins/
/vendors/
/cake/

In 2.x it’s now:

/app/
/plugins/
/vendors/
/lib/Cake/

You can overwrite (=replace) any core class just by putting the file (using the same path/package structure) in your APP/Lib/ folder:
APP/Lib/Routing/Router.php replaces the core one, for example.

Tips for upgrading to 2.x

The migration guide will help to upgrade existing applications to the new version.
This will be quite a bit of work, though. Almost all classes are renamed, many methods and object variables have been dropped.

Your biggest help will be the cake shell script "ugrade" which is available in 2.0 now. It helps you to automatically upgrade some of the code. You can either select all or single tasks like renaming components etc.
Simply type "cake upgrade" in the console to list all available methods.
It really is a huge time safer. You should backup or commit everything before you attempt to run this script, though.

The basic steps:

  • Switch out the core first (in /lib/Cake)
  • Check what is working so far
  • Use the guide to fix the issues piece by piece until everything is working again

UPDATE:
I tried to upgrade a medium sized 1.3 app to 2.0. After finding several problems I opened a ticket.
Hopefully the upgrade process will be made smoother the next couple of weeks 🙂

Also read about some more upgrade tips on my new post here.

Last Words

I am a little bit proud to see many of my tickets and proposed changes/fixes being now part of the framework.
Contributing to such a popular and large framework is sometimes easier than one might think. Sometimes it needed only hours to approve one of my tickets. OK, sometimes it needs months.
Providing a good reason and attaching proposed changes as diff or patch can really speed up things and should encourage you to involve yourself in cake core development, as well.

 
2 Comments

Posted in CakePHP