Posts by harrybailey.

Yii upgrade service

Yii 1.1 is currently in maintenance mode following Yii 2 being released way back in May 2013.

Support and bug fixes for Yii 1 were only provided until December 31, 2016 and security fixes and PHP 7 compatibility ends December 31, 2020.

That means that right now the only reason updates to Yii 1 are being created and made available are for security issues found in the existing codebase, and from 2021 it’s mothballed completely.

If you’re maintaining a Yii 1 codebase it’s time to start thinking about how to migrate away from Yii completely, or upgrade your codebase to Yii 2.

There is an official guide aimed at supporting the upgrade process, but it is unlikely to get you from Yii 1 to Yii 2 without significant pain and head scratching.

Converting from Yii 1 to Yii 2 is completely unlike developing code for either framework, and you’d want to source a Yii upgrade professional rather than getting an inexperienced developer or team involved with a large or mission critical codebase.

Personally I’ve now upgraded four codebases from Yii 1 to Yii 2. All the upgrades have been different. All follow a similar path, and the repeatable process I’ve created, but each has its own edge cases, bespoke widgets and complexities.

The work takes many days per codebase before testing and perfection can happen, and where an existing development team are involved with ongoing development or support of the Yii 1 system, it’s best handled as a team effort. Acceptance that the process isn’t anywhere close to just flicking a switch or downloading a patch is required from day one.

At this point I’m considering two next steps.

Firstly, if your company has significant budget and is in need of support moving from Yii 1 to Yii 2, I’d be interested in hearing from you. You may want a supportive voice helping your existing developers to make the move. You may also be looking to hand over a Yii 1 codebase and get it back ready for some testing and iteration.

Secondly, I’m considering sharing some or all of the process I’ve created for manually moving a codebase over from Yii 1 to Yii 2, the gotchas, the process and how to update specific things within Yii 1, where it isn’t as simple as a like

Feel free to send me a direct message on Twitter @harrybailey or leave a comment below if you’d like to contact me.

Security of WHM backups to an AWS S3 bucket

When you give your Web Hosting Manager (WHM) the ability to send a copy of your backup to Amazon’s AWS S3 service, you have to hand it a Key and Secret that give it that permission.

The worst option is to hand over a Secret and Key related to your own log in.

The best is to:

  1. Create a policy which
    • Only gives access to a single bucket
    • Only allows the least access required for the task
    • Only allows connections from trusted IP addresses
  2. Create a Group to connect the policy to
  3. Create a user (for the WHM) to connect to the group

For validation of connection to S3 WHM currently requires the ability to write objects, list all objects in a bucket, delete objects. Now for some this is frustratingly more than you want to hand over. In theory WHM could make do with just the ability to write to the bucket, but at the moment we have to make all those abilities available.

Luckily, the fact we’re also limiting by IP and then Secret and Key—which WHM encrypts when you submit them—should make it highly unlikely anybody else will be able to abuse the ability to delete objects.

Here is the example policy that I have in place. Feel free to copy, personalise and use:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "WHMBackupAccess",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_BUCKET_NAME",
                "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "YOUR_SERVER_IP/32"
                }
            }
        }    
    ]
}

If you’re in need of help putting this all together, let me know and I might expand this post to include how to do the setup inside WHM and the AWS console.

.htaccess redirects based on date and time

A useful trick for implementing maintenance windows and redirects without having to use a php or similar script is to check date and time in .htaccess files or use it to build a redirect url.

Date and time values in .htaccess come in the form %{TIME_XXXX} where XXXX is the type of date or time you want.

So if you want to redirect a generic url to one which contains today’s date, you might use:

RewriteRule ^posts/today$ /posts/%{TIME_YEAR}-%{TIME_MON}-%{TIME_DAY}

That would result in /posts/today being redirected to something like /posts/2015-08-27

If you wanted redirect a page after a date (and time) is passed you could use something like the following, where if the date and time is passed 9am on 27th August 2015 the redirect will happen. We use a simple number comparison of turning the date into an integer and then comparing it.

RewriteCond %{TIME_YEAR}%{TIME_MON}%{TIME_DAY}%{TIME_HOUR} >2015082709
RewriteRule ^$ /destination/url.html [R=301,L]

The following would only redirect until a specific time (10.22am on 27th August 2015)

RewriteCond %{TIME_YEAR}%{TIME_MON}%{TIME_DAY}%{TIME_HOUR}%{TIME_MIN} <201508271022
RewriteRule ^$ /destination/url.html [R=301,L]

The following would only redirect between two specific dates (20th July 2015 and 27th August 2015)

RewriteCond %{TIME_YEAR}%{TIME_MON}%{TIME_DAY} <20150828
RewriteCond %{TIME_YEAR}%{TIME_MON}%{TIME_DAY} >20150719
RewriteRule ^$ /destination/url.html [R=301,L]

The options you have for %{TIME_XXXX} values are:

TIME_YEAR // current four-digit year
TIME_MON // current month
TIME_DAY // current day of month
TIME_HOUR // current hour (24 hour clock) of day
TIME_MIN // current minute of hour
TIME_SEC // current second of minute
TIME_WDAY // current week-day
TIME // a formatted string representing the date and time down to seconds. e.g. 20150827112234

MySQL roughly random string generation for updating rows

Ever wanted to inject hashes into existing rows of a MySQL database? The code below allows you to generate a different string for each row affected by the update and choose the random string’s length from 1 to 32 character.

I’m aware it’s not the most random of generators but for url hashes etc, it works well. Be sure to then check for duplicates, which are possible!

Change 20 to a length between 1 and 32.

Update the WHERE condition to suit your needs


UPDATE table_name
SET column_name = (
SELECT substring(MD5(RAND()), -20)
)
WHERE condition_column = 1;

Chrome browser masking PHP errors

I thought I was going mad for a while, but it turns out that sometimes spotting php error messages which come back from the server to the Google Chrome browser can be really tough.

If the error is inside an html element or attribute of an html element you’re going to struggle to see it in Google Chrome…

<a href="<?= $Model->fakeFunction(); ?>">link</a>

If $Model doesn’t have a method called fakeFunction then php will spit a “Fatal error: Call to a member function” error. The page that is displayed in Chrome won’t show you the error and viewing the source will also hide it from you.

Even the elements tab in Chrome Developer Tools won’t show it.

There only way I’ve been able to find the error content is to look at the network tab in Chrome and view the raw response of the document back from the server.

A few hours lost on this one!