Developer & Human. Finding my voice.

Author: elstamey Page 2 of 3

I am a Business and Technology Application Analyst in North Carolina. I am currently using PHP and learning some Laravel and Domain Driven Design practices. I have also recently used Ruby on Rails to develop applications.

Outside of work, I enjoy art, music, and spending time with family and friends. I am co-organizer of the TrianglePHP meetup group and have been attending conferences like PHP Tek, PHP World, All Things Open, and Laracon US to improve my skills and understanding of best practices in web development.

Speaking at Peers Conference

In April, I presented for the first time at Peers Conference.  ‘Pulling Up Your Legacy App By Its Bootstraps!’ was my talk title.  I was super excited and honored and humbled by the experience.  It was a very different conference in the best possible ways!  Even now, I don’t think I have unpacked the many ways the experience has changed me.  I’m going to try to share them here.


I had never been to Peers Conference before.  I submitted because several speakers whom I admire recommended the conference, and I finally had an abstract I felt good about submitting.  I had tried to figure out how to share the useful pieces of this legacy project that had dominated my work life.  But the project was HUGE and difficult to put into pieces.

Getting Accepted

Peers selects talks using a blind approval process.  I did not pay attention to this before submitting because I was new and using a shotgun submission approach to becoming a Conference Speaker.  What I mean is that I felt my odds were pretty low and didn’t expect to win this opportunity.  But I did!  Peers featured almost 50% women speaking in its sessions.  The Developer track was dominated by women (75%)!  The lone male speaker on the Dev track was Matt Stauffer (but this isn’t about him).  It’s about me.  😛

I found out I was chosen, not by a form email but a phone call.  We talked about the conference, its community, and about the abstract I had submitted about bootstrapping.  I received advice for how my talk would be most helpful to the community I would be meeting.  It was wonderful and helpful as a new speaker to get this advice and support!

Preparing the Talk

I was offered so much support for preparing this talk!  I organized my first draft and gave it as a google hangout to speakers I admire (Elizabeth Naramore and Beth Tucker Long), and they gave wonderful advice.  I presented again to my supportive user group TrianglePHP.  They asked so many questions throughout my talk, which helped guide me toward the interesting parts and highlighted areas I could explain better.  This was a couple of months before the conference.

I consolidated a lot of those questions and added more code samples into the presentation.  A week before Peers, I organized a small group of developers at work to come listen.  I was really selective of who I picked because I wanted them to know me and to be comfortable giving me helpful feedback.  Unfortunately, I had a really hard time with the order of my slides.  I was saying things ahead of the slides and skipping over some details.  It was really frustrating because my talk ended early, and I had a bit of work to fill in gaps.  Luckily, these people were patient and kind.  They gave me some great advice for some structure to my talk and feedback for filling out the talk. Mitch Amiano and Dustin Wheeler, my teammates on the project, were so helpful, too.  They gave great advice for details I could explain better and corrected some technical details.

I continued revising my slides for the entire week, refining the flow and improving my speaker notes, hoping to keep myself on the current slide’s content!  And I camped in the hotel room on Tuesday, feeling unsure and making my notes cleaner and easier to read.  I was so relieved to only have one talk to give because I couldn’t imagine preparing two.  But I did finally have my talk ready on Wednesday morning and practiced it several times after.


Thursday, my presentation was after the keynote.  It was one I was excited to see, Gregg Pollack from Code School (a learning site with interactive tutorials).  He shared so many great experiences of his team’s growing and how they were able to put their team needs first and grow together.  I wasn’t sure if I would be too nervous to watch his talk, but my nerves weren’t too bad, and I enjoyed his presentation.

I had about 30 minutes before my own talk, so there was plenty of time to get settled!  The A/V guy was super helpful and adjusted the lights to keep them out of my eyes.  He got me set up on the podium and microphone.  I was a bit nervous, but not terribly so.  It was just enough that I felt like I needed the podium and to stay close to my notes.  I chose the fixed microphone, which I later regretted because as I felt more comfortable, I couldn’t move away from the podium.  Also, the microphone drooped a bit, and I was shrinking to stay in range.

As far as I could tell, the talk went well!  I had a pretty attentive audience, and they asked great questions at the end.  Some of them were consistent with what I’d been asked before.  I was glad to have the code samples to use to explain in more detail.

I felt GREAT after giving the presentation!!!  It wasn’t like feeling relief after a test or something I dreaded.  I felt accomplished!  I felt like I had something neat to share and people appreciated it.  I felt like I had contributed something to the conference community I had joined!  I immediately knew I wanted to do it again.

Achievement Unlocked!

Speaking at Peers was incredible!  I met people who were encouraging and supportive who made me feel so welcome.  I never once felt like I needed to spout a list of my tech trivia to prove I belonged there or linger on the outside of a group.  I attended knowing only 2 people that I knew would be there.  I re-met two people, one from [php]tek 2014, and another from our old Laravel group back home! I made so many other new (old) friends while there.  It was an amazing experience!

I’ll be getting the opportunity to speak again soon at Open Source Bridge in June!  And I had the pleasure of speaking to DaytonPHP over Google Hangouts.  I’m feeling pretty great about it!  I’m so grateful for the chances to share this legacy project and the lessons we learned.  I’m enjoying the brief breaks from work to revel in an accomplishment.  I’m exploring new ideas and things I want to teach and share.  It’s awesome!  I can’t wait to do it again!

Ego and Fear: Things I learned from Alison Levine on Inflection Point Radio

I’ve been working on this post for a little while, shortly after I listened to the episode.  It seemed fitting to share on International Women’s Day.  

Inflection Point Radio is quickly becoming one of my favorite podcasts.  Host, Lauren Schiller invites guest from all over, “women who are changing the status quo”.  As she is celebrating the one year anniversary of her podcast, I wanted to share an episode that truly meant a lot to me.

An explorer who has summited the 7 highest peaks in the world, Alison Levine, was the guest on this episode.  Alison was Captain of the First American Women’s Everest Expedition.  I loved hearing her stories, but most of what resonated for me was her talk about Ego and Fear.  I had pretty strong opinions of both as being bad characteristics, but I learned a different perspective from what she shared.

Ego.  I always associated this with arrogant people who felt they deserved to get what they wanted regardless of the effect on others.  But Alison said that she had learned from Coach K that there are many types of Ego.  He shared that ego is the trait he most looks for when he’s choosing players for the US Olympic Men’s Basketball team, but he is looking for a specific type of ego.  Coach K looks for the type of ego that doesn’t let self-doubt enter into things.  He looks for the type of ego that prevents a player from letting his teammates down. I had never seen this type of ego before.  I had only seen the show-boating representation of ego.  But it makes sense that these are all parts of ego, and that ego, like many other personality traits, involves balance.

Fear.  Fear was something I learned from an early age not to share or show.  I was a small kid and easy pickings, so most signs of weakness I pushed down deep and tried hard not to expose them.  As I found real friends in school and matured, this subsided quite a bit.  In college, as I entered Engineering and later Computer Science, I had to toughen up again.  Weakness was attacked on the Internet, even in the “good old days”, and I quickly learned to hide my gender and not to show vulnerability on the Internet.

What Alison shared was that there are two types of fear.  There is the type of fear that informs you of danger and the type of fear that prevents your even trying because something bad might happen.  Being able to distinguish between the two types of fear is invaluable.  You want to try new things, and you want to let yourself fail because that’s how you learn.  If fear keeps you from trying anything new, you won’t grow.

As an athlete and explorer, Alison Levine has certainly put herself in challenging and dangerous situations.  Her stories on Inflection Point Radio were so helpful to me.  I was able to see where in my career I have let fear keep me from trying new things and also where I have protected myself from dangerous situations.

I hope that by recognizing the differences, I will be more bold in the things I do.  I’d like to find that good ego that steels my determination to create something awesome and to stop the fear that makes it difficult to talk about programming on the Internet.  I doubt I’ll be joining reddit anytime soon, but I think this blog is a good first step.

If any of this sounds interesting, I hope you will listen to Inflection Point Radio.  I have learned so much on this podcast about awesome things that people are doing all over the world.  I’m always inspired by this podcast!  I want to be a bigger part of change in the world and helping people, and I feel like this show is helping me to find the right place to do that.

Are *YOU* Inclusive? Take this test and find out!

We’ve had lots of talk about inclusivity in our community. A group can only be as inclusive and welcoming as its members, right? We know the saying, “A rotten apple spoils the bunch”.  Bad apples affect the inclusivity of a community. You can’t control a rotten apple, but you can prevent it from spoiling you and those around you.

So ask yourself, “Am I inclusive?”

We all want to say yes, but how do we know for sure? I have an example to help you answer. Imagine a time when you were talking with three or more people at a conference. There are many other people at the conference. If someone walked near your group, did you make room for them? Did you open the circle and invite them into your discussion? Did you introduce them to the others? Did they instead linger in the outskirts or decide to walk past, playing it cool. When that happened, had you noticed them looking at your group?  Had you made eye contact with them?

This is something I see happen at conferences, and it is both a great test and something easy to fix. I find welcoming a person feels great! The conversation may be interrupted briefly, but you can quickly get back on track.

I have also made eye contact with a person who looked like they wanted to join a group I was in, and watched them walk away instead. I recognized the nervous feeling on the approach and the attempted nonchalance when they walked on to some other place. I’ve been that person, shy to approach a large group.  We probably all have.

It is hard to break into a circle of people together, to squeeze yourself in, not knowing if you’re welcome.  But when the circle opens up to you, there is no doubt you are welcome.  So now, how will you answer the question?

Are YOU inclusive?

Bootstrapping the CodeIgniter App, Part Two

Acceptance Testing

At the end of Part One, we were creating a lot of acceptance tests.  We had a pretty antiquated HTML form for the students to fill in a lot of data, some of which we didn’t need to collect from them.  We knew the templates would be changed and had a designer’s help making those look better and sensible.  We knew what data we needed to keep collecting in the application, so our Codeception tests checked that imaginary student’s application had the same information.  We planned knowing that the User Interface was changing and tried to ensure the data integrity.  Codeception tests are pretty brittle when you have to link to a specific DOM element, but we did the best we could to ensure that data wasn’t left off the Student’s Application for Scholarships.


As we began writing the new code, we needed to bind those namespaces to the CodeIgniter application, so the new code could be linked within the application.

We created /app/bindings.php


use ScholarshipsSelectionInfrastructureStorageHybridSourcedScholarshipRepository;

$container['ScholarshipsSelectionDomainScholarshipScholarshipRepository'] = function($c) {
    return new HybridSourcedScholarshipRepository(
); };

The bindings file is used for most of our new functionality in the /src path.  For example, the HybridSourcedScholarshipRepository builds all the current Scholarships with information from our database tables and our Events.  The constructor requires objects of type EventStore, Database, DepartmentsService, ResidenciesService, AcademicPlansService, and CollaborationsService.  We give the paths to these in the bindings for the container ScholarshipRepository.  The container can then be included in the Selection controller.

In /app/services.php, we included the bindings and facades:

 * Facade registration.
class_alias('ScholarshipsSupportFacadesRequest', 'Request');
class_alias('ScholarshipsSupportFacadesDB', 'DB');
class_alias('ScholarshipsSupportFacadesLog', 'Log');

// Bring in application-specific bindings require_once('bindings.php');

Then we created a new file called /src/CowboyBridge.php, which was used to initialize the Pimple Container.


namespace CodeceptionModule;

use CodeceptionModule;

class CowboyBridge extends Module
     * @var PimpleContainer
    private $container;

    public function _initialize()
        require_once(__DIR__ . '/../app/services.php');
        $this->container = $container;
        $this->debug("Loaded container.");

    public function getContainer()
        return $this->container;


Now we needed to be able to see the new code in our controllers.  This means, for example, ,being able to pass our collection of available Scholarships to the Selection controller, and from the controller into the views.  We named our new selection controller Selectionnext in order to leave the old Selection controller intact.

class Selectionnext extends BaseController
    public function Selectionnext()

        $this->scholarshipRepository = $this->container['ScholarshipsSelectionDomainScholarshipScholarshipRepository'];
protected function scholarshipsDashboard($scholarshipId)
    $committeeMember = $this->getCommitteeMember();

    $scholDetails = $this->getScholarshipDashboard($scholarshipId);

    $this->render('pages/scholarship-details.twig', array("scholarship" => $scholDetails)));

private function getScholarshipDashboard($scholarshipId,$keepItLight=false)
 $committeeMember = $this->getCommitteeMember();

 $presenter = new ScholarshipDashboardPresenter(

 $scholDetails = $presenter->asArrayForJson();
 $scholDetails['json_string'] = json_encode($scholDetails);

 return $scholDetails;

I have tried to remove some of the complexity of this part and hopefully not removed anything critical.  We compiled a lot more information into our $scholDetails and sent many more variables to our views.  But this should show a bit of how we mapped the information into the Controllers of CodeIgniter.


Lastly, we changed our views.  Leaving the old views in the /app/views directory as they were in CodeIgniter, we opted to use Twig views for our new interfaces, and we put those files in the /app/templates directory.    We set these paths in our app/config.php

return array( 
 'twig' => array(
   'template_path' => array(
     __DIR__ . '/templates',
     __DIR__ . '/templates/dashboard',


In the file app/services.php we pick up these configured paths and pull them into CodeIgniter.

$container['twig'] = function ($c) {
    $loader = new Twig_Loader_Filesystem($c['config']['twig']['template_path']);

    $inDevelopment = $_SERVER['APP_ENV'] === 'development';

    $twig = new Twig_Environment($loader, array('debug' => $inDevelopment));

    $app = $c['config']['app'];
    if ($inDevelopment) {
        $app['debug'] = TRUE;

    $twig->addGlobal('app', $app);
    $twig->addGlobal('notice', $c['config']['notice']);

    $twig->addFunction(new Twig_SimpleFunction('route', function($path) {
        return site_url($path);

    $twig->addFunction(new Twig_SimpleFunction('asset', function($path) {
        return base_url() . 'public/' . $path;

    $twig->addFunction( new Twig_SimpleFunction('flash_notice', function() {
        if (isset($_SESSION['flash_notice'])) {
            $_SESSION['old_flash_notice'] = $_SESSION['flash_notice'];

        return isset($_SESSION['old_flash_notice']) ? $_SESSION['old_flash_notice'] : array();

    if ($inDevelopment) {
        $twig->addExtension(new Twig_Extension_Debug());

    $twig->addFunction( new Twig_SimpleFunction('flash_exists', function() {
        return !empty($_SESSION['flash_notice']);

    return $twig;

The $_SERVER['APP_ENV'] variable was set in our .htaccess file.  This Twig configuration allows us to get debug information in our development environments.  We added two simple functions to build our asset path and our route path.  This meant we could use route() and asset() in our templates to correct paths across environments.  There are also simple functions to determine whether there are existing flash messages to pass into the template.


This code grew over a long period along with the new functionality of our application.  If you have questions about something that seems missing, please feel free to ask in comments.  I may be able to include a little more code to clarify the details.  Our Scholarships application is pretty complicated, and I’ve tried to skim a lot of that detail out of the code examples in order to simplify and focus on the bootstrapping.  I hope that it has been useful to you because it was really useful for me to re-examine how this all ended up working together.

Bootstrapping the CodeIgniter App, Part One

I have worked on this Scholarships project for about two and a half years.  It’s going to be replaced by another application, so I have reviewed how we did this and what I’ve learned in the process.  Modernizing a CodeIgniter Application – The Problems discusses the problems we were trying to solve (TLDR; we had a legacy CodeIgniter application with a giant App model full of functions making DB calls).  This post shares how we bootstrapped the CodeIgniter application to allow us to bring new code online without breaking the pre-existing application.  The reason we had to do this is also described in the previous post.

It’s important to me that I mention my coworker, Dustin Wheeler, figured out how to do most of this, and I have also learned a lot from Mitch Amiano during this project.  I am trying to document the ways that we modernized this Application to make sure that I am able to do it again.  Most of my development life has involved taking on existing applications, so this seems like a useful bit of information.

Screen Shot of Early Scholarships Working Tree

Screen Shot of Early Scholarships Working Tree

This is what the tree basically looked like at the beginning:

The directories /_data/app, /dinner, and /public already existed.  The bulk of the Application existed in the app directory.  Dinner was another little application on the side.

The first steps included creating a composer.json file that named the application, set the default namespace and mapped that to a new directory called /src.

The initial composer.json configuration file.

Initial composer.json file




Next we installed Phinx for database migrations and PHPUnit and Codeception for tests.  After the bootstrapping process, we used Codeception acceptance tests to verify that the data displayed on the Student Application stayed the same when we built entirely new views and changed the workflow around how the students applied for Scholarships.


In index.php, we turned on error_reporting and required the composer autoloader.

If no file_exists vendor/autoload.php, throw an exception. Otherwise require vendor/autoload.php

Adding composer autoloader to index.php

Next we had a few fixes to CodeIgniter bugs.  We removed a call to set_magic_quotes_runtime() in the file /_data/system/codeigniter/CodeIgniter.php.  In another file /_data/system/codeigniter/Common.php we removed the & from the following statement: $objects[$class] =& new $name();

We built two .sql files for the two databases used by our application.  In these files we saved the create schemas for each of the databases from Production. These files were later populated with anonymized test data, since we couldn’t use anything personally identifiable about our students or faculty.  We kept most of the scholarship data the same, so we could test against real scholarship matching criteria, but we anonymized the contact info in those as well.

We created a debug controller that later went away.  I’ll come back to note its purpose.  I believe it was to test new code from /src being pulled in.

The database configuration had persistent connections turned on, and we set them false:

$db['default']['pconnect'] = false;

$db['default']['db_debug'] = false;

$db['default']['cache_on'] = false;

A base database configuration script became pretty useful for three developers.  It began as a deploy script, but later evolved into a fully incorporated configuration file.  In the same file as above, the /app/config/database.php, we anonymized the hostname, username, password, and database to things like DB_HOST,  DB_USERNAME, DB_PASSWORD,  and DB_NAME.  The deploy script let us set these to something real in our development environment.  I have pasted the bulk of that script, but this script will only configure one database.  It seemed more readable and shorter this way.


# Start Application Configuration
if [[-f app/config/config.php ]]
        echo "Existing Application Config:"
        GREP "APP_" app.config.config.php


echo "Configure Application Config (1/1):"
read -p "Application Base URL ($APP_BASE_URL): " base_url
read -p "Application Index Page ($APP_INDEX_PAGE): " app_index_page


sed "
" app/config/config.default.php > app/config/config.php

echo "Rewrote app/config/config.php"

# Start Database Configuration

if [[ -f app/config/database.php ]]
    echo "Existing Config:"
    grep "$db" app/config/database.php

# Default Configuration Values

echo "Configuring Scholarship Database (1/2):"
read -p "DB Username ($DB_USERNAME):" username
read -p "DB Password ($DB_PASSWORD):" password
read -p "DB HOST ($DB_HOST):" dbhost
read -p "DB Name ($DB_NAME):" dbname


sed "

" app/config/database.default.php > app/config/database.php

echo "Rewrote app/config/database.php"
sed -i "
" app/config/config.php

echo "Updated app/config/config.php because stupid junk."

# Import base schemas for databases.
# Should kick of migrations in future.

# Import schema for default database.
mysql -u ${DB_USERNAME} -p${DB_PASSWORD} -h ${DB_HOST} < database/seeds/default.sql

Modifying CodeIgniter to Allow Testing

In the file /_data/system/libraries/Loader.php, we removed the line from function CI_Loader():

global $OUT;

with the following line:

$OUT =& load_class('Output');

In the file /app/config/config.php we set $config[‘enable_hooks’] to TRUE.

In the file /app/config/hooks.php we added this hook:

$hook['display_override'] = array(
    'class' => 'DisplayHook',
    'function' => 'captureOutput',
    'filename' => 'DisplayHook.php',
    'filepath' => 'hooks'

I’m pretty sure that hook is for Codeception to capture output using PhantomJS.  At this point, we began with a new Codeception test suite for the Student Application.  This part of our Application was mostly changing visually.  When a student completed their application and submitted the information, we created a StudentSubmittedApplication event instead of saving an entire set of data in a database row, as the previous application was working.  But this is getting a little ahead of the game.  We’re bootstrapping here.

In the file /app/hooks/DisplayHook.php, we told it to get the APP_ENV variable

// application/hooks/DisplayHook.php
class DisplayHook {
    public function captureOutput() {
        $this->CI =& get_instance();

        $output = $this->CI->output->get_output();

        if (getenv('APP_ENV') != 'testing') {
            echo $output;

            if(getenv('APP_ENV') != 'production') {
                if ($this->requestIsNotAjax()) {
                    echo sprintf(
                        '<img id="debug-overlay" src="%spublic/images/debug-overlay.png" /><style>#debug-overlay { position:fixed; top:0; left:0; z-index:-1; width:900px; opacity:0.25; }</style>',

    private function requestIsNotAjax()
        return  !(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == "XMLHttpRequest");

We set this value in a .htaccess file for Apache:

SetEnv APP_ENV development

At this point, we were writing a lot of tests because the existing application had none, and the student application was being redesigned.  There is a lot more to describe here, but I’ve got to parse through a lot of UI changes to find the useful bits.  I’m going post this as a Part One.  Part Two will include Pimple containers and bindings, controller actions to reach new code in /src, and other fun stuff.  Please feel free to post questions.  I would like to keep this as useful as possible.

So you want to be a programmer…

I recently heard this anecdote.  It’s sticking with me, so I’m sharing it!

So!  You want to become a programmer.  Well, here’s a list of languages for you to learn:

Ruby, NodeJS, ASP, PHP, Java, Python, AngularJS, …

Choose one of these as the language you know the best and build your career on.  Now, look at the remaining languages in the list and choose one.  From this point forward, this will be the language you hate.  You don’t need a reason to hate this language, but you can never be convinced to appreciate or use it.  Once in a while you will hear another person hate the same language as you.  They may have a reason, which you can add to your list of reasons for hate without needing to research the validity of that person’s reason.

Does this sound familiar?

Celebrating Accomplishments

Lately I’m thinking about my accomplishments this year in tech.  I feel much more a part of the greater development community than I ever have before.  I owe a lot of that to my Co-Organizing the TrianglePHP meetup group and my TA-ing with Girl Develop It.  I have also overcome some of my hesitation to contribute code in Open Source again.

Modernizing a CodeIgniter Application – The Problems

When I took my current job, I was assigned a specific project that supported the College’s distribution of Scholarship money to students.  This application had many errors and needed additional functionality.  Primarily, it needed to:

  1. handle students with more than one major
  2. reliably match students to Scholarship criteria
  3. allow the selection committee to give awards within in the application

This was a pretty tall order because the application was fairly large.  The bulk of functionality was within a single App model with functions that made SQL queries to the database.

Inspiring Kids with Technology

This week I had the pleasure of attending All Things Open, which is always a restorative, inspiring experience for me!  I love meeting the people, and my favorite thing of all is to learn how others are innovating with Open Source.  It is the main reason I use Open Source and a cause I heartily believe in.  I often wish that I was doing more good with my open source skills and All Things Open shows me ways that I can help!

My favorite talk last year was by Charlie Reisinger at Penn Manor talking about the Open Source classroom.  He told us about how they had open sourced their classrooms at the local hospital and given a Linux-powered laptop to every student.  Students and Faculty worked on the Linux environments that were necessary after consulting with teachers about what their needs might be and including those tools in the software package. Laptops backed up remotely to prevent data loss, and the students were given root level access to make changes as they saw fit.  In addition to all of this, students were the driving force of the help desk.  They supported fellow students and were free to learn and innovate.  This program was a huge source of pride and accomplishment for everyone involved!

Going from Procedural PHP to Modern PHP

I have spent a lot of time over the last few years trying to figure out what is the right way to transition from procedural PHP code to Modern PHP best practices.  It doesn’t seem like it should be the painful, gut-wrenching process as it was for me.  Now the question becomes stronger because I want to help others make that switch, and I don’t want the difficulties to be deal-breakers.  I want to remove the obstacles of prerequisite knowledge but planning things in the simplest order.  However, it seems like you have to know many things all at once to make the transition.  The simpler it is to learn, the more easily I can convince others to join me on this journey.  It makes it easier for their management to agree to it.  But how do I teach it?

Page 2 of 3

Powered by WordPress & Theme by Anders Norén