Tag Archives: CakePHP

CakePHP3 with Hashids

Security by obscurity is never a good policy but there are still some legitimate reasons why you would want to hide your id’s. One good reason is that you don’t want to reveal how many users you perhaps have or at what rate your membership is growing. Making it difficult for the average website visitor to cycle through your id’s by just changing the URL is also important.

The following code should be used with other security measures that check that a user is authenticated and authorized to access a particular record or group of records. The implementation of such security is outside the scope of this article. Reading the CakePHP3 manual should provide you with enough detail on how to achieve this or alternative you should read my previous blog post on using CakePHP3 with TinyAuth.

Install the Hashids Library

The following is all based around using the excellent Hashids.org library. The library has been ported to a huge number of languages. You should visit the website and read the docs for more specific information.

All CakePHP3 users should be familiar with composer, so using the following method to install Hashids is prefered.

Update AppController

Add the following code to your AppController

Notice you can set a couple of parameters. First you need to create your own “salt” just vist random.org and generate a string of characters. You can also change the “min_hash_length” and change the “alphabet” characters that are used for string generation.

Using Hashids in Controllers

Encoding and decoding id integers is now super easy.

Typically I use the decode function inside of controllers as the id string will already be encoded inside the view template and passed back to the controller.

Using Hashids in Template Views

First we need to pass an instance of hashids() to the view. We do that with $this->set().

The important bit is this.

Then inside of views we can access the hashids() object.

You can also use this inside loops to encode or decode lists of id’s and so forth. Let me know if it helped you out or you think the code can be improved.

That’s really all there is to it!

[box type=”alert” size=”large” style=”rounded” border=”full” icon=”empty”]Since writing this article a better cleaner solution is available from the UseMuffin Team. I recommend the UseMuffin/Obfuscate CakePHP 3 Plugin: https://github.com/UseMuffin/Obfuscate

This plugin supports a variety of external obfuscation libraries and the behavior can be configured on a per Model basis.[/box]

CakePHP 3 with TinyAuth & Blame

I want to walk you through a blank CakePHP 3 setup and install a few worthwhile plugins. The primary goal of this post is to show how to setup Dereuromark’s TinyAuth plugin which is fantastic however may leave a few newbies scratching their heads trying to get it set up. So what follows will be a cookbook style approach with copy and paste code.

There is a number of ways we could setup TinyAuth and these are outlined in the manual however I’m just going to show you the Users HasAndBelongsToMany Roles method that way you should see how to revert back to the other “Role Base Access Control” possibilities.

So let’s get started.

Download CakePHP 3

Change [app_name] to the name of the folder that will house your application.

You may also need to make sure the the cake bake feature has the right permissions set. Run the following if you get a permissions error when using the migration commands below.

Create Table Migrations

We’ll need three tables for this to get us started, users, roles and roles_users table. Open your terminal and run the following.

Make sure you have setup your database connection in config/app.php otherwise you will get an error when trying to run the migration commands.

Once the commands above have run successfully you should have 3 new migration files in config/Migrations. Next open up all 3 files in your favorite editor and drop in the following code.

Place this code in your create_user_table.php file.

Next place this code in your create_roles_table.php file.

Next place this code in your create_users_roles_table.php file.

Now run your migrations in your terminal us follows.

 Bake All

Run the cake bake command to create all your models, views and controllers.

 Load Plugins

Ceeram Blame

Next lets load in the plugins we will use. Ceeram’s Blame plugin keeps track of who changed what. You will notice the created_by and the modified_by fields in both the Users and Roles Table. All future tables should also contain those integer fields if you need to keep track of changes made by users.

 Dereuromark TinyAuth

Run the following to load Dereuromark’s TinyAuth.

 Edit Bootstrap.php

Next edit your config/bootstrap.php file. Load the following plugins.

 Authentication with Cake Auth

Let set up the login, logout part of our website. Open up src/Controller/AppController.php and load the auth component with a few settings passed in. Notice we have setup the “authorize” part to use TinyAuth.

Next open up src/Controller/UsersController.php and add the following login, logout methods.

Let’s also add a beforeFilter method that will allow as to override certain method/views so that unlogged in users can access certain parts of the website. Do this for both the User and Role Controller.

Now open up src/Template/User and create a new file called login.ctp then add the following

Next open up src/Model/Entity/User.php and add the following to hash the password.

 TinyAuth acl.ini

Last but not least we need to create an acl.ini file in our config folder. Add the following as a starting point.

Your app should now be fully secured. Try login into to any location such as users/index and you should be bounced back to users/login.

Blame Someone

Lets finalise the Ceeram Blame plugin. We needed to setup the authorization in order for the Blame plugin to know who was logged in so that it can associate a user id with the created_by and modified_by fields.

Simply add the following to your AppController

Next add the Blame Behavior to each of the Role and User models. Go to src/Model/Table.

 Finished

Now you should have a full working login, logout app with the ability to set up role types and set permission for your views! Awesome!

If you have trouble please check out my git repo and compare the code. Alternatively you can clone my repo for a starting point for your next cake project. Download from BitBucket: cakephp3-loaded

[box type=”alert” size=”large” style=”rounded” border=”full” icon=”empty”]Since writing this article a better cleaner solution is available from the UseMuffin Team. Instead of the Blame (depreciated) Plugin I recommend the UseMuffin/Footprint CakePHP 3 Plugin: https://github.com/UseMuffin/Footprint[/box]

CakePHP3 Database Migrations with Phinx

[dropcap]C[/dropcap]ontinuing on from my last post CakePHP3 Database Migration Commands as I promised this is a follow up with actual working examples that you can use right away. The database migrations I have put together use CakePHP3 Model & Database Conventions and so you can be sure all tables will be picked up and correctly related to each other with a “bin/cake bake all {model}” command.

I thought we could create a simple “countries” and “states” model/table migration. This will give us an idea how to create a Migration for each database table and also how to create the Migration with a has many foreign key relationship.

Create Countries Table Migration

So let’s start by creating a new Migration that will allow also to create a “countries” table.

This will generate an empty migrations file in “config/Migrations”. The migration file should have a datetime stamp appended to the file with create_countries_table. So your file should look something like this “20150316082226_create_countries_table.php”.

Next we need to open this file and add our code that will create the countries table. So our countries table will have the following fields and data types, id(integer), name(string), acronym(string), created(datetime) and modified(datetime). The created and modified field are special CakePHP fields that will be automatically updated when database records are created or edited. This is a “behavior” that is attached to the Model/Table/CountriesTable class when we use cake bake.

The Up Method

So there is a little bit happening here, there are three methods that are automatically generated by CakePHP Migrations (Phinx), that is the change, up and down methods. The change method is commented out by default. We are only concerned with the up and down. Within the UP method we are calling a table object and passing into it declarations. In it’s most basic form it’s simply as follows.

Describe the Table

Obviously you need to tell Phinx what you want to name the column and the type of columns you need e.g. integer, string, text, datetime and so on. For more please see the Phinx Valid Column Types. See the basic example below. Notice that we also added an index to the name column. Also note that we have specified a “length” of 255 to the name column. This will create a varchar(255) column in our database. We have also specified “null” as false, this is a default behavior and so it doesn’t need to be stated however I like to be verbose as it makes it easy to simply change it in the future if you later decide to allow null on that column.

In the above example by default Phinx will create an ID column for you named “id”. If you need to override this you can turn off id => false and specify you own id field with ‘primary_key’ => [‘your_id’]. So depending on your table naming conventions you can leave it or override the default behavior. Example with id override below.

Note that because we have specified our own id column we can have control over it’s attributes. Signed false means that it’s cannot have a – or + symbol in front of it. The identity true attribute means the field will be auto_incremented with a unique id each time a new row is created.

Insert Data

After the table is created you can use the following code to perform database tasks with SQL. The most common thing you might do is insert some default or dummy data.

The Down Method

Migrations are all about being able to reverse changes or “rollback” database tables to a previous state. So note in the down method you can place the following code.

Migrate the Database

Now just run the command line migration tool

Using your favorite database tool like Sequel Pro or MySQL Workbench you should see a new countries table in your database. If you wish to rollback use the following command line. Run the rollback command for each migration.

Add States Table Migration

Let’s now create our States Migration. Run the following in your terminal.

Now find the newly generated create_states_table.php file and add the following data into your up and down methods.

This migration includes all the column specifications. You will see a few new ones. The most important is the “country_id” foreign key column to link us to our countries table. This is named country_id and not countries_id according to the CakePHP convention. This makes sense as the states.country_id is only referring to a single parent country.

There are also a few interesting column types to suit longitude and latitude information. Make sure you look closely at the column type and the new attributes.

The rest should be much the same as the CreateCountriesTable migration.

Add Foreign Keys Migration

Next we need to add a foreign key constraint to the states table. This will link the states table to the countries table on the states.country_id colum to the countries.id column.

I personally prefer to create a separate migration for all my foreign keys. I also usually make this the very last migration after all my tables have been created. The reason is because when you rollback all the foreign keys need to be dropped first from all the tables in the database. This will allow you to rollback and drop the previously created tables without an error. If you don’t drop the foreign keys before you attempt a rollback the migration will fail because of a foreign key check error. The opposite is also true, if you try to migrate a table with foreign keys and the linked table hasn’t been created yet the migration will fail.

So let’s do the following in the terminal.

Open up the generated add_foreign_keys.php file and dump in the following code.

Notice that the code for adding and dropping a foreign key are almost the same but see the subtle differences.

Migration Complete

Just one more thing, re-run that migration again in the command line.

For more helpful tips on CakePHP3 Migration Commands see my last post.

I hope that’s given you an insight into how to handle CakePHP migrations in any new CakePHP3 project you might undertake. The advantages of migrations are evident, you can keep it under source control and all members on your team can stay on the same database schema.

This knowledge however is not restricted to the CakePHP3 framework, you can include the Phinx Migration library into any PHP project. So your new found knowledge is portable.

Go migrate something!

CakePHP3 Database Migration Commands

A list of a few helpful commands to use when creating database migration files.

Check the status of migrations

This would show something like the following

 Migrate (up) All Pending Migrations

 Rollback (Down) Last Migration

 Create a New Migration File

The above command should be used for each table you create or any table modification you perform. It’s good to keep each migration name descriptive so for example if I was creating a maps table I would name my migration CreateMapsTable. NOTE: CakePHP3 (Phinx) migrations require that you use CamelCase for migration names.

My next post will explain how to create database table migration files with a table example for both up and down methods.

Install CakePHP3 on Laravel Homestead

This guide is not comprehensive, it is assumed that you have already installed Vagrant, Laravel Homestead and VirtualBox. The guide is based on Mac OSX10.10.

CakePHP3 requires the php5-intl extension that at the time of writing is not by default installed on Laravel Homestead. The good news is that it’s easy to install.

First you need to ssh into your Homestead Machine.

Next you need install the php5-intl extension. Also do an update while you’re at it

If you are missing other php5 extensions that you need you can use the above command, just change the php5-extension name.

Now you can install CakePHP3 with composer.

If you prefer to install CakePHP3 a different way please see the CakePHP3 installation documentation.

Now you should be able to visit your CakePHP3 installation using the URL you have setup, example.local etc. You will need to consult the Laravel Homestead Documentation if you’re not sure what this is.

The problem however is that you may see there are no CSS or Javascript files being loaded. The reason for this is because Nginx has set the DocumentRoot incorrectly. It’s easy fixed. More information on using Nginx.

Use cd to change directory into Nginx “Sites Available”. Edit your site config file “example.local” using nano or whatever is applicable to your setup. Find the “root” declaration and edit as follows.

You may need to restart your Homestead Machine.

Now when you load your CakePHP3 installation in your browser it should load all the CSS and Javascript so that it looks correct.

Enjoy, if you have any question leave them in the comments and I’ll do my best to help.

Install CakePHP2 on Codio

I only just discovered Codio yesterday! How come nobody ever told me about this? If you haven’t tried it yet and you are a keen programmer you should try it out. Chances are though you here because you are trying to get CakePHP2 working.

Well I’ve put in the hard work for you so just follow the steps below to get it working.

Step 1 – Create Project

  1. Create a new project.
  2. Give it a name. I named mine CakePHP2 but you can call it what you want.
  3. Select the “Template” tab.
  4. Choose “Empty project” from drop down list.
  5. Click Create

Sit back while your virtual machine and programming area is created for you. Step one is done.

Step 2 – Install Apache2, MySQL and PHP with PHP Modules

Your new project should launch with a tab called “Backend”, this is just a terminal you can use to run commands. If for some reason it’s not showing just go to Tools > Terminal. Then run the following command to install Apache2, MySQL and PHP with PHP Modules.

You will notice a few important things are installed

  1. Apache2 – Webserver
  2. MySQL – Database Server
  3. PHP5 – Version 5.5.15 (at the time of writing)
  4. Composer – PHP Package Manager
  5. PDO – Required for CakePHP database connection

After installation you are given some important information about where to find things later such as the php.ini and httpd.conf files etc.

You might also be wondering what “parts” is? It’s the codio command for doing a variety of things such as package installation and starting or stopping services such as Apache2. For example “parts search php” lets you search PHP packages that you can install. Lets do that now by installing PHP My Admin, we will need it later.

for good measure let’s restart Apache

Now you should be able to go to the last Menu option on the right and select “Box URL”. Then type /phpmyadmin on the end of the URL. You should now see the PHP My Admin login page for MySQL.

Before we can login to PHP My Admin we need to add a password to the default “root” user of MySQL. Let’s do that with the following command. Change “newpassword” to the password you want. You may need to start MySQL first.

Now that you have added a password to your “root” MySQL account you can go to the “Box URL” and then access /phpmyadmin. Then login with the following

  1. User: root
  2. Password: newpassword

Now that you are logged in to PHP MyAdmin go ahead and create a database for our CakePHP installation. I created a database called: cakephp but you can create and name as many as you like. You can also create database users however remember to GRANT access to these newly created users.

Step 3 – Install CakePHP2 with Composer

We now can install CakePHP. The environment is ready and we have a database ready to use with root/newpassword. First make sure you are outside of the “workspace” folder. In the terminal you can type the “pwd” (present working directory) and it will show you where you are. If you have followed the guide so far then you should be by default be inside the workspace directory however we want to move up a directory to the /home/codio/ directory.  To move back directory you can type “cd ..”. So once you sure you’re inside the “codio” directory type the following.

You may get an error saying that composer needs an update. That’s easy to fix with the following command line. Even with the error CakePHP should have successfully downloaded. You can check by using “ls” to list the items in the folder. You will need to first “cd workspace/” to see the downloaded CakePHP files.

After all this you should now be able to select “Box URL” and see a working copy of CakePHP. You will however notice a few errors. Lets fix those errors now.

Step 4 – Fix CakePHP Errors and Tidy Up

Since we are getting good with composer lets add the official CakePHP Debug Kit so that error goes away.

Next open app/Config/bootstrap.php and add the following

Lets now fix the WARNING: strtotime() error. This is an easy one. Open app/Config/core.php and uncomment the following line.

While we have the core.php file open lets change the Security.salt and Security.cipherSeed values. That gets rid of two more errors.

Last but not least let’s now connect our database. First you will need to create a new file app/Config/database.php. You can copy and paste the code from app/Config/database.php.default. Once you have done that edit the following code with your database user and password.

Make sure you edit the $default datasource and NOT the $test otherwise you will not see any changes.

Installation Finished

Give yourself a pat on the back, that wasn’t to hard was it. I hope that this guide gives you an idea of the process used for installing various packages. With the power of composer the world is your limit. You should be able to set up any PHP package available to you. Once CakePHP3 goes stable then you’ll be ready to install that as well!

Happy app building.

 

Encrypt & Decrypt CakePHP2 Database Fields

In a current project I’ve been working on I needed to encrypt and decrypt database fields such as user phone numbers and email address. While this is not the only security measure you should have in place it’s certainly worth while for sensitive data that you want to provide a little extra obscurity for. Remember that this trick just encrypts the data so that means that it can be decrypted, in other words a determined hacker could still decode this information if he also gain access to the Security Salt.

You need to add two callback methods to your AppModel.php file. The first is a beforeSave which will encrypt the data before it’s saved and the second is an afterFind function that will decrypt the data after it’s retrieved from the database.

Include the following functions between this code in your AppModel.php file.

beforeSave Function

afterFind Function

The above examples show email, mobile_number, home_number etc being encrypted/decrypted however you could change this for any field you wish. I have also wrapped the encrypt/decrypt code in an if statement to check if there is any data or not as I was finding that even if the field was empty it would still encrypt a “blank” into the database. So for the sake of performance I figured it was best to only encrypt or decrypt when there was real data and not empty fields.

Another thing to be aware of is to change your database fields to VARCHAR(255) otherwise if your field is shorter the encryption hash will get trimmed and will not decrypt properly. I’m also using the CakePHP Security.salt found in the Config/core.php file however you could and probably should use a different generated Security Salt.

Another easy CakePHP tip that works well. Enjoy.

Limit CakePHP2 Results by YEAR, MONTH or DAY

You can never have to many tricks up your sleeves when it comes to pulling the data you need from your database. Sometimes you only want to return a limited set of results based on the year, month or day. So how do you do this?

The solution is quite simple. The following code can be used as part of a find(‘all’), find(‘list’) query or as part of a containable condition.

You could remove the PHP date() function and pass in variables rather than fixing it to the current year, month or day. The YEAR(). MONTH() and DAY() functions are special MySQL functions that wrap around your Model.date field (or any date field in your DB) field and pulls only the relevant results.

Another good simple CakePHP trick!

CakePHP2 Find Neighbors Method with UUID Primary Keys

I recently decided to switch over an application I have been developing from using INT primary keys to use CakePHP’s ability to generate UUID primary keys. It wasn’t difficult to do, you simply set the primary key to BINARY(36) and Cake will do the rest. (the CakePHP manual recommends VARCHAR(36) or CHAR(36) however do a bit of reading and you’ll find that these are not the quickest)

That said there are always problems that you don’t foresee  as a result of a small change like this. The problem I faced was that records could no longer be sorted by id. As it was I generally don’t sort by id but by a unique field with a simple ASC or DESC sort. This works most of the time except when you want to find the previous or next record…

In one instance I was using the find by Neighbors method to create some simple NEXT and PREV links to move between records. The task is simple with the follow code when using INT as a primary key.

That works well with ID’s but not with UUID’s. So what can be done. Well you need another field in your model that you can sort your data by. This may mean that you have to create a “sort” field or perhaps like me you have a simple “date” field in your model. In my application this works well because I have only one date for each week of the year so I never have a record with the same date. Here’s the solution I eventually got working.

It requires an extra line of code. The magic findById method is used and then we can set the value of “value” to “$order[‘Model’][‘date’]” and set the “field” value to “date”.

This returns a nice array for you to use in your view.

A simple tidy solution to what at first seemed complicated.