JavaScripting for the PHP Developer in 2012

JavaScripting for the PHP Developer in 2012

The modern day web developer is presented with possibilities the developers of 2005 would salivate over. In this session we'll look at some JavaScript tools that will simplify your web development life by reducing the complexity of your PHP backend, increasing the rich user interface presented in the browser, as well as redundancy in your frontend and backend code.

0f930e13633535c1c4041e95b8881308?s=128

Jeff Carouth

October 24, 2012
Tweet

Transcript

  1. JavaScripting for the PHP Developer in 2012 this is not

    the JavaScript from 1999 Jeff Carouth ZendCon 2012
  2. Jeff Carouth tweets jcarouth blogs http://carouth.com checks jcarouth@gmail.com works

  3. None
  4. JavaScript Basics

  5. Arrays array(); []; //PHP 5.4+ array(1, 2, 3, 4); array(1,

    "foo", new stdClass()); array("foo" => "bar", "fizz" => "buzz");
  6. Arrays array(); []; //PHP 5.4+ array(1, 2, 3, 4); array(1,

    "foo", new stdClass()); array("foo" => "bar", "fizz" => "buzz"); []; // new Array(); [1, 2, 3, 4]; [1, "foo", {}]; ["foo": "bar", "fizz": "buzz"]; //ERROR
  7. Arrays array(); []; //PHP 5.4+ array(1, 2, 3, 4); array(1,

    "foo", new stdClass()); array("foo" => "bar", "fizz" => "buzz"); []; // new Array(); [1, 2, 3, 4]; [1, "foo", {}]; ["foo": "bar", "fizz": "buzz"]; //ERROR {"foo": "bar", "fizz": "buzz"}; //NOT an array
  8. Arrays typeof []; // 'object' typeof new Array(); // 'object'

    [3]; // arr.length = 1 new Array(3); // arr.length = 3
  9. Objects but NOT Classes Prototypes

  10. class Car { private $make; private $model; private $year; public

    function __construct($make, $model, $year) { $this->make = $make; $this->model = $model; $this->year = $year; } // could use __toString() public function toString() { return $this->year." ".$this->make." ".$this->model; } } $myFirstCar = new Car('Acura', 'Integra', 1990); print $myFirstCar->toString(); // Result: ‘1990 Acura Integra’
  11. function Car(make, model, year) { this.make = make; this.model =

    model; this.year = year; this.toString = function() { return this.year + " " + this.make + " " + this.model; } } var myFirstCar = new Car('Acura', 'Integra', 1990); var myNewCar = new Car('Dodge', 'Charger', 2009); myFirstCar.toString(); // Result: ‘1990 Acura Integra’ myNewCar.toString(); // Result: ‘2009 Dodge Charger’
  12. Checking Type gettype($myFirstCar); // object $myFirstCar instanceof Car; // true

    get_class($myFirstCar); // Car typeof myFirstCar; // 'object' myFirstCar instanceof Car; // true myFirstCar.constuctor; // Car php JavaScript
  13. Prototypal Inheritance Warning: Here be dragons…at first.

  14. Object Methods Via the Prototype function Car(make, model, year) {

    this.make = make; this.model = model; this.year = year; this.toString = function() { return this.year + " " + this.make + " " + this.model; } }
  15. Object Methods Via the Prototype function Car(make, model, year) {

    this.make = make; this.model = model; this.year = year; this.toString = function() { return this.year + " " + this.make + " " + this.model; } } function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } Car.prototype.toString = function() { return this.year + " " + this.make + " " + this.model; }
  16. function Car(make, model, year) { this.make = make; this.model =

    model; this.year = year; this.toString = function() { return this.year + " " + this.make + " " + this.model; } } var aCar = new Car('Saturn', 'Vue', 2007); var anotherCar = new Car('Ford', 'F150', '2003'); aCar.toString(); // '2007 Saturn Vue' anotherCar.toString(); // '2003 Ford F150' aCar.toString = function() { return '2013 BMW 335is Convertible'; }; aCar.toString(); // '2013 BMW 335is Convertible' anotherCar.toString(); // '2003 Ford F150'
  17. function Car(make, model, year) { this.make = make; this.model =

    model; this.year = year; } Car.prototype.toString = function() { return this.year + " " + this.make + " " + this.model; } var aCar = new Car('Saturn', 'Vue', 2007); var anotherCar = new Car('Ford', 'F150', '2003'); aCar.toString(); // '2007 Saturn Vue' anotherCar.toString(); // '2003 Ford F150' Car.prototype.toString = function() { return '2013 BMW 335is Convertible'; }; aCar.toString(); // '2013 BMW 335is Convertible' anotherCar.toString(); // '2013 BMW 335is Convertible'
  18. class Dad extends Person { public function __construct($firstName) { $this->familyName

    = 'Carouth'; parent::__construct($firstName); } } class Son extends Dad { } $son = new Son('Jeff'); print $son->familyName; // 'Carouth'
  19. var Dad = function() { this.familyName = 'Carouth'; }; var

    Son = function(firstName) { this.firstName = firstName; }; Son.prototype = new Dad(); Son.prototype.constructor = Son; var jeff = new Son('Jeff'); jeff.familyName; // 'Carouth' jeff instanceof Son; // true jeff instanceof Dad; // true
  20. Namespaces Easy in PHP 5.3+ Easy enough in JavaScript

  21. <?php namespace Foo; class Car { public function __construct($make, $model,

    $year) { // ...snip... } // ...snip... } //someotherfile.php $myCar = new Foo\Car('Toyota', 'Prius', '2011');
  22. var Foo = Foo || {}; Foo.Car = function(make, model,

    year) { // ...snip.. }; var myCar = new Foo.Car('Toyota', 'Prius', '2011');
  23. The Module Pattern

  24. var Car = (function() { var Constructor; Constructor = function(make,

    model, year) { this.make = make; this.model = model; this.year = year; } Constructor.prototype.toString = function() { return this.year + " " + this.make + " " + this.model; } return Constructor; }());
  25. var Car = (function() { var Constructor; Constructor = function(make,

    model, year) { this.make = make; this.model = model; this.year = year; } Constructor.prototype.toString = function() { return this.year + " " + this.make + " " + this.model; } return Constructor; }()); (function() { }());
  26. var Car = (function() { var Constructor; Constructor = function(make,

    model, year) { this.make = make; this.model = model; this.year = year; } Constructor.prototype.toString = function() { return this.year + " " + this.make + " " + this.model; } return Constructor; }()); var Car = var Constructor; return Constructor;
  27. var Car = (function($) { var Constructor; Constructor = function(make,

    model, year) { this.make = make; this.model = model; this.year = year; } Constructor.prototype.toString = function() { return this.year + " " + this.make + " " + this.model; } return Constructor; }(jQuery)); Dependencies
  28. Extension myCar.beep(); //undefined Car = (function(Car) { Car.prototype.beep = function()

    { return 'Beep'; }; return Car; }(Car)); myCar.beep(); // 'Beep'
  29. Information Hiding A.K.A. private properties

  30. var Car = (function() { var started = false; var

    Constructor; Constructor = function(make, model, year) { /* snip */ }; Constructor.prototype = { constructor: Constructor, toString: function() { /* snip */ }, start: function() { if (!started) { started = true; } }, isRunning: function() { return started === true; } }; return Constructor; })();
  31. var myCar = new Car('BMW', '335is Convertible', 2013); myCar.isRunning(); //

    false myCar.started; // undefined myCar.start(); myCar.isRunning(); // true
  32. require.js file and module loader

  33. <!DOCTYPE html> <html> <head> <title>Example Application</title> <script data-main="scripts/main" src="scripts/require-jquery.js"></script> </head>

    <body> <h1>My Example Application</h1> <div id="output"></div> </body> </html>
  34. require(["jquery", "Car"], function($, Car) { var myCar = new Car('BMW',

    '335is Convertible', 2013); $("#output").html(myCar.toString()); }); scripts/main.js
  35. scripts/Car.js define(function () { var Constructor; Constructor = function(make, model,

    year) { this.make = make; this.model = model; this.year = year; }; Constructor.prototype.toString = function() { return this.year + " " + this.make + " " + this.model; } return Constructor; });
  36. None
  37. “MV*” Frameworks Backbone.js, KnockoutJS, AngularJS

  38. structure with models, collections, and views simple binding and handling

    of events connection to RESTful JSON API
  39. View Presenter Model Backbone.Model Backbone.Collection Templates Underscore.js Backbone.View Backbone.Router Backbone.Events

    Backbone.Sync
  40. Backbone.Router Binds URLs and hashes to routes.

  41. Backbone.Router MyRouter = Backbone.Router.extend({ routes: { "": "index", "cars": "cars",

    "cars/:id": "car" }, index: function() { /* show homepage */ }, cars: function() { /* list of cars */ }, car: function(id) { /* show car */ } });
  42. Backbone.View View takes data and transform it into HTML via

    templates and a reference to a DOM element. The view also listens to events and triggers action based those events.
  43. Backbone.View var CarView = Backbone.View.extend({ tagName: "li", className: "car", events:

    { 'click .start': 'start' }, render: function() { this.$el.html( this.name() + ' <span class="start">[start]</span>' ); return this; }, start: function() { alert('car started'); }, name: function() { return this.model.toString(); } });
  44. Backbone.Model The model syncs with a server. If the backend

    is RESTful the “out of the box” sync will just work. A model holds information about a single record from the backend. Model update triggers and event which will update the view for that specific model.
  45. Backbone.Model var Car = Backbone.Model.extend({ urlRoot: '/cars', toString: function() {

    return this.get('year') + " " + this.get('make') + " " + this.get('model'); } }); var CarView = Backbone.View.extend({ initialize: function() { this.model.on('change', this.render, this); } /* ...snip... */ });
  46. Backbone.Collection An “array” of models. Can also sync to the

    server if given a url root.
  47. Backbone.Collection var Cars = Backbone.Collection.extend({ url: '/cars', model: Car });

    var CarsView = Backbone.View.extend({ initialize: function() { this.collection = new Cars(); this.collection.fetch({ success: _.bind(function(resp, status, xhr) { this.render(); }, this) }); }, render: function() { this.collection.each(this.renderCar, this); }, renderCar: function(model) { var carView = new CarView({model: model}); this.$el.append(carView.el); } });
  48. Templates in Backbone There is no default. You can use

    Underscore.js templates since it is a dependency. You are able to use whatever JavaScript templating such as Handlebars.
  49. QUnit You do test your code, don’t you?

  50. <!doctype html> <html> <head> <title>Example Test Runner</title> <link rel="stylesheet" href="vendor/qunit.css"

    /> <script src="vendor/qunit.js"></script> <script src="../src/vendor/require.js" data-main="tests.js"></script> </head> <body> <div id="qunit"></div> </body> </html>
  51. (function() { QUnit.config.autostart = false; require.config({ baseUrl: "../src" }); var

    testModules = [ "model/CarTests.js" ]; require(testModules, QUnit.start); }());
  52. define(function(require) { var Car = require("./Car"); QUnit.module("model/Car", { setup: function()

    {}, teardown: function() {} }); QUnit.test("Car should not be running when first created", function() { var mycar = new Car('BMW', '335is', 2013); ok(!mycar.isRunning()); } ); QUnit.test("Car should be running after it is started", function() { var mycar = new Car("BMW", "335is", 2013); mycar.start(); ok(mycar.isRunning()); } ); });
  53. None
  54. Grunt Task-based build tool for JavaScript projects.

  55. module.exports = function(grunt) { grunt.initConfig({ lint: { src: ['src/model/**/*.js'], tests:

    ['tests/model/**/*.js'] }, qunit: { files: ['tests/tests.html'] }, uglify: {} }); grunt.registerTask('default', 'lint qunit'); };
  56. $ grunt Running "lint:src" (lint) task Lint free. Running "lint:tests"

    (lint) task Lint free. Running "qunit:files" (qunit) task Testing tests.htmlOK >> 2 assertions passed (15ms) Done, without errors.
  57. Thank You! https://joind.in/7022 @jcarouth | jcarouth@gmail.com http://speakerdeck.com/jcarouth