Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Bring your PHP application to the next level wi...

Bring your PHP application to the next level with React.JS

React.JS is a very powerful library for building user interfaces and the new, cool kid in the JavaScript world. But it is also very interesting for creating a fast, maintainable and interactive PHP application. In this talk I'll show what React is all about and how you can combine it’s power with your PHP application, even if you have to render out HTML on the server side. The result will be a flexible, component based architecture that enables developers to take page elements, like a single "follow" button, and place it everywhere on the site without having to duplicate any PHP, JS, HTML, CSS or AJAX endpoints in the process.

Bastian Hofmann

February 19, 2015
Tweet

More Decks by Bastian Hofmann

Other Decks in Programming

Transcript

  1. de duplication ode duplication code duplication code duplication code duplication

    code duplication code duplication code duplication code duplication code duplication code duplication code duplication code duplication code duplicatio code duplicat code duplic code dup code du code cod co co
  2. So?

  3. MVC

  4. var HelloMessage = React.createClass(
 {
 render: function () {
 return

    <div>Hello {this.props.name}</div>;
 }
 }
 );
 
 React.render(<HelloMessage name="John" />, mountNode);
  5. var Timer = React.createClass({
 getInitialState: function () {
 return {secs:

    0};
 },
 tick: function () {
 this.setState({secs: this.state.secs + 1});
 },
 componentDidMount: function () {
 this.interval = setInterval(this.tick, 1000);
 },
 componentWillUnmount: function () {
 clearInterval(this.interval);
 },
 render: function () {
 return (<div> Seconds Elapsed: {this.state.secs}</div> );
 }
 });
 
 React.render(<Timer />, mountNode);
  6. var TodoList = React.createClass(
 {
 render: function () {
 var

    createItem = function (itemText) {
 return <li>{itemText}</li>;
 };
 return ( <ul> {this.props.items.map(createItem)} </ul> );
 }
 }
 );
  7. var TodoApp = React.createClass({
 getInitialState: function () {
 return {items:

    […]};
 },
 render: function () {
 return (
 <div>
 <h3>TODO</h3>
 <TodoList items={this.state.items} />
 </div>
 );
 }
 });
  8. Profile Publications Publication Publication Publication AboutMe LeftColumn Image Menu Account

    Account Account Account Account Publication1 Publication2 Publication3 Institution
  9. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Batch requirements and pass them to resolvers
  10. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Call Services as effective as possible (Multi-GET,...)
  11. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Attach fetched data to Requirements and pass them back to the preparer
  12. Widget Widget Widget Widget Preparer Resolver Resolver Services Connector Interfaces

    Connector Implementations Distribute fetched data to the widgets that required it
  13. public function collect() {
 return new RequirementCollection([
 new EntityRequirement(
 'account',


    Account::class,
 ['id' => $this->request->get('id')]
 ),
 ], function() {
 return new RequirementCollection([
 new ServiceRequirement(
 'scienceDisciplines',
 AccountService::class,
 'getScienceDisciplines',
 ['account' => $this->account]
 )
 ]);
 });
 }
  14. public function collect() {
 yield [
 new EntityRequirement(
 'account',
 Account::class,


    ['id' => $this->request->get('id')]
 ),
 ];
 
 yield [
 new ServiceRequirement(
 'scienceDisciplines',
 AccountService::class,
 'getScienceDisciplines',
 ['account' => $this->account]
 )
 ];
 }
  15. trait ServiceRequirementFactory {
 
 /** @return $this */
 public static

    function getCall() {
 return new ServiceRequirementFactoryProxy( static::class );
 }
 }
  16. class ServiceRequirementFactoryProxy {
 
 private $className;
 
 public function __construct($className)

    {
 $this->className = $className;
 }
 
 public function __call($name, $arguments) {
 return [
 'serviceClass' => $this->className,
 'methodName' => $name,
 'arguments' => $arguments
 ];
 }
 
 }
  17. class PublicationKeywordSearch {
 
 public $publications;
 public $publicationListItems = [];


    
 public function collect() {
 yield [
 serviceRequirement(
 'publications',
 PublicationService::getCall()->getByKeywords(
 ['virology', 'cancer'], 10, 0
 )
 )
 ];
 foreach ($this->publications as $publication) {
 yield new WidgetRequirement(
 'publicationListItems',
 PublicationItem::CLASS,
 [ 'publicationId' => $publication->getId() ]
 );
 }
 }
 }
  18. class PublicationItem {
 
 public $publicationId;
 public $publication;
 
 public

    function collect() {
 yield new RequestDataRequirement('publicationId');
 yield [
 new EntityRequirement(
 'publication',
 Publication::class,
 ['id' => $this->publicationId]
 )
 ];
 }
 }
  19. public function getData() {
 return [
 'key' => 'value',
 'other'

    => 'data',
 'number' => 42,
 'subComponent' => $this->subComponent,
 'someArray' => [1, 2, 3],
 'subComponentList' => [ $this->items[0], $this->items[1] ]
 ];
 }
  20. {
 "component": "ParentComponent.jsx",
 "id": "ParentComponent-1234",
 "data": {
 "key": "value",
 "other":

    "data",
 "number": 42,
 "subComponent": {
 "component": "SubComponent.jsx",
 "id": "SubComponent",
 "data": { "boolValue": true }
 },
 "someArray": [1,2,3],
 "subComponentList": [
 {
 "component": "ListItem",
 "id": "ListItem-444",
 "data": { "title": "444s title“ }
 },
 {
 "component": "ListItem",
 "id": "ListItem-555",
 "data": { "title": "555s title“ }
 }
 ]
 }
 }
  21. var React = require('react');
 var SubComponent = require('SubComponent');
 var ListItem

    = require('ListItem');
 
 module.exports = React.createClass(
 {
 displayName: 'ParentComponent',
 render: function () {
 var items = [];
 
 for (var key in this.props.subComponentList) {
 if (this.props.subComponentList.hasOwnProperty(key)) {
 items.push(
 <li>
 <ListItem {...this.props.subComponentList[key]}></ListItem>
 </li>
 );
 }
 }
 
 return (
 <div className="{this.props.key}">
 <h1>{this.props.other} Hello PHP {this.props.number}</h1>
 <SubComponent {...this.props.subComponent}></SubComponent>
 <ul>{items}</ul>
 </div>
 );
 }
 }
 );
  22. var React = require('react');
 
 module.exports = React.createClass(
 {
 displayName:

    'ListItem',
 render: function () {
 return (
 <div>
 {this.props.title}
 </div>
 );
 }
 }
 );
  23. SEO

  24. Profile Publications Publication Publication Publication AboutMe LeftColumn Image Menu <div

    id="placeholder"></div> <script>loadWidget('/aboutMe', function(w) { w.render({ replace : '#placeholder' }); })</script> Institution