Saturday, March 19, 2016

Swivel Extension for Yii

In my last post, I mentioned that I was looking forward to making a Swivel extension for Yii. I'm excited to share that I've FINALLY found the time to do so.

It's a fairly straight forward extension, simply providing access from the application to a Swivel component which interacts with the core Swivel library, and which handles the general bucket assignment for users as swivel is accessed. I've also provided a class for integrating the existing Swivel logger over to the primary Yii Logger, and provided a data structure and model for storing the list of features for the application.

The extension is available on the Yii Framework Extensions list, from the GitHub repository or as a composer package.

It's really designed to be installed via composer:
composer require "dhluther/yii-swivel":"~1"

I've tried to keep it lean, but provide a good bit of information about how to implement it and how the Swivel features work on the Yii-Swivel Wiki on GitHub.

I will be creating a 2.0 version shortly as well.

Enjoy! I hope others find it as useful as I think I am going to, and huge props to the Zumba team that developed it and to Stephen Young and his presentation at SunshinePHP 2016!

Sunday, February 7, 2016

SunshinePHP 2016 Conference

I had the opportunity this weekend to attend the SunshinePHP conference in Miami. What an amazing group of people who are passionate about what they do. The theme for the weekend centered on collaboration and supporting the open source community, something that is near and dear to the heart of many Yii developers. It was a wonderful thing to meet so many people from around the world who believe in supporting community. A special shout out to Josh Holmes and Michelangelo van Dam who were extremely outgoing, encouraging, and full of tidbits of wisdom which they were willing to share.

I wanted to take a few minutes and share some of my hot takeaways from the weekend.

  • Docker - If you don’t know what it is yet, you need to go check it out. Docker is "an open platform for distributed applications for developers and sysadmins." Docker enables you to quickly compartmentalize processes on your server, while leaving them with access to the same base OS. Through port forwarding, shared folders and other means (built in and easily configurable), you can enable those processes to communicate. This is useful when you want to test a single application installation against multiple versions of PHP or multiple versions of MySQL. It’s also useful when you are trying to standardize a development platform or delivery system. In fact, there are so many potential uses for this technology in streamlining and standardization that I can’t even begin to recount them all. Long story short - if you haven’t looked at it yet, do so. If it still doesn’t make sense after reading about it, ask ;)
  • Swivel - Ok, this is pretty cool - the guys over at Zumba fitness have come up with a slick library for strategy driven, segmented feature toggles. These allow you to release new features in Canary Releases, perform A/B testing, and implement the features in a way that keeps the traditional feature flag system’s potential complexity from overloading your codebase and leading to a lot of technical debt. Swivel is currently limited to a 10 cohort (or buckets as they call it) system, which you evenly split your users into, giving you 10% user base segments for whatever feature you’re going to test or release. They currently have a CakePHP plugin for it, and I’m looking forward to working on a Yii extension for it.
  • Team City - Who knew?? JetBrains has a CI product. I guess I’ve kept the blinders on PHPStorm for so long (which I love and don’t know how I lived without), that I missed the news on this one. I haven’t looked into the details yet, but the PHPStorm developers that were at the conference said they couldn’t make PHPStorm without it, and that’s enough of a recommendation for me!
There’s so much more, I could go on for hours about Graph Databases and RUM, Performance Monitoring and PHP Pipelines, just to name a few. If it’s been awhile since you’ve been to a conference, I highly recommend that you go. Find a conference or a user group nearby, or take a leap of faith and visit one that changes not just your routine, but your whole perspective ;)

Thursday, December 10, 2015

Testing in Yii 2.0 with Codeception - Fixture Data

I'll admit it -- I'm a phpunit addict. Switching to codeception has been a bit of a struggle for me, just because it feels like it should be intuitive, but it's different enough from what I'm used to that it's taken me a few days to really wrap my head around it. My biggest struggle? Trying to get fixture data to automatically load and unload when functional and acceptance tests are run. I finally dug through the yii2-app-advanced code and discovered the FixtureHelper!! The FixtureHelper is the missing link in getting your fixture data to automagically load and unload when the functional and acceptance tests are run.

Friday, December 4, 2015

Flash Messages and Redirects in Yii2

Using Flash messages in Yii 1.1.* is something that I have done for so long, and so commonly, that I take it completely for granted. Whenever a user performs some action and the processing generates some information I want to convey back, I plug that information into a success, warning, info or error flash message, pop in a redirect for that situation and VOILA! After my processes are finished, the flash message is displayed to the user.

For example, in Yii 1.1.*, I have a handy action that is called if a user needs to retrieve their password from the database. It was written well back, around 1.0.6-ish, but still gets the job done nicely. Look up the user by the posted email, if the user is found, send the user an email and set a success message, otherwise, set an error message. Once that's done, redirect the user to the previous page. Otherwise, notify them that there was an error and keep going on.

When I converted this particular action to Yii2 it kept losing my flash messages. If I took out the redirect after successfully processing and sending the email, it was fine -- but I need the redirect to prevent inadvertent multiple form submissions etc. What to do?!? After scouring the internet and Yii forums, and finding multiple instances of people complaining about it not working but no good solutions or notes other than 'working as intended', I finally - FINALLY - realized that it is the redirect method itself that is, while stopping any output to the screen, not actually stopping the currently processed action. If I was more observant, I would have noticed it in the example of a controller redirect here:

Tuesday, November 11, 2014

Active Relations from Yii 1.1 to Yii 2.0

In Yii 1.1.x relations were defined by an array within the model class. In Yii 2.0 that is no longer the case. Relations are now defined by getter methods within the model. For the complete specification see Working with Relational Data in the Yii 2.0 Guide.

Saturday, April 19, 2014

Making the switch from Yii 1.1 to Yii 2.0 - Part 2: Getting Started

Probably my biggest hurdle in getting started with Yii 2.0 (aside from getting my hosting company to upgrade my server from PHP5.2 to 5.4) has been understanding the changes to the application structure and the vast difference between the basic application and the advanced application. Since my personal site runs on a subdomain, this greatly complicated the issue for me. I needed something more than the basic application, but the advanced application was way too much overkill. I finally went with the advanced application, but now that I understand how the composer works to distribute the skeleton files, I'm looking forward to creating something that's between the two.

There is way too much to cover in a single blog, so this is just a look at the basic structure and front end changes that you need to know to get up and running in 2.0.

If you're past all of this and looking to dive into the nitty-gritty detail changes, I suggest you read the official documentation on upgrading.

Tuesday, March 11, 2014

Setting the CDbConnection for Active Records within a Yii Migration

I use migrations whenever possible within Yii applications to help ensure consistency between implementation. I have multiple development environments, a staging environment and a production environment. I really don't want to have to manually issue a lot of sql queries or yii commands if I don't have to. Migrations make that possible and can be integrated automatically in the build process for deployment.

Occasionally, I need to convert some old data into a new structure, and I can do this via the migrations as well!

Create a basic migration to translate data:

For example, to query a set of data from an old table, and create a new set of records from it (that may have additional logical processes added beforeSave etc.) I could start off by doing the following in my migration:

public function up()
  // Query for the existing record data
  $results = Yii::app()->db->createCommand()

  // Ensure that if we fail, we start with a fresh slate
  try {
    foreach( $results as $row )
       $m = new NewModel();
       // assign attributes from $row[] that should be
       // mapped to the new model applying any new
       // logical manipulations required
       if (!$m->save())
         throw new Exception(
            CVarDumper::dumpAsString( $m->errors )
  } catch ( Exception $e )
     echo $e->getMessage(), PHP_EOL;
     // indicate migration failure
     return false;

  // acknowledge success
  return true;

If you only have one db connection in your application, this will work fine. But, if you also have a test database that you need to migrate, it will quickly fail due to duplicate primary keys, or write double the data in your primary database, rather than your test database.

Update the migration to handle alternate connection components:

To update the migration to work with a different connection, we simply need to add a few lines that specify which connection to use, as follows:

public function up()
  // Query for the existing record data 
  // Use migration's db connection rather than Yii::app()->db
  $results = $this->getDbConnection()->createCommand()

  // Set the static connection property for active records to the migration's 
  // connnection
  CActiveRecord::$db = $this->getDbConnection();
  try {
  //  ... the rest remains the same

Now, I can run my migration on the alternate connection with no problems, and no pulling of hair!

./yiic migrate --connectionID=db_test

On the Yii2 front, I was side tracked by the fact that I can't find an equivalent to the CViewAction (which I use extensively), and so much of the main layout involves new widgets in static method form, but I will get back to it soon!