Saltar al contenido principal
Laravel and Django and 
Rails, Oh My! 
Become a web artisan with the Laravel PHP framework 
Chris Roberts @thechrisroberts Caddis Interactive 
1
Chris Roberts @thechrisroberts Caddis Interactive 2
Compare Apples to Apples 
Which of these is your favorite Doctor? 
Chris Roberts @thechrisroberts Caddis Interactive 
3
Apples to Apples 
Chris Roberts @thechrisroberts Caddis Interactive 
4
Choosing Your Environment 
In some ways, it doesn’t matter 
• Pick what fits you and learn it inside and out. 
• Always be ready to try new things. 
• Find the right tool for the job. 
Chris Roberts @thechrisroberts Caddis Interactive 
5
Choosing Your Environment 
When it matters 
• What does your server environment support? 
• Will your chosen framework scale up when your work goes viral? 
• Are your developers familiar with the tools? 
• How is the community support? 
• Does it have the third-party utilities you need? 
Chris Roberts @thechrisroberts Caddis Interactive 
6
Language Overview 
Looking at the details: Language Syntax 
• Ruby is generally considered more human-readable 
• Python is more script-like and white space significant 
• PHP uses a C-style syntax 
Chris Roberts @thechrisroberts Caddis Interactive 
7
Language Overview 
Looking at the details: Language Syntax 
• Each language supports closures 
• Ruby: blocks, procs, and lambdas 
• Python and PHP: nested functions 
• PHP closures introduced in PHP 5.3 
Chris Roberts @thechrisroberts Caddis Interactive 
8
Language Overview 
Looking at the details: Object Oriented 
• Each language supports OO code. 
• PHP is not what it used to be. 
• Namespaces, inheritance, autoloading 
• PSR standards 
Chris Roberts @thechrisroberts Caddis Interactive 
9
Unit Testing 
Find your bugs before your users find them 
• Each framework has options for unit testing 
• Django uses Python’s unittest 
• Rails has unit testing baked in 
• Laravel has out-of-the-box support for PHPUnit with the ability to 
run assertions on your routes 
Chris Roberts @thechrisroberts Caddis Interactive 
10
Language Overview 
Looking at the details: Third-party Packages 
• Ruby: gem packages 
• Python: pip (official support in Python 3.4) 
• PHP: composer 
Chris Roberts @thechrisroberts Caddis Interactive 
11
Language Overview 
Who uses it 
• Ruby: Github (Rails and Erlang), original Twitter 
• Python: Disqus, Instagram 
• PHP: Wikipedia, many CMS’s, Facebook uses their own variant 
Chris Roberts @thechrisroberts Caddis Interactive 
12
Framework Overview 
Rails, Django, and Laravel 
• Numerous frameworks per language 
• Rails and Django are the most popular for their languages 
• PHP has many contenders: Yii, Zend, CakePHP, CodeIgniter, 
Symfony, Aura, Slim, Silex, numerous others. 
• Pick the one that fits your project 
Chris Roberts @thechrisroberts Caddis Interactive 
13
Laravel for PHP 
The PHP Framework for Web Artisans 
• Follows PSR-0/PSR-4 for namespacing and autoloading 
• Flexible configuration system with multiple environment support 
• Powerful ORM tied to a comprehensive query builder 
• Highly extensible through service providers 
• MVC design pattern in Laravel 4 
• Excellent documentation 
Chris Roberts @thechrisroberts Caddis Interactive 
14
DWRM 
(Doctor Who Relationship Management) 
Chris Roberts @thechrisroberts Caddis Interactive 
15
Getting up and running 
Chris Roberts @thechrisroberts Caddis Interactive 
16
Pieces for a DWRM 
Setting things up 
• Models: doctors, companions, enemies, episodes 
• Also prepare for users, comments, and ratings 
• Need pivot tables to track relationships 
• Set up migrations to easily create and update our data structure 
• Add seed data for testing 
Chris Roberts @thechrisroberts Caddis Interactive 
17
Migrations 
Building out your database in code 
• Laravel Migrations: versionable table schemas. 
• Puts your schema inside source control 
• Easily built out with Laravel’s command line utility: artisan 
Chris Roberts @thechrisroberts Caddis Interactive 
18
Laravel Artisan 
This command line tool provides numerous helpers from 
generating classes to running migrations to seeding data. 
Chris Roberts @thechrisroberts Caddis Interactive 
19
use IlluminateDatabaseSchemaBlueprint; 
use IlluminateDatabaseMigrationsMigration; 
class CreateDoctorsTable extends Migration { 
public function up() 
{ 
Schema::create('doctors', function($table) { 
$table->increments('id') 
->integer('number') 
->string('image') 
->text('description') 
->timestamps(); 
}); 
} 
public function down() 
{ 
Schema::drop('doctors'); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
20
use IlluminateDatabaseSchemaBlueprint; 
use IlluminateDatabaseMigrationsMigration; 
class ModifyDoctorsTable extends Migration { 
public function up() 
{ 
Schema::table('doctors', function($table) { 
$table->string('name'); 
}); 
} 
public function down() 
{ 
Schema::table('doctors', function($table) { 
$table->dropColumn('name'); 
}); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
21
Run the Migration 
Chris Roberts @thechrisroberts Caddis Interactive 
22
Rails Migration 
Rails provides a similar mechanism for setting up your data 
structure 
class CreateDoctors < ActiveRecord::Migration 
def change 
create_table :doctors do |t| 
t.integer :number 
t.string :name 
t.string :image 
t.text :description 
t.timestamps 
end 
end 
end 
Chris Roberts @thechrisroberts Caddis Interactive 
23
Django Migration 
Django also provides migrations, though they work a bit 
differently than Rails or Laravel 
• Changes are made on the model class file 
• Migrations are automatically generated based on model changes 
Chris Roberts @thechrisroberts Caddis Interactive 
24
Loading test data 
Laravel data seeding makes it easy to bootstrap your website 
or load data for testing. 
• Laravel seeding makes use of its ORM methods to easily create 
and store model data. 
• The query builder can also be used to manipulate data directly. 
• DB seeds are run using Artisan. 
Chris Roberts @thechrisroberts Caddis Interactive 
25
class DoctorTableSeeder extends Seeder { 
public function run() 
{ 
Doctor::delete(); 
Doctor::create(array('name' => 'Christopher Eccleston', 
'number' => '9', 
'description' => '...', 
'image' => '...' )); 
Doctor::create(array('name' => 'David Tennant', 
'number' => '10', 
'description' => '...', 
'image' => '...' )); 
Doctor::create(array('name' => 'Matt Smith', 
'number' => '11', 
'description' => '...', 
'image' => '...' )); 
Doctor::create(array('name' => 'Peter Capaldi', 
'number' => '12', 
'description' => '...', 
'image' => '...' )); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
26
class CompanionTableSeeder extends Seeder { 
public function run() 
{ 
Companion::delete(); 
$doctorNine = Doctor::where('number', 9)->first(); 
$doctorTen = Doctor::where('number', 10)->first(); 
Companion::create(array(‘name' => 'Rose Tyler', 
'description' => '...', 
'image' => '...' 
)) 
->doctors() 
->attach(array($doctorNine->id, $doctorTen->id)); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
27
Running php artisan db:seed 
Chris Roberts @thechrisroberts Caddis Interactive 
28
Django and Rails 
Other ways to do the same 
• Similar in Rails 
Doctor.create(name: "David Tennant", number: 10, description: "...") 
• Different in Django 
• Can import from structured data (XML, JSON, etc) 
• Primarily imported via data migration 
Chris Roberts @thechrisroberts Caddis Interactive 
29
Data Model 
Writing code that represents “things” 
• Class that provides additional abstraction between you and data 
• A model represents an object in the database 
• The framework provides ways to manipulate those models 
• Laravel, Rails, and Django each follow the Active Record pattern 
Chris Roberts @thechrisroberts Caddis Interactive 
30
Model relationships 
Connecting related pieces 
• Laravel’s ORM (called Eloquent) makes it easy to connect related 
models. 
• In our demo, each doctor has a companion, each episode a 
doctor, companion, and enemy, etc. 
• We also have comments and ratings that can attach to any of 
these. 
Chris Roberts @thechrisroberts Caddis Interactive 
31
Modeling the Doctor 
class Doctor extends Eloquent { 
public function companions() 
{ 
return $this->belongsToMany('Companion'); 
} 
public function enemies() 
{ 
return $this->belongsToMany('Enemy'); 
} 
public function episodes() 
{ 
return $this->belongsToMany('Episode'); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
32
Modeling the Companion 
class Companion extends Eloquent { 
public function doctors() 
{ 
return $this->belongsToMany('Doctor'); 
} 
public function episodes() 
{ 
return $this->belongsToMany('Episode'); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
33
Relationships 
There are many ways 
models might relate to 
each other. Laravel 
provides methods for 
interacting with each 
option. This includes 
nested relations, ie, 
accessing a grandparent 
model through a child. 
• one-to-one 
• hasOne(…) 
• belongsTo(…) 
• one-to-many 
• hasMany(…) 
• belongsTo(…) 
• many-to-many 
• belongsToMany(…) 
Chris Roberts @thechrisroberts Caddis Interactive 
34
Stepping back 
Reviewing the state of our application 
• Our tables are defined and created 
• We’ve loaded seed data 
• We have pieced together our models and their relations 
• Time to get something on screen 
• First step: connecting the URL to our code 
Chris Roberts @thechrisroberts Caddis Interactive 
35
Laravel Routing 
Provides a powerful interface to direct users based on their 
url path and depending on your defined filters 
• Routing is finding out where a user once to go and directing 
them to the appropriate place in your code. 
• Laravel provides several ways to define your application routes. 
• It also provides filters to allow you to lock routes based on 
certain situations, ie, keep guests away from routes requiring 
authentication. 
Chris Roberts @thechrisroberts Caddis Interactive 
36
Routing the Doctor 
Route::get('/', 'IndexController@index'); 
Route::get('/doctors', 'DoctorController@index'); 
Route::get('/companions', 'CompanionController@index'); 
Route::get('/enemies', 'EnemyController@index'); 
Route::get('/episodes', 'EpisodeController@index'); 
Route::get('/doctor/{id}', 'DoctorController@get'); 
Route::get('/companion/{id}', 'CompanionController@get'); 
Route::get('/enemy/{id}', 'EnemyController@get'); 
Route::get('/episode/{season}/{show}', 'EpisodeController@get'); 
Route::post('/comment', 'CommentController@post'); 
Chris Roberts @thechrisroberts Caddis Interactive 
37
Django Routing 
• Django handles routes via a URL dispatcher which matches 
routs through regular expressions. 
• Does not match against GET, POST, etc. 
from django.conf.urls import patterns, url 
from . import views 
urlpatterns = patterns('', 
url(r'^doctors/$', views.list_doctors) 
url(r'^doctor/(d+)$', views.view_doctor) 
Chris Roberts @thechrisroberts Caddis Interactive 
) 
38
Rails Routing 
• Routes defined in application routes.db 
• Out of the box, no route filtering 
• Able to define specific routes to specific controller methods 
• Able to automatically route to controllers and methods 
Rails.application.routes.draw do 
root 'index#index' 
get 'doctors' => 'doctor#index' 
get 'doctor/:id' => 'doctor#get' 
resources :enemy 
end 
Chris Roberts @thechrisroberts Caddis Interactive 
39
Laravel Controllers 
Mediating between your model and view 
• Performs data validation 
• Interacts with necessary models 
• Generates views 
• Returns responses to the client or redirects to an alternate route 
Chris Roberts @thechrisroberts Caddis Interactive 
40
DoctorController.php 
class DoctorController extends BaseController { 
public function index() 
{ 
$doctors = Doctor::orderBy('number')->get(); 
return View::make('doctors', array(‘doctors' => $doctors)); 
} 
public function get($id) 
{ 
$doctor = Doctor::with(array(‘companions', ‘episodes'))->find($id); 
$ratings = RatingController::getRating('doctor', $id); 
$comments = Comment::where('item_id', $id) 
->where('item_type', 'doctor') 
->with('user') 
->orderBy('created_at', 'desc') 
->get(); 
return View::make('items.doctor', array( 'doctor' => $doctor, 
'ratings' => $ratings, 
'comments' => $comments )); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
41
Blade Tempting 
@extends('layouts.structure') 
@section('content') 
<h1>The Modern Doctor</h1> 
<div class="row doctor"> 
@foreach ($doctors as $doctor) 
<div class="item"> 
<a href="/doctor/{{ $doctor->id }}"> 
<img src="{{ $doctor->image }}"> 
<h3>{{ $doctor->name }}</h3> 
</a> 
</div> 
@endforeach 
</div> 
Chris Roberts @thechrisroberts Caddis Interactive 
@stop 
42
Blade Tempting 
<!DOCTYPE html> 
<html lang="en"> 
<head> 
<meta charset="utf-8"> 
<title> 
@if (isset($title)) {{ $title }} | @endif 
The Doctor 
</title> 
<link rel="stylesheet" href="/assets/css/style.css"> 
</head> 
<body> 
<header class="container"> 
<h1 class="site"><a href="/">The Island of Doctor Who</a></h1> 
</header> 
<div class="container"> 
@yield('content') 
</div> 
</body> 
<script src="/assets/js/script.min.js"></script> 
Chris Roberts @thechrisroberts Caddis Interactive 
</html> 
43
Blade Tempting 
@extends('layouts.structure') 
@section('content') 
<h1>The Modern Doctor</h1> 
<div class="row doctor"> 
@foreach ($doctors as $doctor) 
<div class="item"> 
<a href="/doctor/{{ $doctor->id }}"> 
<img src="{{ $doctor->image }}"> 
<h3>{{ $doctor->name }}</h3> 
</a> 
</div> 
@endforeach 
</div> 
Chris Roberts @thechrisroberts Caddis Interactive 
@stop 
44
Chris Roberts Caddis Interactive 45
Chris Roberts Caddis Interactive 46
Chris Roberts Caddis Interactive 47
Retrieving individual models 
Laravel makes it easy to retrieve a model, any related data, 
and pass it to a view for presentation. 
public function get($id) 
{ 
$doctor = Doctor::with(array(‘companions', ‘episodes’))->find($id); 
$ratings = Rating::getRating('doctor', $id); 
$comments = Comment::where('item_id', $id) 
->where('item_type', 'doctor') 
->with('user') 
->orderBy('created_at', 'desc') 
->get(); 
return View::make('items.doctor', array('doctor' => $doctor, 
'ratings' => $ratings, 
'comments' => $comments )); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
48
@extends('layouts.structure') 
@section('content') 
<h1 class="title">{{ $doctor['name'] }}</h1> 
<div class="hero"> 
<img src="{{ $doctor['image'] }}"> 
</div> 
<div class="rating"> 
Rated {{ $ratings['rating'] }} out of 5 with 
{{ $ratings['numRatings'] }} votes 
</div> 
<p class="description"> 
{{ $doctor['description'] }} 
</p> 
Chris Roberts @thechrisroberts Caddis Interactive 
49
<h2>Companions</h2> 
<div class="row companion"> 
@foreach ($doctor['companions'] as $companion) 
<div class="item"> 
<a href="/companion/{{ $companion->id }}"> 
<img src="{{ $companion->image }}"> 
<h3>{{ $companion->name }}</h3> 
</a> 
</div> 
@endforeach 
</div> 
<h2>Episodes</h2> 
<div class="row episode"> 
@foreach ($doctor['episodes'] as $episode) 
<div class="item"> 
<a href="/episode/{{ $episode->season }}/{{ $episode- 
>episode }}"> 
<img src="{{ $episode->image }}"> 
<h3>Season {{ $episode->season }} episode {{ $episode- 
>episode }}</h3> 
<h3>{{ $episode->name }}</h3> 
</a> 
</div> 
@endforeach 
</div> 
@include('layouts.comment', array('type' => 'doctor', 'id' => $doctor['id'], 
'comments' => $comments)) 
@stop 
Chris Roberts @thechrisroberts Caddis Interactive 
50
<a name="comments"></a><h1>Comments</h1> 
@if($errors->has()) 
Display errors 
@endif 
<h2>Add Comment</h2> 
{{ Form::open(array('url' => '/comment/')) }} 
{{ Form::hidden('type', $type) }} 
{{ Form::hidden('id', $id) }} 
{{ Form::label('title', 'Comment title'); }} {{ Form::text('title'); }} 
{{ Form::label('email', 'Email address'); }} {{ Form::text('email'); }} 
{{ Form::label('content', 'Comment text'); }} 
{{ Form::textarea('content'); }} 
{{ Form::submit('Submit'); }} 
{{ Form::close() }} 
@if ($comments && sizeof($comments) > 0) 
@foreach ($comments as $comment) 
<div class="comment"> 
<h3>{{{ $comment['title'] }}}</h3> 
<div class="meta">Comment by {{ $comment['user']['name'] }} at 
{{ date('m-d-Y H:i:s', strtotime($comment['created_at'])) }}</div> 
<p> 
{{{ $comment['content'] }}} 
</p> 
</div> 
@endforeach 
Chris Roberts @thechrisroberts Caddis Interactive 
@endif 
51
CSRF Protection 
Laravel comes with filters to help protect you and your users 
from CSRF attacks 
class BaseController extends Controller { 
public function __construct() 
{ 
$this->beforeFilter('csrf', array('on' => 'post')); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
} 
52
Validation 
Once user data is received, Laravel provides tools to simplify 
validation and storage. 
$validator = Validator::make( 
Input::all(), 
array( 
'type' => 'in:doctor,companion,enemy,episode', 
'title' => 'required|min:5', 
'email' => 'required|email', 
'content' => 'required', 
Chris Roberts @thechrisroberts Caddis Interactive 
)); 
53
When the test fails 
if ($validator->fails()) { 
return Redirect::to(URL::previous() . '#comments') 
->withErrors($validator) 
->withInput(); 
Chris Roberts @thechrisroberts Caddis Interactive 
} 
54
Chris Roberts Caddis Interactive 55
If valid, store the comment 
$comment = new Comment(); 
$comment->user_id = Auth::id(); 
$comment->item_id = Input::get('id'); 
$comment->item_type = Input::get('type'); 
$comment->title = Input::get('title'); 
$comment->content = Input::get('content'); 
$comment->save(); 
return Redirect::to(URL::previous() . '#comments') 
->with('message', 'Comment posted'); 
Chris Roberts @thechrisroberts Caddis Interactive 
56
Chris Roberts Caddis Interactive 57
Fin 
From start to end, Laravel provides a full-featured framework 
to make your development elegant and efficient 
• Laravel provides a powerful, flexible framework for application 
development. 
• Based on PHP, Laravel has broad support from most hosts. 
• Language features and framework methods are on par with or 
better than other popular frameworks. 
Chris Roberts @thechrisroberts Caddis Interactive 
58
Recommended Resources 
• Laracasts: https://laracasts.com/ 
• Laravel Podcast and Forums: http://laravel.io/forum 
• Code Bright by Dayle Rees 
• #Laravel on Freenode 
• https://github.com/JeffreyWay/Laravel-Generators 
• Homestead: http://laravel.com/docs/homestead 
Chris Roberts @thechrisroberts Caddis Interactive 
59
Thank you! 
Chris Roberts 
chris@caddis.co 
@thechrisroberts 
Caddis is hiring let’s talk 
Chris Roberts @thechrisroberts Caddis Interactive 
60