SlideShare una empresa de Scribd logo
1 de 113
フラットなPHPから
 フレームワークへ
       株式会社 adingo
      前田 雅央 @brtriver
@brtriver
Steps


         フラットなPHP

             リファクタリング




          フレームワーク


        * フラットなPHP = 1ファイルで書かれたPHP
Steps
            フラットなPHP
             View部分の分離

        アプリケーション(ドメイン)部分の分離

          Viewにレイアウト機能を追加

             ページを追加する

          フロントコントローラー導入

            ライブラリを利用する


            フレームワーク
どのフレームワークを使う?


なぜフレームワークを使う?
Step 0




     DBからデータ取得し
          取得したデータを
         HTMLで表示する
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
                                                                           list.php
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
                                                                           list.php
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
                                                                           list.php
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
                                                                           list.php
   'myuser',


DBからデータ取得
 );
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)


$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
                                                                           list.php
   'myuser',


DBからデータ取得
 );
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)


$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>



             取得したデータを表示
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
クライアント             サーバー




          リクエスト
                  PHP +
Browser
                  HTML
          レスポンス
                  list.php
Good

       シンプル
       1ファイルたったの26行
Bad
アプリケーションの拡張性が無い


      体系化されていない
       再利用性がない
体系化されていない




フォームの送信を行うコードの追加したい...

            どこに書く?



   同じファイル?別ファイルで書く?
コードの再利用性が低い
 新しい別ファイルでlist.phpのコードを利用
 できない。




     新しいページを コピペで作成
クライアント                     サーバー


             エ スト       PHP + HTML
           リク

                 ポ ンス
            レス            list.php
 Browser




                                     Bad
クライアント                     サーバー


             エ スト       PHP + HTML
           リク

                 ポ ンス
            レス            list.php
 Browser                             COPY




                                     Bad
クライアント                      サーバー


             エ スト        PHP + HTML
           リク

                  ポ ンス
             レス            list.php
 Browser                              COPY
           リクエ
                スト

                         PHP + HTML
           レスポ
               ンス

                          list2.php



                                      Bad
Step 1




         View部分の分離
show.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
show.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
   'myuser',



 );
   'mypassword',
                            ロジック部分
   array(PDO::ATTR_EMULATE_PREPARES => false)


$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
show.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
   'myuser',



 );
   'mypassword',
                            ロジック部分
   array(PDO::ATTR_EMULATE_PREPARES => false)


$stmt = $pdo->query('SELECT id, title FROM post');
?>


<html>
  <head>
    <title>投稿の一覧</title>
  </head>
  <body>
    <h1>投稿の一覧</h1>
    <ul>
                 View(HTML)部分
       <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?>
       <li>
          <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>">
             <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?>
          </a>
       </li>
       <?php endwhile; ?>
    </ul>
  </body>
</html>
show.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db:charset=utf8',
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');


// HTML部分のコードを読み込む
require 'templates/list.php';

                        別ファイルに分離
show.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db:charset=utf8',
   'myuser',
   'mypassword',  ロジック部分
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');


// HTML部分のコードを読み込む
require 'templates/list.php';

                        別ファイルに分離
クライアント                サーバー




          リクエスト   controller
Browser              PHP
                      list.php
クライアント                サーバー




          リクエスト   controller
Browser              PHP
                      list.php
クライアント                 サーバー




           リクエスト   controller
Browser               PHP
                       list.php




          レスポンス
                   view
                     HTML
                   template/list.php
クライアント                   サーバー




           リクエスト    controller
Browser                  PHP
                         list.php




          レスポンス
                    view
                         json
                   template/list-json.php
Good
       View部分の分離



   テンプレートの変更に強い
Step 2




  アプリケーション(ドメイン)
      部分の分離
index.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db:charset=utf8',
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');
index.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db:charset=utf8',

         データベースへ接続する
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );
$stmt = $pdo->query('SELECT id, title FROM post');
index.php
<?php
$pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db:charset=utf8',

         データベースへ接続する
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
 );

         全てのポストを取得する
$stmt = $pdo->query('SELECT id, title FROM post');
ドメイン
  データベースへの接続する
  全てのポストを取得する



   model.php に分離
<?php


// model.php


function get_database_connection()
{
  $pdo = new PDO(
   'mysql:host=localhost;dbname=blog_db;charset=utf8',
   'myuser',
   'mypassword',
   array(PDO::ATTR_EMULATE_PREPARES => false)
  );
  return $pdo;                                   get_database_connection
}


function get_all_posts()
{
  $pdo = get_database_connection();


    $stmt = $pdo->query('SELECT id, title FROM post');
    $posts = array();
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
      $posts[] = $row;
    }                                                    get_all_posts
    return $posts;
}
                                                         model.php
リファクタリング後のlist.php

<?php
require 'model.php';


$posts = get_all_posts();


require 'templates/list.php';


                       コントローラーは制御するだけ
リファクタリング後のlist.php

<?php
require 'model.php';            ロジック読込

$posts = get_all_posts();


require 'templates/list.php';


                       コントローラーは制御するだけ
リファクタリング後のlist.php

<?php
require 'model.php';            ロジック読込

$posts = get_all_posts();   全ポストを取得

require 'templates/list.php';


                       コントローラーは制御するだけ
リファクタリング後のlist.php

<?php
require 'model.php';            ロジック読込

$posts = get_all_posts();   全ポストを取得

require 'templates/list.php';    ビュー読込


                       コントローラーは制御するだけ
Good
アプリケーション(ドメイン)部分の分離


 コントローラが本来のコントローラーに


       シンプルなMVC
クライアント        サーバー




              リクエスト
                      controller
   Browser                   PHP
                             list.php



             レスポンス
                      view
                             HTML
                      template/list.php
クライアント        サーバー
                                        model
                                           Logic
                get_all_posts             model.php


              リクエスト
                      controller
   Browser                   PHP
                             list.php
                                                $POSTS


             レスポンス
                      view
                             HTML
                      template/list.php
Step 3




 Viewにレイアウト機能を追加
レイアウト機能

   Viewの共通部分を再利用できる仕組み
   <html>
     <head>
       <title>トップページ</title>
     </head>
     <body>
       <h1>こんにちは!こんにちは!</h1>
     </body>
   </html>

            template/layout.php
レイアウト機能

   Viewの共通部分を再利用できる仕組み
   <html>
     <head>
       <title>トップページ</title>
     </head>
     <body>
       <h1>こんにちは!こんにちは!</h1>
     </body>
                     動的部分を決定
   </html>

            template/layout.php
レイアウト機能

    PHPで書き換え
   <html>
     <head>
       <title><?php echo $title ?></title>
     </head>
     <body>
       <?php echo $content ?>
     </body>
   </html>

                 template/layout.php
ob_start() ... ob_get_clean()
<?php $title = '投稿のリスト' ?>                                 list.php

<?php ob_start() ?>
   <h1>投稿のリスト</h1>
   <ul>
     <?php foreach ($posts as $post): ?>
     <li>
        <a href="show.php?id=<?php echo
htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>">
           <?php echo htmlspecialchars($post['title'], ENT_QUOTES,
'utf-8') ?>
        </a>
     </li>
     <?php endforeach; ?>
   </ul>
<?php $content = ob_get_clean() ?>


<?php include 'layout.php' ?>
ob_start() ... ob_get_clean()
<?php $title = '投稿のリスト' ?>                                 list.php

<?php ob_start() ?>
   <h1>投稿のリスト</h1>
   <ul>
     <?php foreach ($posts as $post): ?>
     <li>
        <a href="show.php?id=<?php echo
htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>">
           <?php echo htmlspecialchars($post['title'], ENT_QUOTES,
'utf-8') ?>
        </a>
     </li>
     <?php endforeach; ?>
   </ul>
<?php $content = ob_get_clean() ?>


<?php include 'layout.php' ?>
ob_start() ... ob_get_clean()
<?php $title = '投稿のリスト' ?>                                 list.php

<?php ob_start() ?>
   <h1>投稿のリスト</h1>
   <ul>
     <?php foreach ($posts as $post): ?>
     <li>
        <a href="show.php?id=<?php echo
htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>">
           <?php echo htmlspecialchars($post['title'], ENT_QUOTES,
'utf-8') ?>
        </a>
     </li>
     <?php endforeach; ?>
   </ul>
<?php $content = ob_get_clean() ?>


<?php include 'layout.php' ?>
ob_start() ... ob_get_clean()
<?php $title = '投稿のリスト' ?>                                 list.php

<?php ob_start() ?>
   <h1>投稿のリスト</h1>
   <ul>
     <?php foreach ($posts as $post): ?>
     <li>
        <a href="show.php?id=<?php echo
htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>">
           <?php echo htmlspecialchars($post['title'], ENT_QUOTES,
'utf-8') ?>
        </a>
     </li>
     <?php endforeach; ?>
   </ul>
<?php $content = ob_get_clean() ?>
                                       出力せずにバッファリング
<?php include 'layout.php' ?>
ob_start() ... ob_get_clean()
<?php $title = '投稿のリスト' ?>                                 list.php

<?php ob_start() ?>
   <h1>投稿のリスト</h1>
   <ul>
     <?php foreach ($posts as $post): ?>
     <li>
        <a href="show.php?id=<?php echo
htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>">
           <?php echo htmlspecialchars($post['title'], ENT_QUOTES,
'utf-8') ?>
        </a>
     </li>
     <?php endforeach; ?>
   </ul>
<?php $content = ob_get_clean() ?>
                                       出力せずにバッファリング
<?php include 'layout.php' ?>
クライアント        サーバー
                                        model
                get_all_posts              Logic
                                           model.php


              リクエスト
                      controller
   Browser                   PHP
                             list.php

                                                $POSTS

             レスポンス
                      view
                          HTML
                      template/list.php
クライアント        サーバー
                                        model
                get_all_posts               Logic
                                            model.php


              リクエスト
                      controller
   Browser                   PHP
                             list.php

                                                 $POSTS

             レスポンス
                      view
                          HTML
                      template/list.php

                                        layout
                                           HTML
                                           layout.php
Good
  テンプレートの可用性がUP


Bad
 テンプレートエンジンの機能より劣る
     Smarty, Twig...
テンプレートエンジンのメリット

   Pure PHP
<title><?php echo htmlspecialchars($title, ENT_QUOTES, 'utf-8') ?></title>




   Twig (escape)
                     <title>{{ title }}</title>


   Twig (un escape)
                  <title>{{ title¦raw }}</title>
Step 4




       ページを追加する
   blogの詳細ページ(show)
list.phpと同じ仕組を作る
<?php


require_once 'model.php';


$post = get_post_by_id($_GET['id']);


require 'templates/show.php';     特定の記事を取得




                            show.php
クライアント        サーバー
                                      model
               get_post_by_id              Logic
                                            model.php


              リクエスト
                       controller
   Browser                    PHP
                           show.php

                                               $POST


             レスポンス
                       view
                           HTML
                      template/show.php

                                      layout
                                          HTML
                                          layout.php
クライアント         controller
                                             サーバー
                      PHP
                                            get_all_posts
                      list.php

            view
                 HTML              $POSTS

            template/list.php


             layout                   model
  Browser           HTML                    Logic
                      layout.php            model.php



             view
                                    $POST
                   HTML
            tempalte/show.php

                 controller
                                       get_post_by_id
                        PHP
                      show.php
クライアント         controller
                                             サーバー
                      PHP
                                            get_all_posts
                      list.php

            view
                      一覧表示処理
                 HTML              $POSTS

            template/list.php


             layout                   model
  Browser           HTML                    Logic
                      layout.php            model.php



             view
                                    $POST
                   HTML
            tempalte/show.php

                 controller
                                       get_post_by_id
                        PHP
                      show.php
クライアント         controller
                                             サーバー
                      PHP
                                            get_all_posts
                      list.php

            view
                      一覧表示処理
                 HTML              $POSTS

            template/list.php


             layout                   model
  Browser           HTML                    Logic
                      layout.php            model.php



             view
                                    $POST
                   HTML
                      詳細表示処理
            tempalte/show.php

                 controller
                                       get_post_by_id
                        PHP
                      show.php
クライアント         controller
                                             サーバー
                      PHP
                                            get_all_posts
                      list.php

            view
                      一覧表示処理
                 HTML              $POSTS

            template/list.php


             layout                   model
  Browser           HTML                    Logic
                      layout.php            model.php



             view
                                    $POST
                   HTML
                      詳細表示処理
            tempalte/show.php

                 controller
                                       get_post_by_id
                        PHP
                      show.php
Good
 Model, Layoutが共通化できている




Bad
   リクエストを受けるPHPは
    model.phpを忘れずに
  requireしなければならない
Step 5




    フロントコントローラー
フロントコントローラー?




      全てのリクエストを
       最初に必ず受ける
      1つのPHPファイル
Before
クライアント                                   サーバー
         http://example.com/list.php
                         controller
                              PHP
                              list.php


   Browser
Before
クライアント                                   サーバー
         http://example.com/list.php
                         controller
                              PHP
                              list.php


   Browser
                         controller
                              PHP
                             show.php

    http://example.com/show.php?id=5
After
クライアント                             サーバー



             front controller   controllers
   Browser         PHP              PHP
                 index.php      controllers.php
After
クライアント                                              サーバー

http://example.com/index.php/list         list_action()

                       front controller          controllers
    Browser                  PHP                     PHP
                           index.php             controllers.php
After
クライアント                                               サーバー

http://example.com/index.php/list          list_action()

                       front controller           controllers
    Browser                  PHP                      PHP
                           index.php              controllers.php



                                          show_action(5)

http://example.com/index.php/show?id=5
フロントコントローラー (routing)
require_once 'model.php';
require_once 'controllers.php';


// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></
body></html>';
}
                                            index.php
フロントコントローラー (routing)
require_once 'model.php';
require_once 'controllers.php';


// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></
body></html>';
}
                                            index.php
フロントコントローラー (routing)
require_once 'model.php';
require_once 'controllers.php';


// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></
body></html>';
}
                                            index.php
フロントコントローラー (routing)
require_once 'model.php';
require_once 'controllers.php';


// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></
body></html>';
}
                                            index.php
フロントコントローラー (routing)
require_once 'model.php';
require_once 'controllers.php';


// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();                   一覧表示へのリクエスト
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></
body></html>';
}
                                        index.php
フロントコントローラー (routing)
require_once 'model.php';
require_once 'controllers.php';


// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();                   一覧表示へのリクエスト
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);        記事詳細へのリクエスト
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></
body></html>';
}
                                        index.php
フロントコントローラー (routing)
require_once 'model.php';
require_once 'controllers.php';


// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();                   一覧表示へのリクエスト
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);        記事詳細へのリクエスト
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></
body></html>';                        想定外のリクエスト
}
                                        index.php
フロントコントローラー(アクション)
<?php                              controllers.php
// controllers.php
function list_action()
{
   $posts = get_all_posts();
   require 'templates/list.php';
}


function show_action($id)
{
  $post = get_post_by_id($id);
  require 'templates/show.php';
}
フロントコントローラー(アクション)
<?php                            controllers.php
// controllers.php
function list_action()
{
   $posts = get_all_posts();
   require 'templates/list.php';
}                              一覧表示へのリクエスト

function show_action($id)
{
  $post = get_post_by_id($id);
  require 'templates/show.php';
}
フロントコントローラー(アクション)
<?php                            controllers.php
// controllers.php
function list_action()
{
   $posts = get_all_posts();
   require 'templates/list.php';
}                              一覧表示へのリクエスト

function show_action($id)
{
  $post = get_post_by_id($id);
  require 'templates/show.php';
}                              記事詳細へのリクエスト
Good
   設定の読込などの集中管理
       ルーティング機能
Point

   クラスはまだ使ってません


     クラスで書かなくても
   ある程度の体系化は可能です
Step6




        ライブラリを利用する
ライブラリを利用する




 HttpFoundation Component
HttpFoundation Component を使うことで....




  Webアプリケーションで必須な
$_GET, $_POST, レスポンスデータ
    をオブジェクトで扱える
HttpFoundation Component を使うことで....


Pure PHP

   $id = (isset($_GET[ id ]))? $_GET[ id ]: 0;




 Object
          $id = $request->query( id , 0);
HttpFoundation Component を
    採用しているプロジェクト


       Symfony2
          Silex
        Drupal8
        phpBB4
          ppi2
        Laravel4
         Zikula
           ... more
HttpFoundation Component は
   今後のデファクトスタンダート

                   Laravel4




                              ??



                      FuelPHP2
Pure PHP

// リクエストを内部的にルーティング
$uri = $_SERVER['REQUEST_URI'];
if ($uri === ('/index.php/list')) {
   list_action();
} elseif ( preg_match("#^/index.php/show#", $uri) &&
isset($_GET['id'])) {
   show_action($_GET['id']);
} else {
   header('Status: 404 Not Found');
   echo '<html><body><h1>ページが見つかりません</h1></body></html>';
}

                                           index.php
Symfony component

$request = Request::createFromGlobals();


$uri = $request->getPathInfo();
if ($uri === '/') {
   $response = list_action();
} elseif ($uri === '/show' && $request->query->has('id')) {
   $response = show_action($request->query->get('id'));
} else {
   $html = '<html><body><h1>Page Not Found</h1></body></
html>';
   $response = new Response($html, 404);
}


$response->send();                         index.php
Symfony component

$request = Request::createFromGlobals();


$uri = $request->getPathInfo();
if ($uri === '/') {
   $response = list_action();
} elseif ($uri === '/show' && $request->query->has('id')) {
   $response = show_action($request->query->get('id'));
} else {
   $html = '<html><body><h1>Page Not Found</h1></body></
html>';
   $response = new Response($html, 404);
}


$response->send();                         index.php
<?php                              controllers.php
// controllers.php
function list_action()
{
   $posts = get_all_posts();
   require 'templates/list.php';
}
<?php                              controllers.php
// controllers.php
function list_action()
{
   $posts = get_all_posts();
   require 'templates/list.php';
}

                     テンプレートをレンダリング (echo)
Controllers
function list_action()
{
  $posts = get_all_posts();
  $html = render_template('templates/list.php', array('posts' =>
$posts));
  return new Response($html);
}


function render_template($path, $params)
{
  extract($params, EXTR_SKIP);
  ob_start();
  require $path;
  $html = ob_get_clean();


    return $html;
}
Controllers
function list_action()
{
  $posts = get_all_posts();
  $html = render_template('templates/list.php', array('posts' =>
$posts));
  return new Response($html);
}
                              Responseオブジェクトを返す
function render_template($path, $params)
{
  extract($params, EXTR_SKIP);
  ob_start();
  require $path;
  $html = ob_get_clean();


    return $html;
}
Controllers
function list_action()
{
  $posts = get_all_posts();
  $html = render_template('templates/list.php', array('posts' =>
$posts));
  return new Response($html);
}
                              Responseオブジェクトを返す
function render_template($path, $params)
{
  extract($params, EXTR_SKIP);
  ob_start();
  require $path;
  $html = ob_get_clean();


    return $html;
}
Controllers
function list_action()
{
  $posts = get_all_posts();
  $html = render_template('templates/list.php', array('posts' =>
$posts));
  return new Response($html);
}
                              Responseオブジェクトを返す
function render_template($path, $params)
{
  extract($params, EXTR_SKIP);
  ob_start();
  require $path;
  $html = ob_get_clean();


    return $html;
}
                             典型的なPHPテンプレートパターン
CakePHP




DietCake
CakePHP




DietCake
CakePHP




DietCake
Good
  簡易的なフレームワークが完成
       車輪の再開発を防ぐ
      必要な機能だけ利用できる
        再利用性が高い

Bad
必要以上の機能が含まれるかもしれない
クライアント             サーバー
                                                model
                                                     Logic
                                                     model.php
                            list_action()

            リクエスト front controller          controllers
  Browser               PHP                    PHP
                    index.php           controllers.php


                              show_action()



              レスポンス
                             view
                                     HTML
                            template/show.php

                                                layout
                                                      HTML
                                                   layout.php
クライアント              サーバー
                                        Model
                    MVC

            リクエスト
  Browser
                           controller




             レスポンス


                              view
Final




        フレームワークを使う
            とは?
フレームワークを使う




    フレームワークを使っても
    やりたいことは変わらない
フレームワークを使う




  作りたいのはアプリケーション
フレームワークを使う




     ルーティング
     規約
     コントローラー
     バリデーター
     ......
Silexで書き換えると...
$app = new SilexApplication();
.....
$app->get('/show', function(Application $app, Request $request)
{
    $get_post_by_id = $app['model.post_by_id'];
    $post = $get_post_by_id($request->query->get('id'));
    return $app->render('templates/show.twig',
                         array('post' => $post));
});
フラットなPHPからSymfony2へ

 フラットなPHPからSliexへ

  フラットなPHPからSlimへ

           詳しくはぐぐってみてください
フレームワークを使う




  自分でゼロから作らなくて良い


   万能なフレームワークは無い
   実際に使って思想を理解する
まとめ


  フラットなPHPのデメリット
フレームワークの本来の仕事は何か?


使われるのではなく使うこと
thank you.

Más contenido relacionado

La actualidad más candente

PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~Miki Shimogai
 
マスター・オブ・Reflectパッケージ
マスター・オブ・Reflectパッケージマスター・オブ・Reflectパッケージ
マスター・オブ・ReflectパッケージTakuya Ueda
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法についてYuji Otani
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話Koichiro Matsuoka
 
ある工場のRedmine +(Plus)
ある工場のRedmine +(Plus)ある工場のRedmine +(Plus)
ある工場のRedmine +(Plus)Kohei Nakamura
 
View customize plugin for Redmineの紹介 (2019年版)
View customize plugin for Redmineの紹介 (2019年版)View customize plugin for Redmineの紹介 (2019年版)
View customize plugin for Redmineの紹介 (2019年版)onozaty
 
ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 ( Redmine of one plant 2022 ...
ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 (  Redmine of one plant 2022 ...ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 (  Redmine of one plant 2022 ...
ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 ( Redmine of one plant 2022 ...Kohei Nakamura
 
【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮
【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮
【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮Hibino Hisashi
 
Redmine にいろいろ埋め込んでみた
Redmine にいろいろ埋め込んでみたRedmine にいろいろ埋め込んでみた
Redmine にいろいろ埋め込んでみたKohei Nakamura
 
Redmineプラグイン導入・開発入門
Redmineプラグイン導入・開発入門Redmineプラグイン導入・開発入門
Redmineプラグイン導入・開発入門Minoru Maeda
 
ぐるなびが活用するElastic Cloud
ぐるなびが活用するElastic Cloudぐるなびが活用するElastic Cloud
ぐるなびが活用するElastic CloudElasticsearch
 
はじめる! Redmine
はじめる! Redmineはじめる! Redmine
はじめる! RedmineGo Maeda
 
こわくない Git
こわくない Gitこわくない Git
こわくない GitKota Saito
 
Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~
Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~
Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~Masahito Zembutsu
 
Redmineによるメール対応管理の運用事例
Redmineによるメール対応管理の運用事例Redmineによるメール対応管理の運用事例
Redmineによるメール対応管理の運用事例Go Maeda
 
Redmine 5.0 + RedMica 2.1 新機能評価ガイド
Redmine 5.0 + RedMica 2.1 新機能評価ガイドRedmine 5.0 + RedMica 2.1 新機能評価ガイド
Redmine 5.0 + RedMica 2.1 新機能評価ガイドGo Maeda
 
Redmineをちょっと便利に! プログラミング無しで使ってみるREST API
Redmineをちょっと便利に! プログラミング無しで使ってみるREST APIRedmineをちょっと便利に! プログラミング無しで使ってみるREST API
Redmineをちょっと便利に! プログラミング無しで使ってみるREST APIGo Maeda
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMPYusuke Kagata
 
世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計増田 亨
 

La actualidad más candente (20)

PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
 
マスター・オブ・Reflectパッケージ
マスター・オブ・Reflectパッケージマスター・オブ・Reflectパッケージ
マスター・オブ・Reflectパッケージ
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
 
ある工場のRedmine +(Plus)
ある工場のRedmine +(Plus)ある工場のRedmine +(Plus)
ある工場のRedmine +(Plus)
 
View customize plugin for Redmineの紹介 (2019年版)
View customize plugin for Redmineの紹介 (2019年版)View customize plugin for Redmineの紹介 (2019年版)
View customize plugin for Redmineの紹介 (2019年版)
 
ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 ( Redmine of one plant 2022 ...
ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 (  Redmine of one plant 2022 ...ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 (  Redmine of one plant 2022 ...
ある工場の Redmine 2022 〜ある工場の Redmine 5.0 バージョンアップ〜 ( Redmine of one plant 2022 ...
 
【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮
【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮
【第26回Elasticsearch勉強会】Logstashとともに振り返る、やっちまった事例ごった煮
 
Redmine にいろいろ埋め込んでみた
Redmine にいろいろ埋め込んでみたRedmine にいろいろ埋め込んでみた
Redmine にいろいろ埋め込んでみた
 
Redmineプラグイン導入・開発入門
Redmineプラグイン導入・開発入門Redmineプラグイン導入・開発入門
Redmineプラグイン導入・開発入門
 
ぐるなびが活用するElastic Cloud
ぐるなびが活用するElastic Cloudぐるなびが活用するElastic Cloud
ぐるなびが活用するElastic Cloud
 
はじめる! Redmine
はじめる! Redmineはじめる! Redmine
はじめる! Redmine
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出
 
Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~
Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~
Dockerの期待と現実~Docker都市伝説はなぜ生まれるのか~
 
Redmineによるメール対応管理の運用事例
Redmineによるメール対応管理の運用事例Redmineによるメール対応管理の運用事例
Redmineによるメール対応管理の運用事例
 
Redmine 5.0 + RedMica 2.1 新機能評価ガイド
Redmine 5.0 + RedMica 2.1 新機能評価ガイドRedmine 5.0 + RedMica 2.1 新機能評価ガイド
Redmine 5.0 + RedMica 2.1 新機能評価ガイド
 
Redmineをちょっと便利に! プログラミング無しで使ってみるREST API
Redmineをちょっと便利に! プログラミング無しで使ってみるREST APIRedmineをちょっと便利に! プログラミング無しで使ってみるREST API
Redmineをちょっと便利に! プログラミング無しで使ってみるREST API
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMP
 
世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計世界でいちばんわかりやすいドメイン駆動設計
世界でいちばんわかりやすいドメイン駆動設計
 

Destacado

RUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践SmalltalkRUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践SmalltalkSho Yoshida
 
Parquet performance tuning: the missing guide
Parquet performance tuning: the missing guideParquet performance tuning: the missing guide
Parquet performance tuning: the missing guideRyan Blue
 
徳丸本とAmazonと僕
徳丸本とAmazonと僕徳丸本とAmazonと僕
徳丸本とAmazonと僕monmon Kumagai
 
ベトナムでのアジャイルオフショア開発への挑戦
ベトナムでのアジャイルオフショア開発への挑戦ベトナムでのアジャイルオフショア開発への挑戦
ベトナムでのアジャイルオフショア開発への挑戦Arata Fujimura
 
NoSQL Architecture Overview
NoSQL Architecture OverviewNoSQL Architecture Overview
NoSQL Architecture OverviewChristopher Foot
 
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswiftSwift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswiftTomohiro Kumagai
 
Memory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine LearningMemory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine LearningWes McKinney
 
Goをカンストさせる話
Goをカンストさせる話Goをカンストさせる話
Goをカンストさせる話Moriyoshi Koizumi
 
Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)lestrrat
 
Scikit learnで学ぶ機械学習入門
Scikit learnで学ぶ機械学習入門Scikit learnで学ぶ機械学習入門
Scikit learnで学ぶ機械学習入門Takami Sato
 
逆説のカスタマーサクセス
逆説のカスタマーサクセス逆説のカスタマーサクセス
逆説のカスタマーサクセスTakaaki Umada
 
JSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めようJSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めようVOYAGE GROUP
 
PHPカンファレンス関西2012 Silex
PHPカンファレンス関西2012 SilexPHPカンファレンス関西2012 Silex
PHPカンファレンス関西2012 SilexMasao Maeda
 
今すぐ使えるPHP開発のあれこれ
今すぐ使えるPHP開発のあれこれ今すぐ使えるPHP開発のあれこれ
今すぐ使えるPHP開発のあれこれYuya Kikukawa
 
アジャイルマインドの重要性(長野)
アジャイルマインドの重要性(長野)アジャイルマインドの重要性(長野)
アジャイルマインドの重要性(長野)Akiyah
 
JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)VOYAGE GROUP
 
HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用
HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用
HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用Device WebAPI Consortium
 
環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向
環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向
環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向Device WebAPI Consortium
 

Destacado (20)

RUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践SmalltalkRUNNING Smalltalk - 実践Smalltalk
RUNNING Smalltalk - 実践Smalltalk
 
Intro to DevOps
Intro to DevOpsIntro to DevOps
Intro to DevOps
 
Parquet performance tuning: the missing guide
Parquet performance tuning: the missing guideParquet performance tuning: the missing guide
Parquet performance tuning: the missing guide
 
徳丸本とAmazonと僕
徳丸本とAmazonと僕徳丸本とAmazonと僕
徳丸本とAmazonと僕
 
ベトナムでのアジャイルオフショア開発への挑戦
ベトナムでのアジャイルオフショア開発への挑戦ベトナムでのアジャイルオフショア開発への挑戦
ベトナムでのアジャイルオフショア開発への挑戦
 
NoSQL Architecture Overview
NoSQL Architecture OverviewNoSQL Architecture Overview
NoSQL Architecture Overview
 
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswiftSwift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
Swift 3 を書くときに知っておきたい API デザインガイドライン #love_swift #akibaswift
 
Memory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine LearningMemory Interoperability in Analytics and Machine Learning
Memory Interoperability in Analytics and Machine Learning
 
Goをカンストさせる話
Goをカンストさせる話Goをカンストさせる話
Goをカンストさせる話
 
Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)Kubernetes in 30 minutes (2017/03/10)
Kubernetes in 30 minutes (2017/03/10)
 
Scikit learnで学ぶ機械学習入門
Scikit learnで学ぶ機械学習入門Scikit learnで学ぶ機械学習入門
Scikit learnで学ぶ機械学習入門
 
逆説のカスタマーサクセス
逆説のカスタマーサクセス逆説のカスタマーサクセス
逆説のカスタマーサクセス
 
極める routes.php
極める routes.php極める routes.php
極める routes.php
 
JSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めようJSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めよう
 
PHPカンファレンス関西2012 Silex
PHPカンファレンス関西2012 SilexPHPカンファレンス関西2012 Silex
PHPカンファレンス関西2012 Silex
 
今すぐ使えるPHP開発のあれこれ
今すぐ使えるPHP開発のあれこれ今すぐ使えるPHP開発のあれこれ
今すぐ使えるPHP開発のあれこれ
 
アジャイルマインドの重要性(長野)
アジャイルマインドの重要性(長野)アジャイルマインドの重要性(長野)
アジャイルマインドの重要性(長野)
 
JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)
 
HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用
HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用
HeartSyncのアップアップガールズ(仮)@武道館ライブでの利用
 
環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向
環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向
環境発電(エナジーハーベスト)に適した無線方式EnOceanの技術・市場動向
 

Similar a フラットなPHPからフレームワークへ

FuelPHP Osu Nagoya vol.1
FuelPHP Osu Nagoya vol.1FuelPHP Osu Nagoya vol.1
FuelPHP Osu Nagoya vol.1Fumito Mizuno
 
第21回Creators MeetUp
第21回Creators MeetUp第21回Creators MeetUp
第21回Creators MeetUpKenichi Mukai
 
Gen-Template-for-Perl
Gen-Template-for-PerlGen-Template-for-Perl
Gen-Template-for-Perlnasneg
 
101210 supreme web adobe seminar Nagoya
101210 supreme web adobe seminar Nagoya101210 supreme web adobe seminar Nagoya
101210 supreme web adobe seminar Nagoyatamotsu toyoda
 
WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法regret raym
 
Mojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるMojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるjamadam
 
WebAPIではじめるphp入門
WebAPIではじめるphp入門WebAPIではじめるphp入門
WebAPIではじめるphp入門Hiroaki Murayama
 
Modern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI SeminarModern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI SeminarSotaro Karasawa
 
20091030cakephphandson 01
20091030cakephphandson 0120091030cakephphandson 01
20091030cakephphandson 01Yusuke Ando
 
Ruby on Rails Tutorial
Ruby on Rails TutorialRuby on Rails Tutorial
Ruby on Rails TutorialKen Iiboshi
 
最新PHP事情 (2000年7月22日,PHPカンファレンス)
最新PHP事情 (2000年7月22日,PHPカンファレンス)最新PHP事情 (2000年7月22日,PHPカンファレンス)
最新PHP事情 (2000年7月22日,PHPカンファレンス)Rui Hirokawa
 
Wordpressで自分好みのテーマを作る
Wordpressで自分好みのテーマを作るWordpressで自分好みのテーマを作る
Wordpressで自分好みのテーマを作るTakashi Uemura
 
FuelPHPをさわってみて
FuelPHPをさわってみてFuelPHPをさわってみて
FuelPHPをさわってみてSotaro Omura
 
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道20123時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012Yusuke Ando
 
<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー<第1回>Laravelハンズオンセミナー
<第1回>LaravelハンズオンセミナーTatsuyoshi Mashiko
 
WordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニック
WordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニックWordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニック
WordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニックTakashi Uemura
 
System3 search
System3 searchSystem3 search
System3 searchJun Chiba
 
WordPress実践 導入からカスタマイズまで
WordPress実践 導入からカスタマイズまでWordPress実践 導入からカスタマイズまで
WordPress実践 導入からカスタマイズまでTakashi Uemura
 
Erlang Web
Erlang WebErlang Web
Erlang WebNgoc Dao
 

Similar a フラットなPHPからフレームワークへ (20)

FuelPHP Osu Nagoya vol.1
FuelPHP Osu Nagoya vol.1FuelPHP Osu Nagoya vol.1
FuelPHP Osu Nagoya vol.1
 
WordPress と Bootstrap
WordPress と BootstrapWordPress と Bootstrap
WordPress と Bootstrap
 
第21回Creators MeetUp
第21回Creators MeetUp第21回Creators MeetUp
第21回Creators MeetUp
 
Gen-Template-for-Perl
Gen-Template-for-PerlGen-Template-for-Perl
Gen-Template-for-Perl
 
101210 supreme web adobe seminar Nagoya
101210 supreme web adobe seminar Nagoya101210 supreme web adobe seminar Nagoya
101210 supreme web adobe seminar Nagoya
 
WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法WordPressで投稿記事情報の取得方法
WordPressで投稿記事情報の取得方法
 
Mojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるMojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてる
 
WebAPIではじめるphp入門
WebAPIではじめるphp入門WebAPIではじめるphp入門
WebAPIではじめるphp入門
 
Modern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI SeminarModern PHP Programming @ PFI Seminar
Modern PHP Programming @ PFI Seminar
 
20091030cakephphandson 01
20091030cakephphandson 0120091030cakephphandson 01
20091030cakephphandson 01
 
Ruby on Rails Tutorial
Ruby on Rails TutorialRuby on Rails Tutorial
Ruby on Rails Tutorial
 
最新PHP事情 (2000年7月22日,PHPカンファレンス)
最新PHP事情 (2000年7月22日,PHPカンファレンス)最新PHP事情 (2000年7月22日,PHPカンファレンス)
最新PHP事情 (2000年7月22日,PHPカンファレンス)
 
Wordpressで自分好みのテーマを作る
Wordpressで自分好みのテーマを作るWordpressで自分好みのテーマを作る
Wordpressで自分好みのテーマを作る
 
FuelPHPをさわってみて
FuelPHPをさわってみてFuelPHPをさわってみて
FuelPHPをさわってみて
 
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道20123時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
 
<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー<第1回>Laravelハンズオンセミナー
<第1回>Laravelハンズオンセミナー
 
WordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニック
WordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニックWordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニック
WordPressでオリジナルサイトを作るための最初の一歩的なカスタマイズテクニック
 
System3 search
System3 searchSystem3 search
System3 search
 
WordPress実践 導入からカスタマイズまで
WordPress実践 導入からカスタマイズまでWordPress実践 導入からカスタマイズまで
WordPress実践 導入からカスタマイズまで
 
Erlang Web
Erlang WebErlang Web
Erlang Web
 

Más de Masao Maeda

アットホームな感じの オンラインイベントの配信を意識してみた
アットホームな感じの オンラインイベントの配信を意識してみたアットホームな感じの オンラインイベントの配信を意識してみた
アットホームな感じの オンラインイベントの配信を意識してみたMasao Maeda
 
営業・運用を支える "気付ける" 管理画面
営業・運用を支える "気付ける" 管理画面営業・運用を支える "気付ける" 管理画面
営業・運用を支える "気付ける" 管理画面Masao Maeda
 
管理画面のアクセスコントロール
管理画面のアクセスコントロール 管理画面のアクセスコントロール
管理画面のアクセスコントロール Masao Maeda
 
Japan PHPCon2011 Silex UPdate
Japan PHPCon2011 Silex UPdateJapan PHPCon2011 Silex UPdate
Japan PHPCon2011 Silex UPdateMasao Maeda
 
次世代PHPフレームワーク Symfony2
次世代PHPフレームワーク Symfony2次世代PHPフレームワーク Symfony2
次世代PHPフレームワーク Symfony2Masao Maeda
 
Symfony Study 090518
Symfony Study 090518Symfony Study 090518
Symfony Study 090518Masao Maeda
 

Más de Masao Maeda (7)

アットホームな感じの オンラインイベントの配信を意識してみた
アットホームな感じの オンラインイベントの配信を意識してみたアットホームな感じの オンラインイベントの配信を意識してみた
アットホームな感じの オンラインイベントの配信を意識してみた
 
営業・運用を支える "気付ける" 管理画面
営業・運用を支える "気付ける" 管理画面営業・運用を支える "気付ける" 管理画面
営業・運用を支える "気付ける" 管理画面
 
管理画面のアクセスコントロール
管理画面のアクセスコントロール 管理画面のアクセスコントロール
管理画面のアクセスコントロール
 
Japan PHPCon2011 Silex UPdate
Japan PHPCon2011 Silex UPdateJapan PHPCon2011 Silex UPdate
Japan PHPCon2011 Silex UPdate
 
Silex 入門
Silex 入門Silex 入門
Silex 入門
 
次世代PHPフレームワーク Symfony2
次世代PHPフレームワーク Symfony2次世代PHPフレームワーク Symfony2
次世代PHPフレームワーク Symfony2
 
Symfony Study 090518
Symfony Study 090518Symfony Study 090518
Symfony Study 090518
 

フラットなPHPからフレームワークへ

  • 1. フラットなPHPから フレームワークへ 株式会社 adingo 前田 雅央 @brtriver
  • 3. Steps フラットなPHP リファクタリング フレームワーク * フラットなPHP = 1ファイルで書かれたPHP
  • 4. Steps フラットなPHP View部分の分離 アプリケーション(ドメイン)部分の分離 Viewにレイアウト機能を追加 ページを追加する フロントコントローラー導入 ライブラリを利用する フレームワーク
  • 6. Step 0 DBからデータ取得し 取得したデータを HTMLで表示する
  • 7. <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', list.php 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 8. <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', list.php 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 9. <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', list.php 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 10. <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', list.php 'myuser', DBからデータ取得 ); 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 11. <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', list.php 'myuser', DBからデータ取得 ); 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> 取得したデータを表示 <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 12. クライアント サーバー リクエスト PHP + Browser HTML レスポンス list.php
  • 13. Good シンプル 1ファイルたったの26行
  • 14. Bad アプリケーションの拡張性が無い 体系化されていない 再利用性がない
  • 15. 体系化されていない フォームの送信を行うコードの追加したい... どこに書く? 同じファイル?別ファイルで書く?
  • 17. クライアント サーバー エ スト PHP + HTML リク ポ ンス レス list.php Browser Bad
  • 18. クライアント サーバー エ スト PHP + HTML リク ポ ンス レス list.php Browser COPY Bad
  • 19. クライアント サーバー エ スト PHP + HTML リク ポ ンス レス list.php Browser COPY リクエ スト PHP + HTML レスポ ンス list2.php Bad
  • 20. Step 1 View部分の分離
  • 21. show.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 22. show.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', 'myuser', ); 'mypassword', ロジック部分 array(PDO::ATTR_EMULATE_PREPARES => false) $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 23. show.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', 'myuser', ); 'mypassword', ロジック部分 array(PDO::ATTR_EMULATE_PREPARES => false) $stmt = $pdo->query('SELECT id, title FROM post'); ?> <html> <head> <title>投稿の一覧</title> </head> <body> <h1>投稿の一覧</h1> <ul> View(HTML)部分 <?php while ($row = $stmt->fetch(PDO::FETCH_ASSOC)): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($row['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($row['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endwhile; ?> </ul> </body> </html>
  • 24. show.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db:charset=utf8', 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post'); // HTML部分のコードを読み込む require 'templates/list.php'; 別ファイルに分離
  • 25. show.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db:charset=utf8', 'myuser', 'mypassword', ロジック部分 array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post'); // HTML部分のコードを読み込む require 'templates/list.php'; 別ファイルに分離
  • 26. クライアント サーバー リクエスト controller Browser PHP list.php
  • 27. クライアント サーバー リクエスト controller Browser PHP list.php
  • 28. クライアント サーバー リクエスト controller Browser PHP list.php レスポンス view HTML template/list.php
  • 29. クライアント サーバー リクエスト controller Browser PHP list.php レスポンス view json template/list-json.php
  • 30. Good View部分の分離 テンプレートの変更に強い
  • 31. Step 2 アプリケーション(ドメイン) 部分の分離
  • 32. index.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db:charset=utf8', 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post');
  • 33. index.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db:charset=utf8', データベースへ接続する 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); $stmt = $pdo->query('SELECT id, title FROM post');
  • 34. index.php <?php $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db:charset=utf8', データベースへ接続する 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); 全てのポストを取得する $stmt = $pdo->query('SELECT id, title FROM post');
  • 35. ドメイン データベースへの接続する 全てのポストを取得する model.php に分離
  • 36. <?php // model.php function get_database_connection() { $pdo = new PDO( 'mysql:host=localhost;dbname=blog_db;charset=utf8', 'myuser', 'mypassword', array(PDO::ATTR_EMULATE_PREPARES => false) ); return $pdo; get_database_connection } function get_all_posts() { $pdo = get_database_connection(); $stmt = $pdo->query('SELECT id, title FROM post'); $posts = array(); while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { $posts[] = $row; } get_all_posts return $posts; } model.php
  • 37. リファクタリング後のlist.php <?php require 'model.php'; $posts = get_all_posts(); require 'templates/list.php'; コントローラーは制御するだけ
  • 38. リファクタリング後のlist.php <?php require 'model.php'; ロジック読込 $posts = get_all_posts(); require 'templates/list.php'; コントローラーは制御するだけ
  • 39. リファクタリング後のlist.php <?php require 'model.php'; ロジック読込 $posts = get_all_posts(); 全ポストを取得 require 'templates/list.php'; コントローラーは制御するだけ
  • 40. リファクタリング後のlist.php <?php require 'model.php'; ロジック読込 $posts = get_all_posts(); 全ポストを取得 require 'templates/list.php'; ビュー読込 コントローラーは制御するだけ
  • 42. クライアント サーバー リクエスト controller Browser PHP list.php レスポンス view HTML template/list.php
  • 43. クライアント サーバー model Logic get_all_posts model.php リクエスト controller Browser PHP list.php $POSTS レスポンス view HTML template/list.php
  • 45. レイアウト機能 Viewの共通部分を再利用できる仕組み <html> <head> <title>トップページ</title> </head> <body> <h1>こんにちは!こんにちは!</h1> </body> </html> template/layout.php
  • 46. レイアウト機能 Viewの共通部分を再利用できる仕組み <html> <head> <title>トップページ</title> </head> <body> <h1>こんにちは!こんにちは!</h1> </body> 動的部分を決定 </html> template/layout.php
  • 47. レイアウト機能 PHPで書き換え <html> <head> <title><?php echo $title ?></title> </head> <body> <?php echo $content ?> </body> </html> template/layout.php
  • 48. ob_start() ... ob_get_clean() <?php $title = '投稿のリスト' ?> list.php <?php ob_start() ?> <h1>投稿のリスト</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($post['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endforeach; ?> </ul> <?php $content = ob_get_clean() ?> <?php include 'layout.php' ?>
  • 49. ob_start() ... ob_get_clean() <?php $title = '投稿のリスト' ?> list.php <?php ob_start() ?> <h1>投稿のリスト</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($post['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endforeach; ?> </ul> <?php $content = ob_get_clean() ?> <?php include 'layout.php' ?>
  • 50. ob_start() ... ob_get_clean() <?php $title = '投稿のリスト' ?> list.php <?php ob_start() ?> <h1>投稿のリスト</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($post['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endforeach; ?> </ul> <?php $content = ob_get_clean() ?> <?php include 'layout.php' ?>
  • 51. ob_start() ... ob_get_clean() <?php $title = '投稿のリスト' ?> list.php <?php ob_start() ?> <h1>投稿のリスト</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($post['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endforeach; ?> </ul> <?php $content = ob_get_clean() ?> 出力せずにバッファリング <?php include 'layout.php' ?>
  • 52. ob_start() ... ob_get_clean() <?php $title = '投稿のリスト' ?> list.php <?php ob_start() ?> <h1>投稿のリスト</h1> <ul> <?php foreach ($posts as $post): ?> <li> <a href="show.php?id=<?php echo htmlspecialchars($post['id'], ENT_QUOTES, 'utf-8') ?>"> <?php echo htmlspecialchars($post['title'], ENT_QUOTES, 'utf-8') ?> </a> </li> <?php endforeach; ?> </ul> <?php $content = ob_get_clean() ?> 出力せずにバッファリング <?php include 'layout.php' ?>
  • 53. クライアント サーバー model get_all_posts Logic model.php リクエスト controller Browser PHP list.php $POSTS レスポンス view HTML template/list.php
  • 54. クライアント サーバー model get_all_posts Logic model.php リクエスト controller Browser PHP list.php $POSTS レスポンス view HTML template/list.php layout HTML layout.php
  • 55. Good テンプレートの可用性がUP Bad テンプレートエンジンの機能より劣る Smarty, Twig...
  • 56. テンプレートエンジンのメリット Pure PHP <title><?php echo htmlspecialchars($title, ENT_QUOTES, 'utf-8') ?></title> Twig (escape) <title>{{ title }}</title> Twig (un escape) <title>{{ title¦raw }}</title>
  • 57. Step 4 ページを追加する blogの詳細ページ(show)
  • 58. list.phpと同じ仕組を作る <?php require_once 'model.php'; $post = get_post_by_id($_GET['id']); require 'templates/show.php'; 特定の記事を取得 show.php
  • 59. クライアント サーバー model get_post_by_id Logic model.php リクエスト controller Browser PHP show.php $POST レスポンス view HTML template/show.php layout HTML layout.php
  • 60. クライアント controller サーバー PHP get_all_posts list.php view HTML $POSTS template/list.php layout model Browser HTML Logic layout.php model.php view $POST HTML tempalte/show.php controller get_post_by_id PHP show.php
  • 61. クライアント controller サーバー PHP get_all_posts list.php view 一覧表示処理 HTML $POSTS template/list.php layout model Browser HTML Logic layout.php model.php view $POST HTML tempalte/show.php controller get_post_by_id PHP show.php
  • 62. クライアント controller サーバー PHP get_all_posts list.php view 一覧表示処理 HTML $POSTS template/list.php layout model Browser HTML Logic layout.php model.php view $POST HTML 詳細表示処理 tempalte/show.php controller get_post_by_id PHP show.php
  • 63. クライアント controller サーバー PHP get_all_posts list.php view 一覧表示処理 HTML $POSTS template/list.php layout model Browser HTML Logic layout.php model.php view $POST HTML 詳細表示処理 tempalte/show.php controller get_post_by_id PHP show.php
  • 64. Good Model, Layoutが共通化できている Bad リクエストを受けるPHPは model.phpを忘れずに requireしなければならない
  • 65. Step 5 フロントコントローラー
  • 66. フロントコントローラー? 全てのリクエストを 最初に必ず受ける 1つのPHPファイル
  • 67. Before クライアント サーバー http://example.com/list.php controller PHP list.php Browser
  • 68. Before クライアント サーバー http://example.com/list.php controller PHP list.php Browser controller PHP show.php http://example.com/show.php?id=5
  • 69. After クライアント サーバー front controller controllers Browser PHP PHP index.php controllers.php
  • 70. After クライアント サーバー http://example.com/index.php/list list_action() front controller controllers Browser PHP PHP index.php controllers.php
  • 71. After クライアント サーバー http://example.com/index.php/list list_action() front controller controllers Browser PHP PHP index.php controllers.php show_action(5) http://example.com/index.php/show?id=5
  • 72. フロントコントローラー (routing) require_once 'model.php'; require_once 'controllers.php'; // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></ body></html>'; } index.php
  • 73. フロントコントローラー (routing) require_once 'model.php'; require_once 'controllers.php'; // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></ body></html>'; } index.php
  • 74. フロントコントローラー (routing) require_once 'model.php'; require_once 'controllers.php'; // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></ body></html>'; } index.php
  • 75. フロントコントローラー (routing) require_once 'model.php'; require_once 'controllers.php'; // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></ body></html>'; } index.php
  • 76. フロントコントローラー (routing) require_once 'model.php'; require_once 'controllers.php'; // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); 一覧表示へのリクエスト } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></ body></html>'; } index.php
  • 77. フロントコントローラー (routing) require_once 'model.php'; require_once 'controllers.php'; // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); 一覧表示へのリクエスト } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); 記事詳細へのリクエスト } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></ body></html>'; } index.php
  • 78. フロントコントローラー (routing) require_once 'model.php'; require_once 'controllers.php'; // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); 一覧表示へのリクエスト } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); 記事詳細へのリクエスト } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></ body></html>'; 想定外のリクエスト } index.php
  • 79. フロントコントローラー(アクション) <?php controllers.php // controllers.php function list_action() { $posts = get_all_posts(); require 'templates/list.php'; } function show_action($id) { $post = get_post_by_id($id); require 'templates/show.php'; }
  • 80. フロントコントローラー(アクション) <?php controllers.php // controllers.php function list_action() { $posts = get_all_posts(); require 'templates/list.php'; } 一覧表示へのリクエスト function show_action($id) { $post = get_post_by_id($id); require 'templates/show.php'; }
  • 81. フロントコントローラー(アクション) <?php controllers.php // controllers.php function list_action() { $posts = get_all_posts(); require 'templates/list.php'; } 一覧表示へのリクエスト function show_action($id) { $post = get_post_by_id($id); require 'templates/show.php'; } 記事詳細へのリクエスト
  • 82. Good 設定の読込などの集中管理 ルーティング機能
  • 83. Point クラスはまだ使ってません クラスで書かなくても ある程度の体系化は可能です
  • 84. Step6 ライブラリを利用する
  • 86. HttpFoundation Component を使うことで.... Webアプリケーションで必須な $_GET, $_POST, レスポンスデータ をオブジェクトで扱える
  • 87. HttpFoundation Component を使うことで.... Pure PHP $id = (isset($_GET[ id ]))? $_GET[ id ]: 0; Object $id = $request->query( id , 0);
  • 88. HttpFoundation Component を 採用しているプロジェクト Symfony2 Silex Drupal8 phpBB4 ppi2 Laravel4 Zikula ... more
  • 89. HttpFoundation Component は 今後のデファクトスタンダート Laravel4 ?? FuelPHP2
  • 90. Pure PHP // リクエストを内部的にルーティング $uri = $_SERVER['REQUEST_URI']; if ($uri === ('/index.php/list')) { list_action(); } elseif ( preg_match("#^/index.php/show#", $uri) && isset($_GET['id'])) { show_action($_GET['id']); } else { header('Status: 404 Not Found'); echo '<html><body><h1>ページが見つかりません</h1></body></html>'; } index.php
  • 91. Symfony component $request = Request::createFromGlobals(); $uri = $request->getPathInfo(); if ($uri === '/') { $response = list_action(); } elseif ($uri === '/show' && $request->query->has('id')) { $response = show_action($request->query->get('id')); } else { $html = '<html><body><h1>Page Not Found</h1></body></ html>'; $response = new Response($html, 404); } $response->send(); index.php
  • 92. Symfony component $request = Request::createFromGlobals(); $uri = $request->getPathInfo(); if ($uri === '/') { $response = list_action(); } elseif ($uri === '/show' && $request->query->has('id')) { $response = show_action($request->query->get('id')); } else { $html = '<html><body><h1>Page Not Found</h1></body></ html>'; $response = new Response($html, 404); } $response->send(); index.php
  • 93. <?php controllers.php // controllers.php function list_action() { $posts = get_all_posts(); require 'templates/list.php'; }
  • 94. <?php controllers.php // controllers.php function list_action() { $posts = get_all_posts(); require 'templates/list.php'; } テンプレートをレンダリング (echo)
  • 95. Controllers function list_action() { $posts = get_all_posts(); $html = render_template('templates/list.php', array('posts' => $posts)); return new Response($html); } function render_template($path, $params) { extract($params, EXTR_SKIP); ob_start(); require $path; $html = ob_get_clean(); return $html; }
  • 96. Controllers function list_action() { $posts = get_all_posts(); $html = render_template('templates/list.php', array('posts' => $posts)); return new Response($html); } Responseオブジェクトを返す function render_template($path, $params) { extract($params, EXTR_SKIP); ob_start(); require $path; $html = ob_get_clean(); return $html; }
  • 97. Controllers function list_action() { $posts = get_all_posts(); $html = render_template('templates/list.php', array('posts' => $posts)); return new Response($html); } Responseオブジェクトを返す function render_template($path, $params) { extract($params, EXTR_SKIP); ob_start(); require $path; $html = ob_get_clean(); return $html; }
  • 98. Controllers function list_action() { $posts = get_all_posts(); $html = render_template('templates/list.php', array('posts' => $posts)); return new Response($html); } Responseオブジェクトを返す function render_template($path, $params) { extract($params, EXTR_SKIP); ob_start(); require $path; $html = ob_get_clean(); return $html; } 典型的なPHPテンプレートパターン
  • 102. Good 簡易的なフレームワークが完成 車輪の再開発を防ぐ 必要な機能だけ利用できる 再利用性が高い Bad 必要以上の機能が含まれるかもしれない
  • 103. クライアント サーバー model Logic model.php list_action() リクエスト front controller controllers Browser PHP PHP index.php controllers.php show_action() レスポンス view HTML template/show.php layout HTML layout.php
  • 104. クライアント サーバー Model MVC リクエスト Browser controller レスポンス view
  • 105. Final フレームワークを使う とは?
  • 106. フレームワークを使う フレームワークを使っても やりたいことは変わらない
  • 108. フレームワークを使う ルーティング 規約 コントローラー バリデーター ......
  • 109. Silexで書き換えると... $app = new SilexApplication(); ..... $app->get('/show', function(Application $app, Request $request) { $get_post_by_id = $app['model.post_by_id']; $post = $get_post_by_id($request->query->get('id')); return $app->render('templates/show.twig', array('post' => $post)); });
  • 110. フラットなPHPからSymfony2へ フラットなPHPからSliexへ フラットなPHPからSlimへ 詳しくはぐぐってみてください
  • 111. フレームワークを使う 自分でゼロから作らなくて良い 万能なフレームワークは無い 実際に使って思想を理解する

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n
  51. \n
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n
  62. \n
  63. \n
  64. \n
  65. \n
  66. \n
  67. \n
  68. \n
  69. \n
  70. \n
  71. \n
  72. \n
  73. \n
  74. \n
  75. \n
  76. \n
  77. \n
  78. \n
  79. \n
  80. \n
  81. \n
  82. \n
  83. \n
  84. \n
  85. \n
  86. \n
  87. \n
  88. \n
  89. \n
  90. \n
  91. \n
  92. \n
  93. \n