CakeDC Blog

TIPS, INSIGHTS AND THE LATEST FROM THE EXPERTS BEHIND CAKEPHP

CakePHP 3.0 is coming

For those of you who may have missed it, this week we released the first alpha of CakePHP 3.0, with a significant update to begin our move towards beta. I'm really excited to see how the project is evolving, and the amazing work that the members of the core team are doing, as well as what all those contributing are helping to build. But its important to look back in retrospect, and understand from where we've come.

Baking the Cake

If you're not aware, CakePHP has now been almost 10 years in the making. That's a long time for a project to stay as active as it has. Everyone has their favorite framework, and some like a few more than others, but one thing that's clear in my mind is that CakePHP has always been very popular, even until today. The project started when I teamed up with Michal Tatarynowicz, who had created the basic feature set of what would become CakePHP. I had begun work on what is currently the model layer in the pre 3.0 version of the framework, and continued leading the project when Michal left shortly after we open sourced under the MIT license. This was back in 2005, and working with PHP 4. Back then we had to work around the language a lot, as it was lacking the object oriented features which we now all take for granted. We had to emulate or actually build out many of the native aspects now included with PHP, which made the task all the more complicated. Don't get me wrong, it was fun times, as the language was growing fast and we were all pushing it along. It's no secret the Rasmus isn't a huge fan of frameworks, but like Rails for Ruby, many of the frameworks for PHP have also helped the language gain a place in many people's hearts. But time goes by, and like all things, PHP grew up and matured as a language. A lot of the features we had implemented for CakePHP in PHP 4 now became native with PHP 5, so although we'd provided the solutions when they weren't available, these now became redundant. But people and hosting companies were slow to adopt. The framework had grown a large community by then, so it was difficult for us to just drop support for PHP 4 and leave them without their framework. It was also in our interest to support PHP by prompting people to upgrade, so we took the middle road. This is where our infamous backwards compatibility for PHP 4 stems from. There were disagreements between core members of the project, where some advocated for jumping the gun and releasing a version which required the latest version of PHP, but I refused to allow our community to be left behind. These are people who had grown up with the framework, people who relied on us to keep a solution which allowed anyone to use it. In hindsight you could say that those developers weren't worth supporting, but I see our community as a family, and like my Marine training taught me, no man gets left behind. However, the years past, and we went from 1.2 to 1.3, and CakePHP begun to mature into a powerful solution for rapid application development. We also saw how adoption for PHP 5 improved, and hosts begun to offer broad support, which is when we decided to make the move to PHP 5.2 with the release of CakePHP 2. There were mixed feelings about the decision to not jump straight to 5.3, but I still feel today that, in allowing the framework to mature as it has on a stable code base, people who have counted on us would hopefully understand that choice.

Growing up as a Community

Like the years that have come before us, we all grow up as developers, and PHP the language grows with us. The impulse we've seen over the past years with the releases of 5.3, 5.4 and 5.5 have shown how the community can really build a powerful language. But it's not only the language that grows, but the community around it as well. We've seen over the past years how interoperability between frameworks has become a requirement, and the technical expectations of developers have become consistently more demanding. We've seen how the rise of packages managers, like Composer, have facilitated this distributed and modular approach to building PHP applications. So when we looked at what we expected for 3.0, as Jose Lorenzo said in the technical keynote at CakeFest, our annual conference, "we're all older and wiser", so it's time to put those years of experience to good use. So, for CakePHP 3.0 we decided that now is a good time to take our community and move everything towards a stronger and brighter future. This means that we've made some of the important decisions, which align the framework with the coming features in the language, and provide the same framework goodness people are used to, but deliver it with new features which upgrade the solution for another 10 years to come. This also means breathing new life into many of the core aspects of the framework, which in some cases have become its winning features, and in others the infamous trademarks of CakePHP. I invite you all, those who love CakePHP and even those who don't, to give this alpha of the latest major version of the framework a try, and let us know how well it tastes. We hope that this is the beginning of a great new chapter in the history of CakePHP, and one which lets us grow further, and together, as a community. Thank you.

CakeDC Git Workflow - Tips and Tricks

Over the past months we've had many people ask us about how to integrate and work with the CakeDC Git Workflow as we do. So, here are few tips and tricks on how to use our workflow for the git version control system, to help you keep a clean commit history on every CakePHP project.

Using ticket numbers in commit messages

One thing which becomes pretty obvious early on is how handy it can be to have commits tied to your issue tracker. The easiest way to do this is to use the issue or ticket ID in your commit messages. $ git commit -m "#1234 changed this and that" Following this pattern (starting the commit message with #ID), with a bit of git rebase sauce, makes the lines of your updates read like a story of your code.

Automation with use of commit-msg hook

It's possible that you may not using a git bash prompt, so you don't see the name of the current branch in console all the time. Alternatively, the dialog window of your preferred UI for git may not clearly disclose the name of the branch you're working on. Or, maybe you're just too lazy to write ticket number every time you commit something to the repository. Using our workflow, where non-permanent branches are named after the related ticket number, you can create an executable file .git/hooks/commit-msg in the project's root directory with following content: #!/bin/sh TICKET=$(git rev-parse --abbrev-ref HEAD | awk -F '/' '{print $2}') if [ -n "$TICKET" ]; then echo "#$TICKET `cat $1`" > $1 fi From now on, the message of every commit to any branch with a forward slash in the name (in our case, its always the ID of the related feature/issue/hot-fix ticket), will start with a hash and the ticket number. Also, lets assume that you're using our workflow for all of your projects. In that case, it could be better to install the git hook globally: $ mkdir -p ~/.git_template/hooks ... add global hook(s) to this directory ... $ git config --global init.templatedir '~/.git_template' After setting this up, every created or cloned repository will use this template directory (will make copy of its content). Existing repositories could be reinitialized with the new template by running git init in their root folders.

Temporary local branches

With the previous commit-msg hook in place, we can now go crazy with temporary local branches, while still maintaining a readable project timeline with references to tickets. Changes don't have to be committed directly to published branches, and here are some examples how to do that.

Local branch for debugging

Debugging sometimes takes a lot of code to be written, and sometimes a few of the changes made during debugging need to be merged and propagated. $ git checkout -t origin/feature/1234 $ git checkout -b debug/1234 Now we have local branch debug/1234 based on feature/1234. Lets do some work in loop, like adding tests, debugging code, applying fixes... everything in commits as small as possible, with meaningful commit messages: $ git commit -m "Added debug code for debugging this and that" $ git commit -m "Added test case proving this and that" $ git commit -m "Tried to fix this and that" The history of the debug/1234 branch will look like the following: #1234 Added debug code for debugging this and that #1234 Added test case proving this and that #1234 Tried to fix this and that We'll still have the feature branch free of debugging related code. You can then merge to this branch to keep it updated with progress from feature branch, but you can also commit fixes to it that you'll want to publish, and then use cherry-pick for including them elsewhere. And if you changed something in your debug/1234 branch, that you'll want to still see in the feature/1234 branch, then simply perform the following: $ git checkout feature/1234 ... merge, cherry-pick, rebase ... $ git push Then, finally some clean up, like so: $ git branch -D debug/1234 We hope you found something useful here, to make working with the workflow more engaging, and help you keep building awesome applications with CakePHP.

Comments plugin 1.3.0 released

We've just released version 1.3.0 of the CakeDC Comments plugin for CakePHP, with a collection of revisions and fixes, as well as an update of the code for 2.5, and a reformat of the documentation inline with the CakeDC Plugin Standard. The Comments plugin lets you easily add comments to any model in your application. The comments structure can also be defined as "flat", "threaded", or as a "tree". To use the plugin simply include it in your application, run the schema or migration to add the comments table, then add the following to your controller: public $components = array('Comments.Comments'); Then, all that's needed is to include the comments in your view, using the following: echo $this->CommentWidget->display(); You'll probably notice that we did nothing with the model. This is handled internally by the plugin, although you can customize the behavior, or use the callbacks provided. The component also boasts a selection of configuration options, to help customize the integration. The plugin also includes an admin interface, for managing your comments, and you can also use the widget helper to define the output or customize via templates. This plugin as well as many others are released as Open Source, free of charge, and maintained by contributions from the CakePHP community. We thank all of our contributors to the Comments plugin, and hope the continued involvement helps keep your favorite framework ecosystem healthy and strong, with a wide range of great plugins to help build your applications.

The annual CakePHP conference

As most of those in the community know, CakeFest is our annual conference, dedicated to everything CakePHP. It's an impressive event, where developers from all over the world come together, share their secret recipes, and talk about baking awesome apps. It's an invaluable opportunity to mix with other talented developers, learn new approaches and techniques, and network with the community at large. With the third major version of CakePHP on the horizon, and a celebration of the project's nearly 10 years of Open Source goodness, this really is an event you don't want to miss. The event itself lasts 4 days, and is broken into two areas. The first area, covering the first 2 days, are the developer workshops. These are hands on sessions with the core developers of the framework, where we show you the best practices and methods to getting the most out of CakePHP. They really are an awesome introduction to the framework, and a headfirst dive into the internals of the project. These are also divided into both beginner and advanced sessions, so everyone attending can get as much out of the workshops as possible. We're also really friendly and involved in the process, to you can reach out to any of us for hands on tips and tricks, or just to get an opinion on your own approaches. The second 2 days are dedicated to the conference part of the event, where a wide array of international speakers will be giving over 20 talks and presentations on CakePHP and related technologies. It's also where we have some of our conference activities, such as the core team Q&A session, where you can pitch your questions directly to the core developers of the framework; an hour of lightning talks, for both newcomers and those with little experience at speaking to give it a shot; the Hour of Contribution, where we introduce you to the Open Source process and open collaboration; as well as our raffle and prize giveaways. And, of course, what would an event like this be without some real cake? At CakeDC we've always been actively involved in organizing, sponsoring and running the conference over the years. For those who don't know, Larry Masters, founder of CakePHP, is also the president of the commercial entity behind the framework. Over the past 8 years we've held the event around the world. From Buenos Aires, Argentina and Berlin, Germany, to Manchester, England and San Francisco in the United States, we've gone all around to make sure we can reach out to as much of the community as possible, and give everyone a chance to get their piece of the cake. This year's event will be hosted in the beautiful city of Madrid, Spain, from the 21st until the 24th of August. So be sure to grab your ticket now, and join us for a jam packed event. You or your company may even be interested in sponsoring this year. Either way, don't miss out on the landing of the big three point oh! See you there.

Tags plugin 1.6.0 released

Version 1.6.0 of the CakeDC Tags plugin for CakePHP has just been released, with an array of fixes and improvements, updated the code for 2.5, and also reformatted the documentation inline with the CakeDC Plugin Standard. The Tags plugin allows you to tag anything in your application, including an additional semantic layer to your models. Getting started with the plugin is easy. Just include the plugin, run the schema or migration to add the tags table, then add the following to your model: public $actsAs = array('Tags.Taggable'); That's it. Then, finding tagged records is just as simple, by using the "tagged" find type, for example: $this->Tagged->find('tagged', array('model' => 'Post')); Alternatively, you could find all records by a specific tag: $this->Tagged->find('tagged', array( 'by' => 'awesome', 'model' => 'Post' )); As you can see, using the plugin is a breeze. Adding tags to form takes no extra effort either, simply add the input to your form, and the behavior takes care of the rest. $this->Form->input('tags'); The plugin also comes packed with an admin interface, for managing tags, as well as a tag cloud helper, as a great addition to your applications. Check it out here, and give it a try. All of our plugins are released as Open Source, free of charge, and maintained by the many contributions from the CakePHP community. We thank all of the contributors to the Tags plugin, and hope that the continued involvement helps keep the framework ecosystem healthy and strong, with many great plugins that help you build awesome applications.

CakeDC Git Workflow - An Introduction

Its been almost a year now since we released, and then later open sourced, the CakeDC Git Workflow at CakeFest 2013 in San Francisco. Since then, we've had loads of feedback, and have also experienced ourselves how it's revolutionized the way we work on projects. When we first set out to define the workflow we had some issues which we wanted to resolve. The main ones being broken staging servers due to unstable branches, an unorganized planning of QA on a build, repeated efforts when testing code which is constantly changing, and messy repositories with no clear organization. Having these problems at hand, we wanted to accomplish a couple of goals:

  • Maintain a master branch which is reliable as a stable and versioned code base
  • Provide a staged code base that's stable and best represents the upcoming version
  • Allow new releases to be comprised of multiple milestones (or sprints)
  • Allow developers to create features from the code developed by others
  • Allow the next milestone to start while the QA process is still active on the previous
  • Allow QA to review code on an isolated branch without affecting the stage server
  • Isolate bug fixing on separate branches to avoid active development during QA
  • Provide a process which can be planned around and scheduled for QA and releases
So, we set out to define a process which would allow us to meet these goals, and help us deliver projects, without the pain of the managing that process itself.

Organize and coordinate

When working with a team of managers, developers and testers, it becomes very important to keep your sanity by organizing and coordinating efforts on projects. When these projects are large in size and scope, that can become a difficult task, especially if you don't have a clearly defined process at hand. And that doesn't just mean defining a series of steps to follow, but a process which sets the team's direction, and facilitates the desired results. The CakeDC Git Workflow does just that, by setting out a clear path to follow, and key points in which members of the team are involved, from managers and developers, through to QA testers and client review. These break down as the following:
  • Development: After gathering requirements and planning out a milestone this is the first phase. During this time the code base is actively worked on, and can be considered unstable, in a bleeding edge state. Each ticket is developed on a feature branched from the develop branch. Peer review would take place on each feature branch before it reaches develop.
  • QA: Once the first phase of development is complete the QA process begins. This is performed on an isolated branch, so the next milestone could commence. The acceptance criteria defined from the requirements would be applied here. Any bugs found by the testers are fixed on an issue branched from the qa branch.
  • Review: Once testing has concluded and the code base is considered stable it's merged to the stage branch, and a milestone is tagged. The client or product manager would now review the results and provide feedback.
  • Release: Once the work completed in milestones constitutes a new version of the application the code from stage is merged to master, and a release is tagged.

Iterating through milestones

At the core of the workflow is the concept of milestone development. A milestone represents a deliverable, and is broken down into 3 phases: development, qa and staging. Each of these has a dedicated branch in the repository, which holds the work completed at each step of the process, and ensures that all work done on the project follows through these phases. The milestone also helps organize the development team as well as the client (product owner), as the workflow keeps everyone in a cycle, which helps avoid feature creep and sets clear and coherent objectives and responsibilities at each point in the process.

Quality as the driving factor

At CakeDC our ultimate objective is to deliver the highest quality possible. This means that all members involved with a project need to provide the best possible to meet that common goal. We do it because we care about what we're building, and want the result to match our expectations as to what the "best" means in each case. Our workflow keeps that philosophy in high regard, as its designed to protect the code base at all times from anything which doesn't meet the grade. Each phase acts as a barrier to avoid the master branch from being compromised.

Search plugin 2.3.0 released

We’ve just released version 2.3.0 of the CakeDC Search plugin for CakePHP with an array of fixes and improvements, updated the code for 2.5, and also reformatted the documentation inline with the CakeDC Plugin Standard. The Search plugin provides an interface using PRG (Post/Redirect/Get) to enable search in any CakePHP application. From simple comparisons of values, to complex search types on any data, even wildcards, expression and custom query methods, as well as subqueries. The plugin gives you all you need, in just a few lines of code. As an example, if you had a controller for products, and wanted to offer a way to simply search among your existing products by “name”, you'd need only include the Prg component, then use it to process the request for the search criteria. Here we show the most verbose example, so it's clear how the component is used. class ProductsController extends AppController { public $components = array('Search.Prg'); public function index() { // start a standard search $this->Prg->commonProcess(); // process the URL parameters $params = $this->Prg->parsedParams(); // generate the Paginator conditions $conditions = $this->Product->parseCriteria($params); // add the conditions for paging $this->Paginator->settings['conditions'] = $conditions; $this->set('products', $this->Paginator->paginate()); } } Then, in your product model, you would just include a $filterArgs property, which defines the fields by which you can search for records. In this case, you can see how the “name” field is defined as a searchable column. class Product extends AppModel { public $actsAs = array('Search.Searchable'); public $filterArgs = array( 'product' => array( 'type' => 'like', 'field' => 'name' ) ); } Finally, in your view, there's no need to do any more than define your search form as you normally would, without the need for any additional options or configuration. echo $this->Form->create(); echo $this->Form->input('product'); echo $this->Form->end(__('Search')); This is just a simple example, to illustrate the potential of the Search plugin. You can find more on the functionality available in the documentation. We're sure you'll find plenty more uses for it, to enhance your application with a search functionality that will keep your users searching for more! As you already know, our plugins are released as Open Source, free of charge, and are helped by the contributions from the CakePHP community. We thank all of our contributors to the Search plugin, and hope the continued involvement helps keep the framework ecosystem healthy and strong, with an array of great plugins that help you all build awesome applications.

Migrations plugin 2.3.0 released

We’ve just released version 2.3.0 of the CakeDC Migrations plugin for CakePHP, and with it a couple of new features, a collection of bug fixes and improvements, an update of the code to 2.5, as well as a reformatting of the documentation, inline with the CakeDC Plugin Standard. For those who haven’t used the Migrations plugin, it’s an essential part of any CakePHP application. It helps keep the integrity of your database schema in check, managing changes as it evolves, and offers you a convenient and simple way to keep track of your database development. The migrations themselves are database agnostic, and all data sources supported by CakePHP are available. You can think of each migration as being a new "version" of the database. A schema starts off with nothing in it, and each migration modifies it to add or remove tables, columns or rows. Fields and tables can be renamed, and their data types can be modified as well within the constraints of the type conversion. Migrations can even be rolled back if needed. There is no more messing with arbitrary named SQL files, as migrations will provide you with a clear and comprehensive way of keeping track of your database changes, within the scope of your application code, as the migrations are a part of your application. As an example, and described in the Quick Start tutorial, generating your first migration is as simple as calling a shell command: $ cake Migrations.migration generate This adds the database migration to your application, which can then be shared with other developers on your team, or used by your deployment system to update your server. You could even use the plugin to create an application installer/updater. Running the available migrations is just as easy, and is also a shell command: $ cake Migrations.migration run all The plugin comes with numerous shell commands to control your migrations, and can be found in the documentation here. One of the new features included with this release is the ability to create migrations from the command line, without any database interaction. For example, we could create a "users" table, with an "id" field as the primary key, a "name" field as a string, as well as the standard "created" and "modified" fields, all via a shell command: generate create_users id:primary_key name:string created modified This is particularly useful for scripting changes to the database, and automating your update procedures. A special thanks goes out to Jose Gonzalez for his contribution! As always, our plugins are released as Open Source, free of charge, and benefit directly from the contributions made by the CakePHP community at large. We want to thank all of the contributors to the Migrations plugin, and hope that future involvement helps keep the framework ecosystem strong, with a host of powerful plugins that keep you all building awesome applications. Thanks!

CakePHP 2.5 and beyond

If you haven't heard yet, CakePHP 2.5 was just released, and with it comes a plethora of awesomeness, such as the new completion shell, the Memcached cache adaptor and support for Amazon ElastiCache, a simple AES-256 encryption API, improved email parsing and validation options, support for unsigned, numeric, real and decimal types, cross origin requests (CORS) and much more. Be sure to check out the changelogs, as well as the migration guide, for a full breakdown of the what's been introduced. With this milestone release, upgrading your code base is now more important than ever, as the framework heads towards a significantly mature and stable state. This directly affects your application, as you take full advantage of that stability, performance, security and a host of features, which help make your application the very best it can be. If you're still on an older version of the framework, and think you may face great adversity in migrating, but still really want to see you code running on the latest and greatest version of the framework, don't hesitate to contact us. Upgrading is vital if you want to stay ahead of the pack, and get the most out of CakePHP.  

Plugins

As we mentioned in an article a while back, we've been busy upgrading our Open Source plugins for CakePHP with the CakeDC Plugin Standard. At the same time, we're targeting them at the latest 2.5 code base, while also testing against Travis CI for greater community involvement on code stability and integration. We encourage everyone who maintains a CakePHP plugin to also review their code, and revise that the changes in this latest version are compatible. And when you do, be noisy about it! Tell the world. Get it registered, and post around the CakePHP community. It's huge, and stretches across the globe. Only together can we make sure the quality of the framework and it's eco-system are strong and healthy, which benefits us all.

Contributing

If you're reading this, you probably use CakePHP, in either your own applications, or possibly at a company which uses the framework for client projects. Most of you may also be well aware of the active development that's currently going on with the third major version of the framework, and may have even played around with the developer preview releases of CakePHP 3.0, which were shared with the community over the past months. Over time, we've grown up with the framework, as well as others, and have helped advance the project to help everyone reap the full benefits of it's extraordinary rapid development. If you're actively involved with the framework, and using it regularly, then don't pass up on the chance to join in with the world wide community of contributors, who help build and shape CakePHP, making it what it is today. And that doesn't necessarily mean writing code. There are plenty of ways you can help out and get involved with the project, and in the process, help maintain CakePHP as the project that it's become over the last, nearly 10 years of it's life time. We're happy to be a part of this journey, and hope that you too join in for the next 10 years to come! The cake was never a lie.

The Imagine plugin

The Imagine plugin for CakePHP, which has been available from the CakeDC account on GitHub, was written as a separate plugin, but complementary to my FileStorage plugin. In the past, the old CakePHP 1.3 times, we've had our Media plugin which we never released. The main purpose of the plugin was to deal with file uploads, but only to the local system and to process images. I've had to work with a few client projects that used phpthumb, which I've learned to dislike because it had its faults and issues. Before reinventing the wheel I simply tried to ask if somebody knows about something modern, OOP, PHP 5+, with unit tests, and had some luck. Imagine is a modern PHP 5.3 library that provides an interface to different image processing back-ends like gd, imagick and imagick shell. Others can be implemented as well. I really recommend this lib over phpthumb, and suggest you to replace it with Imagine if your project is moving on. The plugin for CakePHP is basically a wrapper around the Imagine library, that will autoload the library (because CakePHP 2.0 does not have it's own autoloader until 3.0) and make it available as a behavior. The behavior provides some methods that handle commonly used image operations, like cropping and thumbnails. Besides that, the plugin comes with a helper and a component, which allows it to generate versions of images on the fly. This was more done for backward compatibility for some apps, rather than being a concept that should be used. In fact, it is not the recommended way to handle this. I've written two other articles related to image processing and file storage that explain the issues with that. Instead of creating images on the fly, which is just putting load on the server all the time, you should create the versions of an image after upload. The Imagine plugin works together with the FileStorage plugin, which can use Imagine to generate whatever images you want, right after upload. I originally contributed this plugin, which I developed in my own free time, to CakeDC. But now, it is finally going back to my GitHub user, to pull some maintenance work away from the company. I'll continue to maintain it, and hope you take some time to check it out, and contribute if possible.

The future of the CakeDC plugins

It has been more than 3 years now that we released our internal plugins as open source for the CakePHP community. Some of the first plugins released are now our most popular, like Users, Migrations and Utils. Most of the plugins were developed for version 1.3 of the framework. The later ones were just for 2.x, with the older plugins upgraded to 2.0. It is true that we have sometimes not been happy ourselves with the current organization of the branches and versioning of the plugins. This has been a lot to do with the legacy of the code, which comes over 2 major versions of the framework, and many years of active development. It is probably obvious to experienced open source developers that it's not easy to maintain and test the code for all and every available version of CakePHP. But, we've now spent some time discussing this internally and we are finally able to propose a solution we're happy with. These are the changes that will be made over the next months, to take us to version 3.0 of the framework:

  • Repositories: The branches for the plugin repositories will be updated, and we will focus on tags for releases. Each major and minor version of the framework will also have a development branch, like 1.3 or 2.2. The main develop and master branches will be for the latest version of the plugin, for the latest version of the framework.
  • Versioning: Our current versions are limited to 1.3 and 2.0. This will change, as we will adopt semantic versioning (http://semver.org), and plugins will follow a new version style, that is the core version and plugin version, like 2.3/1.2.1. This would be version 1.2.1 of the plugin, for version 2.3 of the framework.
  • Documentation: We've been working on building a dedicated API site for the CakeDC plugins, very similar to the same one for CakePHP. This should help developers access the technical documentation more easily. We will also be revising the README files for each plugin, as over the years some of these have become less well structured.
  • Testing: As always we take unit testing very seriously. In order to confirm the functionality of the plugins we will be providing build test coverage for each of our plugins on the supported versions of CakePHP, as well as varied versions of the PHP language. This will allow coverage to be viewed by anyone using or contributing to our plugins.
We hope that these changes will help make the CakeDC plugins more accessible and dependable for the CakePHP community. This is the perfect moment to thank everyone who has contributed to the code, helped resolve issues, or even just joined the conversation and provided input or criticism. A contribution can be a bug report or even a feature request. So do not hesitate to tell us via an issue on GitHub that there is something wrong, or you would like to see something useful added to a plugin. A contribution can even be improving the documentation or adding examples for other developers. If you're using our plugins, but don't think the README or API documentation supports your problem, don't hesitate in creating an issue on GitHub, as sometimes other developers can help you out. However, you can also find community driven help and support from the channels listed over at the community center. To get an immediate response the best place is always the #cakephp IRC channel on Freenode. We are frequently available at these locations, but mostly in our free time. Finally, we estimated until today that we have spent more than 600 hours developing and maintaining the CakeDC plugins, not including the time we spend reviewing or discussing issues. We provide these plugins for free, under the MIT open source license, while also providing professional support, in the form of integration or development services. These are just some of the many ways we contribute back to the CakePHP community.

Making great things even greater

If you ever have the time, take a few seconds of your day to check this out: https://github.com/cakephp/cakephp/commit/1e6c7b9d902d6867e3b475bb437eabe98c0acce3 Though this may seem trivial to some, it was a very significant moment in the history of the CakePHP framework. Over 8 years ago now, on the 15th of May 2005, the source code for the project was released under the MIT open source license. So, why was this so important? Simply because it was the first major step which got the project to where it is today. It's also been over 6 years now since the Cake Development Corporation was established by Larry Masters, founder of CakePHP, along side the now departed Michal Tatarynowicz and Kamil Dzielinski. Many well respected developers, as well as contributors to the project, past and present, have set foot in the company, delivering the very best of CakePHP in some awesome projects, while leaving their footprint in the process. And it not only counts for those on the inside, but also the developers from the community, who openly collaborate on the CakeDC open source plugins. These have been a long and colorful six years, full of roller coaster ups and downs, twists and turns, but it's not so much the "when it was created" that counts here, but the "why". Rewind back to 2007, and Larry's proposal was simple: to create a commercial entity which allows people to live and breathe CakePHP, doing what they love day-to-day, while also providing them with a means to support their financial obligations. That's it. Sounds simple, right? Ha! That's much easier said than done, and you’ll soon find out why. Over the coming months we'll be taking an in-depth look at the history and internals of the Cake Development Corporation, giving you a unique insight through a series of posts into how this singular company does business very differently. Hope you enjoy the ride!

Working with a company that embraces o...

I've done my fair share of working for closed and "open" companies. I've recently (in July 2011) clocked over two years working here at the Cake Development Corporation, and while attending the Open Source Developers Conference (2011) in Canberra, I have had some time to reflect on my experiences with the company, and my feelings regarding my work here. Traditionally I have found that companies that claim to be pro-FOSS or open source companies are those that are making a profit, through the use of open source technologies. This is awesome. I love that the proliferation of open source software continues to grow and be adopted by traditionally closed, and proprietary software users. This produces better quality software for all of us. While CakeDC produces a large quantity of client projects that are closed source, what we do have control over is the common reusable components that we use to build and produce web applications for our clients. These are developed and refined over a number of years, and have been a pillar in our success as a company. To be able to draw on years of experience through various developers and quickly build high quality, high performance websites continues to draw attention, referrals and interest from businesses and the community alike. A decision made back in mid 2010, initially proposed by Larry Masters, our President, was to open source all of our plugins. This decision stirred a lot of discussion internally, and there were mixed opinions. While we each individually contribute to open source, speak about it at conferences, engage the community and promote open source, the concept of releasing all our internal code for public consumption for me was a little daunting. The decision was made, and we spent some time cleaning up code, making sure everything was documented and in a good state to release. You can now find all of our plugins and projects on the CakeDC Github Account. The initial load of dealing with issues and support questions, emails and contact from the public was somewhat overwhelming. We deal with issues and features very well internally, but as the process is different to open source projects we contribute to, this produced a somewhat less productive period of time for us while we adjusted our work structure and organisation to accommodate our new open source projects. We now action issues, support requests and other contact from users in a timely manner, and are receiving new and useful commits to the repositories consistently from the community. Overall the experience has been a learning one, and a very positive one. CakeDC support the staff and community in other ways. We are constantly sending staff to conferences both to speak and to attend. This allows us to talk more broadly about CakePHP, PHP in general, and other projects we use and are involved with. It also allows those attending the events from CakeDC a great opportunity to network, and learn from some of the more interesting and innovative minds of our time. This is something that we have come to do through the support of CakePHP, and through our newfound knowledge and experience in working with communities and projects openly. Working with a company like CakeDC, embracing open source and supporting a community like CakePHP is extremely rewarding and equally challenging; and a job without challenges is not what that I would want to be involved in for any long period of time. After speaking with many people working on awesome, interesting projects that are closed, or "not ready" to open source, I really count myself lucky to be working for a company that has embraced open source, contributed to the community, and demonstrates a dedication to supporting those projects and communities.

Call out to the CakePHP community

Everyone knows CakePHP has one of the largest and most loyal communities in the Open Source world, over the last few months we have been witnessing some very disturbing things happening to one of our community members. Many of you may know Jonathan Freeman over at Widget Press he created some tools that have helped many people build applications using CakePHP. He has also been a target of a patent troll suing him for patent infringement. As a software developer I find the tactics of the software patent trolls to be one of the biggest hurdles of innovation in todays development market, too many people afraid to pursue an idea because they fear being sued by a company who had an idea and was not skillful enough to build something from that idea. What upsets me even more is these trolls target people or companies who do not have the funds to stand up to "Goliath" and defend themselves. Well today we as a community need to help one of our own standup and become a David facing Goliath. What I am proposing is helping Jonathan gather some "stones" in the form of small donations from our community. If we have enough people donate we might be able to help him arm himself to defeat the troll "Goliath". We (Cake Development Corporation) are putting up $1000.00 for his defense fund on behalf of the CakePHP project and I am asking people in our community to help also. You do not need to donate this amount or you can do more if you like, any amount will be useful. But let's come together like an unexpected force and help one of our own. Updated information, if you can not donate money to help Widget Press maybe you can help  via ArticleOne on twitter.com "We launched a Second Study around a #patent in the MacroSolve App Developer case, this time with $10,000 #Reward http://ow.ly/5tO9f"

Tags Plugin release v1.1

Following the release an update for our Utils Plugin, we've compiled a few commits that have been finalised on the Tags plugin, bundled it and packaged for release. The tags plugin, if you've not used it, is a great and simple plugin that allows you to apply tags to any object in your existing application without modification of tables or structure. Its unobtrusive, and awesome. This latest update takes it to v1.1 with the following changes:

  • Commit [79afb1d]: Update inline docs, and test behavior removal for #5
  • Commit [0d96881]: Renamed schema to work properly.
  • Commit [982ff5b]: Minor readme update.
  • Commit [edd0e8e]: updating readme
  • Commit [db78a26]: update russian translation plural forms
  • Commit [48c1a44]: Adding spanish translation
  • Commit [3347464]: Added Portuguese translation
  • Commit [f4c4e6b]: Adding german translation file
  • Commit [44379a7]: Update license text.
  • Commit [da433cb]: Cleaned up headers for all files.
  • Commit [8c76f95]: Renamed license and readme files.
  • Commit [6e6eae4]: Renamed license and readme files.
  • Commit [99f1e89]: Added an initial Russian translation
  • Commit [93a7ad6]: Documenting identifiers in tags and the new taggedCounter behavior option
  • Commit [0242a6e]: Adding assertion to ensure trailing whitspace is removed before saving the tag
  • Commit [2de4e80]: Fixing remaining failing test cases
  • Commit [d03e1a6]: Adding the ability to have a counterCache to track the times a record has been tagged with a particular tag
  • Commit [5527079]: Fixing bug in saving tags with identifiers prepended. Refactoring code to avoid repetetions
The tags plugin received a number of ticket submissions over on lighthouse app from the community. We can't thank you enough for taking the time to submit questions, issues and suggestions to the ticket system. Its helped us fix problems and extend the plugin to become an even more useful plugin for your apps. The release is available now on the master branch of the repository, or you can download a release archive here. We hope you enjoy the update!

Using the CakeDC Tags plugin for CakePHP

This is an introduction to using the CakeDC Tags plugin for CakePHP. I'll take you through a new project creation, and the addition of the Tags plugin to your project for use with tagging a Blog model on your project. You should be able to take the skills learnt here to any other project, and start taking advantage of the Tags plugin for tagging your models appropriately. Lets get started by baking a new project: cake bake project blog1 Follow the prompts to complete the baking operation. You will now have a "blog1" directory available. Change into that directory: cd blog1 ensure that the `tmp` directory is writable: chmod -R 777 tmp Open up the `config/database.php.default` file in your favourite editor. Immediately choose to "Save as..." and save the file in the same location omitting the ".default" part of the filename. So save the file as `config/database.php`. Configure the options at the bottom to match the database credentials for your application. Mine are as follows: <?php class DATABASE_CONFIG { var $default = array( 'driver' => 'mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'dev', 'password' => 'dev', 'database' => 'blog1', 'prefix' => '', ); } For the moment, I have remove the 'test' datasource, as we won't use that right now. Go ahead and create your MySQL database, and a simple table to hold blog items: CREATE DATABASE `blog1`; USE `blog1`; CREATE TABLE `blogs` ( `id` CHAR(36) NOT NULL PRIMARY KEY, `title` VARCHAR(255) NOT NULL, `body` TEXT, `created` DATETIME, `modified` DATETIME ); Now lets bake the controller, model and views for this blogs table, in order to be able to add and edit content. Once this is complete, we'll begin integrating the tags plugin into the application. First bake the model: cake bake model blog Next bake the controller. The following bakes all the "public" actions for this controller: cake bake controller blog public And finally, the views: cake bake view all Browse around your application at the address: /blogs to begin with to ensure that your app is functioning correctly. You should be able to add, edit, delete and view blog entries. Time to get cracking on the Tags plugin. Our objective here is to tag each blog entry with an arbitrary tag at add / edit time to allow us to easily categorise content we are posting. In order to download and install the Tags plugin, I'll be using git. You can however download an archive from the github website, and extract that archive into your `APP/plugins` directory. In either case, the result will be a `tags` directory in your `APP/plugins` directory, containing the contents of the CakeDC tags plugin. From your `APP` directory (in this example, the APP directory is `blog1`), clone the tags repository: git clone git://github.com/CakeDC/tags.git plugins/tags The first thing that we need to do now that the Tags plugin has been added to our project, is to create the tables required to store the tag information. These are available in schema's and migrations within the Tags plugin, so you don't need to handle the SQL yourself, just use the cake console to create the tables for you: If you prefer using the builtin CakePHP schema mechanism, or you are not sure what the "migrations" plugin is, you can create the database tables like this: cake schema create schema -plugin tags -name tags If however, you are familiar with using the migrations plugin, or you want to use the migrations plugin for this project, add the migration plugin to your project, and then run the migrations: git clone git://github.com/CakeDC/migrations.git plugins/migrations cake migration -plugin tags all Either method is fine. Next up, we need to add the `Taggable` behavior from the `Tags` plugin to our model to enable all the awesome functionality. Add the following variable to your `Blog` model in `APP/models/blog.php`: public $actsAs = array( 'Tags.Taggable' ); Finally, we need to add a new input for the tags on our add and edit screens, to allow users to customise the tags they want for the blog posts. Simply add a new input called 'tags' to your forms, such as the following: echo $this->Form->input('tags', array('type' => 'text')); Note that this needs to be done for both your add and edit views. You can also make this be of type `textarea`, if you need gigantic amounts of tags. `text` is fine though, to allow a good number of tags, and to minimise the input space. This is all you need to do to enable your content to be tagged! Looking back at all the instructions so far, the bulk of the content has been on how to create a new project, bake the model, views and controller, and the addition of plugins. In terms of code addition, we've only added a behavior to the Blog model, and a new input to the add and edit views. To test your tagging, use a comma to separate your tags when using the tags input. Using a comma allows you to enable users to add multiple-word tags. What now!? You can tag stuff, thats pretty cool. You probably want to look up blog posts based on tags now. Thats already provided for you in the Tags Controller quick comes with the Tags plugin. Browse to `/tags` to see the tags controller index action from the tags plugin render all the tags that you have added to your blog so far. There is a whole lot more that you can do with tagging in terms of both operation and the visual representation of the tags themselves. Stay tuned for more blog articles explaining our plugins and other interesting PHP and CakePHP code from myself and the rest of the CakeDC team. UPDATE: An excellent guide on how to style the tags with CSS has been written by @WyriHaximus, check it out here.

Utils Plugin release v1.1

The Utils plugin is our mixed bag of "awesome". If you've not yet checked it out, definitely hop over to github to check it out. It aggregates a lot of useful code and miscellaneous ideas into a single plugin thats portable and dead easy to use in your applications. Since its release in September, we've made a few changes and updates, and we've bundled a new version for release. Here's a summary of the commits:

  • Commit [7bdf401]: Update license and readme.
  • Commit [e7630bd]: Added tests for data retrieval and false return from model delete.
  • Commit [8510fe4]: Updated documentation for Soft Delete tests.
  • Commit [f7d9983]: Removed empty test file.
  • Commit [c5db61b]: Changed the behavior saving the position manipulation without running model callbacks and validation by default. This is now also configureable by setting 'callbacks' and 'validate' in the behavior settings to true/false.
  • Commit [ca98003]: updating readme
  • Commit [edc6576]: updating readme
  • Commit [da6ec86]: Add a russian translation
  • Commit [a2319ca]: Adding spanish translation
  • Commit [752f1d7]: Added a Portuguese translation
The release is available now on the master branch of the repository, or you can download a release archive here. Don't forget if you have any issues, suggestions or fixes for the utils plugin, you can lodge a ticket on Github. Enjoy!

CakeDC Plugins updates, October 2010

Its been a little while since we launched our plugins at CakeFest 2010 to the community, and a few things have been changed and updated in that time, so its time to throw out a new release for the community. We have received a huge response after opening our code to the community, and we're absolutely thrilled to know that you're taking advantage of the experience and effort that CakeDC has put into making these plugins. Getting feedback and hearing stories about usage makes it all worthwhile. The team has been monitoring tickets, and cleaning up where we can in-between "real work" :) Thanks to everyone that lodged tickets, submitted patches, we're overwhelmed with the generosity that people have shown by contributing to help benefit the community and to further the work we began. This blog marks the beginning of a run of updates we're doing with the plugins that have been released. We'll process tickets, package and release new versions every couple of weeks to ensure we're on top of tickets, and getting any updates published for people to use on a regular basis. We hope you enjoy the upcoming releases, and thanks again for the support! From all the team at CakeDC.

i18n routes with CakePHP 1.3

Internationalizing a CakePHP application can be tricky when it comes to deal with i18n urls. We will see in this article how the Custom route classes introduced by CakePHP 1.3 could be used to add the current language to your urls in a few lines of code. EDIT: This proof of concept has now been improved and a better version of the code below can be found in CakeDC's I18n plugin on Github

Requirements

This article will not go too deep in internationalizing an application as many resources already exist about it. We suppose the following:
  • Your application defines the current language on given the language code passed in the url
  • The available languages are configured via Configure::write('Config.languages', array('eng', 'fre', 'deu'));
  • You use the CakePHP array syntax for defining urls:
    • $this->Html->link('link', array('controller' => 'posts', 'action' => 'view', $post['Post']['id']));
    • $this->redirect(array('controller' => 'posts', 'action' => 'index'));
    • Router::url(array('controller' => 'posts', 'action' => 'index'), true);
Custom routes were already introduced by Mark Story on his blog, so we will not do it again here... before continuing be sure you have read "Using custom Route classes in CakePHP"

Show me some code!

I18nRoute

As I said (or not), routes are probably the best place for customizing your urls and add information in them... much more better at least than overriding the Helper::url() method in an AppHelper class! Custom routes introduced a way to customize how routes are processed in a very easy and powerful way (i.e ~20 lines of code). It is a bit like wrapping the Router class in CakePHP 1.2, a good example of this was the CroogoRouter. First, we are going to create an I18nRoute class extending CakeRoute in the "/libs/routes/i18n_route.php" file. Here is its code: <?php class I18nRoute extends CakeRoute { /** * Constructor for a Route * Add a regex condition on the lang param to be sure it matches the available langs * * @param string $template Template string with parameter placeholders * @param array $defaults Array of defaults for the route. * @param string $params Array of parameters and additional options for the Route * @return void * @access public */ public function __construct($template, $defaults = array(), $options = array()) { $options = array_merge((array)$options, array( 'lang' => join('|', Configure::read('Config.languages')) )); parent::__construct($template, $defaults, $options); } /** * Attempt to match a url array. If the url matches the route parameters + settings, then * return a generated string url. If the url doesn't match the route parameters false will be returned. * This method handles the reverse routing or conversion of url arrays into string urls. * * @param array $url An array of parameters to check matching with. * @return mixed Either a string url for the parameters if they match or false. * @access public */ public function match($url) { if (empty($url['lang'])) { $url['lang'] = Configure::read('Config.language'); } return parent::match($url); } } The most important part of the code is in the "match()" method. We just add the current language to the url "lang" named param if it was not set. The constructor was also overriden to add a regex pattern for the "lang" param. Thus, only lang prefixes defined in your list of available languages will be parsed by the route.

Define your routes

It is now time to use this custom route in your application. Here is how the default route for pages could be defined in "/config/routes.php": App::import('Lib', 'routes/I18nRoute'); Router::connect('/:lang/pages/*', array('controller' => 'pages', 'action' => 'display'), array('routeClass' => 'I18nRoute'));
  1. import the library file containing the custom route
  2. add a ":lang" param in where you want the language code appear in the url
  3. tell the Router you want to use this custom class (third param)

Link from everywhere!

Now you won't have to worry about the language code transmitted in your urls... every generated link will contain the current language code. If you want to switch the language (for instance switching to the French version of your application), you will just have to add the "lang" param to the url array. Here are some examples of urls which would be generated on the "/eng/posts/index" page: $this->Html->link(__('French', true), array_merge($this->passedArgs, array('lang' => 'fre'))); // /fre/posts/index $this->Html->link('link', array('controller' => 'posts', 'action' => 'view', $post['Post']['id'])); // /eng/posts/view/2

Disclaimer

This code is experimental and the article shows you how to use CustomRoutes to implement this basic feature. Many improvements could be added to fit your needs (no language code for the default application lang, short languages code...) Even if the tests we made were successful, we have not used this code in production yet so there may be "real word" use cases that are not handled correctly with this solution... if you find one, please tell us in the comments!

We Bake with CakePHP