SlideShare a Scribd company logo
1 of 113
Download to read offline
フラットな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.

More Related Content

What's hot

オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)NTT DATA Technology & Innovation
 
Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)
Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)
Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)Youngil Cho
 
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみたOPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみたYoshio Hanawa
 
オープンソースのAPIゲートウェイ Kong ご紹介
オープンソースのAPIゲートウェイ Kong ご紹介 オープンソースのAPIゲートウェイ Kong ご紹介
オープンソースのAPIゲートウェイ Kong ご紹介 briscola-tokyo
 
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―shinjiigarashi
 
なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景Tatsuo Kudo
 
OpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンスOpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンスOpenID Foundation Japan
 
Hadoopのシステム設計・運用のポイント
Hadoopのシステム設計・運用のポイントHadoopのシステム設計・運用のポイント
Hadoopのシステム設計・運用のポイントCloudera Japan
 
JSON:APIについてざっくり入門
JSON:APIについてざっくり入門JSON:APIについてざっくり入門
JSON:APIについてざっくり入門iPride Co., Ltd.
 
Linuxカーネル超入門
Linuxカーネル超入門Linuxカーネル超入門
Linuxカーネル超入門Takashi Masuda
 
SpotBugs(FindBugs)による 大規模ERPのコード品質改善
SpotBugs(FindBugs)による 大規模ERPのコード品質改善SpotBugs(FindBugs)による 大規模ERPのコード品質改善
SpotBugs(FindBugs)による 大規模ERPのコード品質改善Works Applications
 
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)Takanori Sejima
 
Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話yaegashi
 
認証の課題とID連携の実装 〜ハンズオン〜
認証の課題とID連携の実装 〜ハンズオン〜認証の課題とID連携の実装 〜ハンズオン〜
認証の課題とID連携の実装 〜ハンズオン〜Masaru Kurahayashi
 
php and sapi and zendengine2 and...
php and sapi and zendengine2 and...php and sapi and zendengine2 and...
php and sapi and zendengine2 and...do_aki
 
JWTを使った簡易SSOで徐々にシステムをリニューアルしている話
JWTを使った簡易SSOで徐々にシステムをリニューアルしている話JWTを使った簡易SSOで徐々にシステムをリニューアルしている話
JWTを使った簡易SSOで徐々にシステムをリニューアルしている話Kazuyoshi Tsuchiya
 

What's hot (20)

オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
オススメのJavaログ管理手法 ~コンテナ編~(Open Source Conference 2022 Online/Spring 発表資料)
 
Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)
Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)
Python/Django를 이용한 쇼핑몰 구축(2018 4월 Django Girls Seoul)
 
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみたOPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
OPcacheの新機能ファイルベースキャッシュの内部実装を読んでみた
 
オープンソースのAPIゲートウェイ Kong ご紹介
オープンソースのAPIゲートウェイ Kong ご紹介 オープンソースのAPIゲートウェイ Kong ご紹介
オープンソースのAPIゲートウェイ Kong ご紹介
 
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
 
Paxos
PaxosPaxos
Paxos
 
なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景なぜOpenID Connectが必要となったのか、その歴史的背景
なぜOpenID Connectが必要となったのか、その歴史的背景
 
OpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンスOpenID Connect のビジネスチャンス
OpenID Connect のビジネスチャンス
 
Hadoopのシステム設計・運用のポイント
Hadoopのシステム設計・運用のポイントHadoopのシステム設計・運用のポイント
Hadoopのシステム設計・運用のポイント
 
JSON:APIについてざっくり入門
JSON:APIについてざっくり入門JSON:APIについてざっくり入門
JSON:APIについてざっくり入門
 
Linuxカーネル超入門
Linuxカーネル超入門Linuxカーネル超入門
Linuxカーネル超入門
 
SpotBugs(FindBugs)による 大規模ERPのコード品質改善
SpotBugs(FindBugs)による 大規模ERPのコード品質改善SpotBugs(FindBugs)による 大規模ERPのコード品質改善
SpotBugs(FindBugs)による 大規模ERPのコード品質改善
 
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)
 
SpringBootTest入門
SpringBootTest入門SpringBootTest入門
SpringBootTest入門
 
Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話Raspberry Pi + Go で IoT した話
Raspberry Pi + Go で IoT した話
 
Maven基礎
Maven基礎Maven基礎
Maven基礎
 
認証の課題とID連携の実装 〜ハンズオン〜
認証の課題とID連携の実装 〜ハンズオン〜認証の課題とID連携の実装 〜ハンズオン〜
認証の課題とID連携の実装 〜ハンズオン〜
 
php and sapi and zendengine2 and...
php and sapi and zendengine2 and...php and sapi and zendengine2 and...
php and sapi and zendengine2 and...
 
JWTを使った簡易SSOで徐々にシステムをリニューアルしている話
JWTを使った簡易SSOで徐々にシステムをリニューアルしている話JWTを使った簡易SSOで徐々にシステムをリニューアルしている話
JWTを使った簡易SSOで徐々にシステムをリニューアルしている話
 
Hadoop入門
Hadoop入門Hadoop入門
Hadoop入門
 

Viewers also liked

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
 

Viewers also liked (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 to フラットな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 to フラットな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
 

More from 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
 

More from 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
 

Recently uploaded

TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfTaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfMatsushita Laboratory
 
2024 01 Virtual_Counselor
2024 01 Virtual_Counselor 2024 01 Virtual_Counselor
2024 01 Virtual_Counselor arts yokohama
 
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見Shumpei Kishi
 
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦Sadao Tokuyama
 
20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdfAyachika Kitazaki
 
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-LoopへTetsuya Nihonmatsu
 
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~arts yokohama
 
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)ssuser539845
 
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法ssuser370dd7
 

Recently uploaded (12)

2024 04 minnanoito
2024 04 minnanoito2024 04 minnanoito
2024 04 minnanoito
 
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdfTaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
TaketoFujikawa_台本中の動作表現に基づくアニメーション原画システムの提案_SIGEC71.pdf
 
2024 01 Virtual_Counselor
2024 01 Virtual_Counselor 2024 01 Virtual_Counselor
2024 01 Virtual_Counselor
 
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
持続可能なDrupal Meetupのコツ - Drupal Meetup Tokyoの知見
 
2024 03 CTEA
2024 03 CTEA2024 03 CTEA
2024 03 CTEA
 
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
ARスタートアップOnePlanetの Apple Vision Proへの情熱と挑戦
 
20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf20240326_IoTLT_vol109_kitazaki_v1___.pdf
20240326_IoTLT_vol109_kitazaki_v1___.pdf
 
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
「今からでも間に合う」GPTsによる 活用LT会 - 人とAIが協調するHumani-in-the-Loopへ
 
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
2024 02 Nihon-Tanken ~Towards a More Inclusive Japan~
 
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
IFIP IP3での資格制度を対象とする国際認定(IPSJ86全国大会シンポジウム)
 
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
情報処理学会86回全国大会_Generic OAMをDeep Learning技術によって実現するための課題と解決方法
 
What is the world where you can make your own semiconductors?
What is the world where you can make your own semiconductors?What is the world where you can make your own semiconductors?
What is the world where you can make your own semiconductors?
 

フラットな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. フレームワークを使う 自分でゼロから作らなくて良い 万能なフレームワークは無い 実際に使って思想を理解する

Editor's Notes

  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