Category Archives: Laravel

Thoughts on Vagrant

I’ve been making a play to get current and stay current with today’s web dev technologies, trends, etc.

It’s not easy. Things are moving fast and I was a bit behind to begin with.

Some of the tools that developers on the cutting edge are pushing appear to be a little abstract relative to what I’m actually working on right now or to my current workflow. One of these tools is Vagrant. Don’t worry, I do get it. Dev environments should match Prod and Vagrant makes it much easier to accomplish. But as a single developer who doesn’t need new environments that often, do I really want to spend time learning about Vagrant, along with Chef and/or Puppet just to prop up the occasional new environment when my current OS X/MAMP Pro dev environment really hasn’t caused me any problems to date? (actually, I did have an issue with case-sensitivity and class names, but not a big deal.)

Again, my use-case is currently limited (single developer, very few new environments, content with MAMP). And I don’t really want to take the time right now to learn Chef or Puppet. But if I can make it super simple, and considering the prospect of developing an app and packaging it up with a Vagrantfile and including it in a repo – all ready to go (I haven’t really seen this, but it sounds cool), then maybe it’s worth looking into. Plus, I’ll have that peace of mind that my Dev and Prod environments are matched.

So I borrowed some code from a couple of different Vagrant/Laravel 4 Github repos and mashed together my own Vagrantfile/boostrap.sh that is very simple and doesn’t require Puppet or Chef to get something up and running that to run a Laravel app. In addition to installing a LAMP environment, it points the default Apache site to the public folder.

Your web app will be available at http::/localhost:8888 and you can access MySQL via an SSH tunnel using the “vagrant” user.

Posted on Github: https://github.com/rufhausen/super-simple-vagrant-laravel

My “fix” for preserving timestamps on import with Laravel

Edit: This will not work on “updated_at” btw, for reasons that become obvious very quickly, but for my application, this is not an issue.

I’m currently re-developing a Coldfusion app in Laravel 4. Most of the current db tables have “createdat” and “updatedat” fields. I went thru the trouble of creating migrations for all of the db tables and then writing an Artisan command called “Import” that connects to a copy of the old db and imports all of the data into the new db created with the migrations that includes a few schema changes that are crosswalked over.

One of the problems with this is that the timestamp fields (“created_at” and “updated_at”) created by Laravel during migrations will be current(as in “now”) even if I try to map the old timestamps on import:

//no workie
$videogroup->created_at = $vg->createdat;

As a result, I lose important timestamp info. from my old database.

My new fix involves running the import as before:

$videogroups = DB::connection('mysql_vm_old')->select('select * from videogroups');
foreach ($videogroups as $vg) {
$videogroup = new VideoGroup;
...
$videogroup->save();

Except that I add this to the loop:

$videogroup->createdat  = $vg->createdat;

Then after the initial table import is complete, run:

$videogroups = VideoGroup::all();

//replace default timestamp value with the one from the old db
foreach ($videogroups as $vg) {
$vg->created_at = $vg->createdat;
$vg->save();
}

//get rid of the temporary 'createdat' column
Schema::table('videogroups', function($table)
{
$table->dropColumn('createdat');
});

This certainly adds more overhead to my import script for larger tables, and I’ve already had to increase mysql’s memory limit to handle the script as it’s grown, but once the site goes into production, I’ll no longer need the Import script.

As it stands now, I’m running the following on a daily basis as I make changes:

php artisan migrate:refresh --seed
php artisan import

6 reasons not to use a PHP Framework

  1. You are immortal, and therefore, will always be around to help other developers understand and extend your code.
  2. You have no life, and therefore, don’t mind spending all of your free time writing code comments and documentation that would already be written in a good framework, so other developers after you (or with you) can also write code for your app(s).
  3. You are coding an app that will be one of the most visited sites on the web (all by your self and for eternity if #1 and #2 are true), and therefore, can justify the potential nanoseconds saved by not having the “overhead” of a framework.
  4. You are a web security god and are way smarter than the collective group of developers who code and test good frameworks for security issues.
  5. You want to spend all of your time re-inventing the wheel by writing your own RESTful routing implementation, ORM, templating engine, etc. etc. instead of what a good framework provides. Or maybe you skip the ORM part and just re-write larges parts of the app when you need to switch DB engines.
  6. You don’t do “deadlines”.

If these reasons don’t apply to you, I recommend checking out Laravel, or better yet, the Laravel 4 beta.

Updating related models in Laravel

Not sure how other frameworks handle this (if they do), but Laravel’s ability to simply update a related model is pretty nice.

 $video->videoevent()->update(array('event_date' => createDbDate(Input::get('event_date'))));

Assuming I have a relationship between Video and Videoevent have made ‘event_date’ available for mass assignment the Videoevent model, magic happens.

Laravel 4 Pagination with Column Sorting

It took a little effort, but I finally got Laravel 4′s pagination class working with the ability to sort by column. Posted here so I don’t forget.

//Controller

$widgets = Widget::all();
$sort = (!is_null(Input::get('sort')) ? Input::get('sort') : 'name'); 
//with 'name' being the default column to sort on.
$order = (!is_null(Input::get('order')) ? Input::get('order') : 'desc');
//'desc' is the default sort order.
$widgets = $widgets->orderBy($sort, $order);
$widgets = $widgets->paginate(20);

//include $order and $sort when retrieving your layout/view
$this->layout->nest('content', 'widgets.index',array('widgets' => $widgets, 'sort' => $sort, 'order' => $order));
//View

//Display the pagination
//I tried using appends() first, but could not chain multiples
{{ $events->addQuery('order',$order)->addQuery('sort', $sort)->links() }}

//Column header
{{link_to_route('widgets.index','Name', array('sort' => 'name'))}}
//Using Twitter Boostrap up/down arrows
<a href="{{route($route, array('sort' => $sort, 'order' => 'asc'))}}">
        <i class="icon-chevron-up"></i>
</a>
<a href="{{route($route, array('sort' => $sort, 'order' => 'desc'))}}">
        <i class="icon-chevron-down"></i>
</a>