SlideShare a Scribd company logo
フラットな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

Fuel php osc tokyo2012
Fuel php osc tokyo2012Fuel php osc tokyo2012
Fuel php osc tokyo2012
Fumito Mizuno
 
WebAPIではじめるphp入門
WebAPIではじめるphp入門WebAPIではじめるphp入門
WebAPIではじめるphp入門Hiroaki Murayama
 
Flask勉強会その1
Flask勉強会その1Flask勉強会その1
Flask勉強会その1
Masato Kawamura
 
WordBeach @kurudrive
WordBeach @kurudriveWordBeach @kurudrive
WordBeach @kurudrive
Hidekazu Ishikawa
 
メタプログラミングRuby勉強会#7(fluentプラグイン)
メタプログラミングRuby勉強会#7(fluentプラグイン)メタプログラミングRuby勉強会#7(fluentプラグイン)
メタプログラミングRuby勉強会#7(fluentプラグイン)Ashitaba YOSHIOKA
 
はじめての FuelPHP
はじめての FuelPHPはじめての FuelPHP
はじめての FuelPHPSho A
 
Mojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるMojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるjamadam
 
CodeIgniter入門
CodeIgniter入門CodeIgniter入門
CodeIgniter入門
Sho A
 
実用裏方 Perl 入門
実用裏方 Perl 入門実用裏方 Perl 入門
実用裏方 Perl 入門
keroyonn
 
第21回Creators MeetUp
第21回Creators MeetUp第21回Creators MeetUp
第21回Creators MeetUp
Kenichi Mukai
 
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道20123時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
Yusuke Ando
 
CakePHP+Smartyハイブリッドによるラクラク開発
CakePHP+Smartyハイブリッドによるラクラク開発CakePHP+Smartyハイブリッドによるラクラク開発
CakePHP+Smartyハイブリッドによるラクラク開発
Shinzo SAITO
 
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
leverages_event
 
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LTNorikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Masahiro Nagano
 
Alfrescoのカスタムテーブルの使い方
Alfrescoのカスタムテーブルの使い方Alfrescoのカスタムテーブルの使い方
Alfrescoのカスタムテーブルの使い方
Jun Terashita
 
[Alfresco]ドキュメントライブラリのUIカスタマイズ
[Alfresco]ドキュメントライブラリのUIカスタマイズ[Alfresco]ドキュメントライブラリのUIカスタマイズ
[Alfresco]ドキュメントライブラリのUIカスタマイズJun Terashita
 
Php5 4勉強会
Php5 4勉強会Php5 4勉強会
Php5 4勉強会Yuji Otani
 

What's hot (19)

Fuel php osc tokyo2012
Fuel php osc tokyo2012Fuel php osc tokyo2012
Fuel php osc tokyo2012
 
WebAPIではじめるphp入門
WebAPIではじめるphp入門WebAPIではじめるphp入門
WebAPIではじめるphp入門
 
Flask勉強会その1
Flask勉強会その1Flask勉強会その1
Flask勉強会その1
 
WordBeach @kurudrive
WordBeach @kurudriveWordBeach @kurudrive
WordBeach @kurudrive
 
メタプログラミングRuby勉強会#7(fluentプラグイン)
メタプログラミングRuby勉強会#7(fluentプラグイン)メタプログラミングRuby勉強会#7(fluentプラグイン)
メタプログラミングRuby勉強会#7(fluentプラグイン)
 
はじめての FuelPHP
はじめての FuelPHPはじめての FuelPHP
はじめての FuelPHP
 
Mojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてるMojoliciousをウェブ制作現場で使ってみてる
Mojoliciousをウェブ制作現場で使ってみてる
 
CodeIgniter入門
CodeIgniter入門CodeIgniter入門
CodeIgniter入門
 
実用裏方 Perl 入門
実用裏方 Perl 入門実用裏方 Perl 入門
実用裏方 Perl 入門
 
第21回Creators MeetUp
第21回Creators MeetUp第21回Creators MeetUp
第21回Creators MeetUp
 
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道20123時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
3時間濃縮CakePHP2.1 in PHPカンファレンス北海道2012
 
CakePHP+Smartyハイブリッドによるラクラク開発
CakePHP+Smartyハイブリッドによるラクラク開発CakePHP+Smartyハイブリッドによるラクラク開発
CakePHP+Smartyハイブリッドによるラクラク開発
 
Pyramid入門
Pyramid入門Pyramid入門
Pyramid入門
 
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
「スピード」と「品質」を実現するPHP開発チームの取り組み~AngularJS+FuelPHP+AspectMock~
 
PHP勉強会 #51
PHP勉強会 #51PHP勉強会 #51
PHP勉強会 #51
 
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LTNorikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
Norikraで作るPHPの例外検知システム YAPC::Asia Tokyo 2015 LT
 
Alfrescoのカスタムテーブルの使い方
Alfrescoのカスタムテーブルの使い方Alfrescoのカスタムテーブルの使い方
Alfrescoのカスタムテーブルの使い方
 
[Alfresco]ドキュメントライブラリのUIカスタマイズ
[Alfresco]ドキュメントライブラリのUIカスタマイズ[Alfresco]ドキュメントライブラリのUIカスタマイズ
[Alfresco]ドキュメントライブラリのUIカスタマイズ
 
Php5 4勉強会
Php5 4勉強会Php5 4勉強会
Php5 4勉強会
 

Viewers also liked

第4回Symfony2勉強会 基礎編ワークショップ.1
第4回Symfony2勉強会 基礎編ワークショップ.1第4回Symfony2勉強会 基礎編ワークショップ.1
第4回Symfony2勉強会 基礎編ワークショップ.1
Yusuke Ueno
 
第4回Symfony2勉強会 基礎編ワークショップ.0
第4回Symfony2勉強会 基礎編ワークショップ.0第4回Symfony2勉強会 基礎編ワークショップ.0
第4回Symfony2勉強会 基礎編ワークショップ.0
Yusuke Ueno
 
Symfony2 Behat/BDD (#Symfony2study 4)
Symfony2 Behat/BDD (#Symfony2study 4)Symfony2 Behat/BDD (#Symfony2study 4)
Symfony2 Behat/BDD (#Symfony2study 4)
Hidenori Goto
 
Symfony2のフォームフレームワーク
Symfony2のフォームフレームワークSymfony2のフォームフレームワーク
Symfony2のフォームフレームワーク
Katsuhiro Ogawa
 
Silex 入門
Silex 入門Silex 入門
Silex 入門
Masao Maeda
 
Symfony2でより良いソフトウェアを作るために
Symfony2でより良いソフトウェアを作るためにSymfony2でより良いソフトウェアを作るために
Symfony2でより良いソフトウェアを作るためにAtsuhiro Kubo
 

Viewers also liked (6)

第4回Symfony2勉強会 基礎編ワークショップ.1
第4回Symfony2勉強会 基礎編ワークショップ.1第4回Symfony2勉強会 基礎編ワークショップ.1
第4回Symfony2勉強会 基礎編ワークショップ.1
 
第4回Symfony2勉強会 基礎編ワークショップ.0
第4回Symfony2勉強会 基礎編ワークショップ.0第4回Symfony2勉強会 基礎編ワークショップ.0
第4回Symfony2勉強会 基礎編ワークショップ.0
 
Symfony2 Behat/BDD (#Symfony2study 4)
Symfony2 Behat/BDD (#Symfony2study 4)Symfony2 Behat/BDD (#Symfony2study 4)
Symfony2 Behat/BDD (#Symfony2study 4)
 
Symfony2のフォームフレームワーク
Symfony2のフォームフレームワークSymfony2のフォームフレームワーク
Symfony2のフォームフレームワーク
 
Silex 入門
Silex 入門Silex 入門
Silex 入門
 
Symfony2でより良いソフトウェアを作るために
Symfony2でより良いソフトウェアを作るためにSymfony2でより良いソフトウェアを作るために
Symfony2でより良いソフトウェアを作るために
 

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

WordPress と Bootstrap
WordPress と BootstrapWordPress と Bootstrap
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
 
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 Tutorial
Ken 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
 
<第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 Web
Ngoc Dao
 
Web 04
Web 04Web 04
Web 04
XMLProJ2014
 
Phpcon tokyo 20120_bigginer
Phpcon tokyo 20120_bigginerPhpcon tokyo 20120_bigginer
Phpcon tokyo 20120_bigginer
Hideo Kashioka
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterMasanori Oobayashi
 
初めての Data api
初めての Data api初めての Data api
初めての Data api
Yuji Takayama
 
メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月
メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月
メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月
Masahiro Nagano
 
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみようAlfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Tasuku Otani
 

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

WordPress と Bootstrap
WordPress と BootstrapWordPress と Bootstrap
WordPress と Bootstrap
 
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で投稿記事情報の取得方法
 
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で自分好みのテーマを作る
 
<第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
 
Web 04
Web 04Web 04
Web 04
 
Phpcon tokyo 20120_bigginer
Phpcon tokyo 20120_bigginerPhpcon tokyo 20120_bigginer
Phpcon tokyo 20120_bigginer
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
 
初めての Data api
初めての Data api初めての Data api
初めての Data api
 
メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月
メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月
メルカリのデータベース戦略 / PHPとMySQLの怖い話 MyNA会2015年8月
 
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみようAlfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
Alfresco勉強会#36 alfresco 5でカスタムREST APIを作ってみよう
 

More from VOYAGE GROUP

AWS SDK for Go in #jawsmeguro
AWS SDK for Go in #jawsmeguroAWS SDK for Go in #jawsmeguro
AWS SDK for Go in #jawsmeguro
VOYAGE GROUP
 
Data Engineering at VOYAGE GROUP #jawsdays
Data Engineering at VOYAGE GROUP #jawsdaysData Engineering at VOYAGE GROUP #jawsdays
Data Engineering at VOYAGE GROUP #jawsdaysVOYAGE GROUP
 
JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)VOYAGE GROUP
 
JSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めようJSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めようVOYAGE GROUP
 
Flux react現状確認会
Flux react現状確認会Flux react現状確認会
Flux react現状確認会VOYAGE GROUP
 
[20140625]wwdc2014 feedback
[20140625]wwdc2014 feedback[20140625]wwdc2014 feedback
[20140625]wwdc2014 feedback
VOYAGE GROUP
 
Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-
Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-
Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-VOYAGE GROUP
 
事業内デザイナーのミッション(公開版) genesix 藤井幹大
事業内デザイナーのミッション(公開版) genesix 藤井幹大事業内デザイナーのミッション(公開版) genesix 藤井幹大
事業内デザイナーのミッション(公開版) genesix 藤井幹大VOYAGE GROUP
 
[20130624]最近の開発環境について話してみる sakata
[20130624]最近の開発環境について話してみる sakata[20130624]最近の開発環境について話してみる sakata
[20130624]最近の開発環境について話してみる sakataVOYAGE GROUP
 
セミナープレゼン資料【Adingo】 20130529 
セミナープレゼン資料【Adingo】 20130529 セミナープレゼン資料【Adingo】 20130529 
セミナープレゼン資料【Adingo】 20130529 VOYAGE GROUP
 
セミナープレゼン資料【Adingo】 20130530 
セミナープレゼン資料【Adingo】 20130530 セミナープレゼン資料【Adingo】 20130530 
セミナープレゼン資料【Adingo】 20130530 VOYAGE GROUP
 
Abテストノススメ
AbテストノススメAbテストノススメ
AbテストノススメVOYAGE GROUP
 
iPhoneアプリ「トリセツ」にて実践したリーンスタートアップ
iPhoneアプリ「トリセツ」にて実践したリーンスタートアップiPhoneアプリ「トリセツ」にて実践したリーンスタートアップ
iPhoneアプリ「トリセツ」にて実践したリーンスタートアップVOYAGE GROUP
 
【発表用】Lpoワークショップ~組織でサイト改善をする方法~
【発表用】Lpoワークショップ~組織でサイト改善をする方法~【発表用】Lpoワークショップ~組織でサイト改善をする方法~
【発表用】Lpoワークショップ~組織でサイト改善をする方法~VOYAGE GROUP
 
Jenkinsとhadoopを利用した継続的データ解析環境の構築
Jenkinsとhadoopを利用した継続的データ解析環境の構築Jenkinsとhadoopを利用した継続的データ解析環境の構築
Jenkinsとhadoopを利用した継続的データ解析環境の構築VOYAGE GROUP
 
Androidにおけるテストに関して〜デバイスをどう選択するか〜
Androidにおけるテストに関して〜デバイスをどう選択するか〜Androidにおけるテストに関して〜デバイスをどう選択するか〜
Androidにおけるテストに関して〜デバイスをどう選択するか〜VOYAGE GROUP
 
スマホ無料アプリのマネタイズについて【Adingo】
スマホ無料アプリのマネタイズについて【Adingo】スマホ無料アプリのマネタイズについて【Adingo】
スマホ無料アプリのマネタイズについて【Adingo】VOYAGE GROUP
 
最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーション
最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーション最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーション
最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーションVOYAGE GROUP
 
【発表用】ウェブアナリスト養成講座「Lpoとabテスト」
【発表用】ウェブアナリスト養成講座「Lpoとabテスト」【発表用】ウェブアナリスト養成講座「Lpoとabテスト」
【発表用】ウェブアナリスト養成講座「Lpoとabテスト」VOYAGE GROUP
 
ゴールから始めよう!
ゴールから始めよう!ゴールから始めよう!
ゴールから始めよう!VOYAGE GROUP
 

More from VOYAGE GROUP (20)

AWS SDK for Go in #jawsmeguro
AWS SDK for Go in #jawsmeguroAWS SDK for Go in #jawsmeguro
AWS SDK for Go in #jawsmeguro
 
Data Engineering at VOYAGE GROUP #jawsdays
Data Engineering at VOYAGE GROUP #jawsdaysData Engineering at VOYAGE GROUP #jawsdays
Data Engineering at VOYAGE GROUP #jawsdays
 
JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)JavaScriptトレンド総括(2014)
JavaScriptトレンド総括(2014)
 
JSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めようJSON Schema で Web API のスキマを埋めよう
JSON Schema で Web API のスキマを埋めよう
 
Flux react現状確認会
Flux react現状確認会Flux react現状確認会
Flux react現状確認会
 
[20140625]wwdc2014 feedback
[20140625]wwdc2014 feedback[20140625]wwdc2014 feedback
[20140625]wwdc2014 feedback
 
Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-
Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-
Google playでのリワードアプリリジェクトからの今後のマネタイズ手段について インタースティシャル広告×クロスプロモーション-
 
事業内デザイナーのミッション(公開版) genesix 藤井幹大
事業内デザイナーのミッション(公開版) genesix 藤井幹大事業内デザイナーのミッション(公開版) genesix 藤井幹大
事業内デザイナーのミッション(公開版) genesix 藤井幹大
 
[20130624]最近の開発環境について話してみる sakata
[20130624]最近の開発環境について話してみる sakata[20130624]最近の開発環境について話してみる sakata
[20130624]最近の開発環境について話してみる sakata
 
セミナープレゼン資料【Adingo】 20130529 
セミナープレゼン資料【Adingo】 20130529 セミナープレゼン資料【Adingo】 20130529 
セミナープレゼン資料【Adingo】 20130529 
 
セミナープレゼン資料【Adingo】 20130530 
セミナープレゼン資料【Adingo】 20130530 セミナープレゼン資料【Adingo】 20130530 
セミナープレゼン資料【Adingo】 20130530 
 
Abテストノススメ
AbテストノススメAbテストノススメ
Abテストノススメ
 
iPhoneアプリ「トリセツ」にて実践したリーンスタートアップ
iPhoneアプリ「トリセツ」にて実践したリーンスタートアップiPhoneアプリ「トリセツ」にて実践したリーンスタートアップ
iPhoneアプリ「トリセツ」にて実践したリーンスタートアップ
 
【発表用】Lpoワークショップ~組織でサイト改善をする方法~
【発表用】Lpoワークショップ~組織でサイト改善をする方法~【発表用】Lpoワークショップ~組織でサイト改善をする方法~
【発表用】Lpoワークショップ~組織でサイト改善をする方法~
 
Jenkinsとhadoopを利用した継続的データ解析環境の構築
Jenkinsとhadoopを利用した継続的データ解析環境の構築Jenkinsとhadoopを利用した継続的データ解析環境の構築
Jenkinsとhadoopを利用した継続的データ解析環境の構築
 
Androidにおけるテストに関して〜デバイスをどう選択するか〜
Androidにおけるテストに関して〜デバイスをどう選択するか〜Androidにおけるテストに関して〜デバイスをどう選択するか〜
Androidにおけるテストに関して〜デバイスをどう選択するか〜
 
スマホ無料アプリのマネタイズについて【Adingo】
スマホ無料アプリのマネタイズについて【Adingo】スマホ無料アプリのマネタイズについて【Adingo】
スマホ無料アプリのマネタイズについて【Adingo】
 
最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーション
最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーション最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーション
最新のマーケットアルゴリズムと、 アルゴリズムを踏まえてのプロモーション
 
【発表用】ウェブアナリスト養成講座「Lpoとabテスト」
【発表用】ウェブアナリスト養成講座「Lpoとabテスト」【発表用】ウェブアナリスト養成講座「Lpoとabテスト」
【発表用】ウェブアナリスト養成講座「Lpoとabテスト」
 
ゴールから始めよう!
ゴールから始めよう!ゴールから始めよう!
ゴールから始めよう!
 

Recently uploaded

【slideshare】オンライン二次健診サービス_20240607.pptx.pdf
【slideshare】オンライン二次健診サービス_20240607.pptx.pdf【slideshare】オンライン二次健診サービス_20240607.pptx.pdf
【slideshare】オンライン二次健診サービス_20240607.pptx.pdf
chiakiota2
 
CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介
CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介
CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介
taisukekuwano4
 
株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介
株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介
株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介
ssuserdc1268
 
LabBase就職ご紹介資料_240605サービス概要説明資料240605.pdf
LabBase就職ご紹介資料_240605サービス概要説明資料240605.pdfLabBase就職ご紹介資料_240605サービス概要説明資料240605.pdf
LabBase就職ご紹介資料_240605サービス概要説明資料240605.pdf
ssuser8de8212
 
研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案
研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案
研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案
ssuser4eac57
 
smartcamp_RECRUIT_deck 2024060606 dddddd
smartcamp_RECRUIT_deck 2024060606 ddddddsmartcamp_RECRUIT_deck 2024060606 dddddd
smartcamp_RECRUIT_deck 2024060606 dddddd
design777859
 
Service-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipService-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadership
Yasuyoshi Minehisa
 
【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)
【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)
【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)
recruit9
 
kintone Café 山口 Vol.8 kintone×UiPath.pdf
kintone Café 山口 Vol.8 kintone×UiPath.pdfkintone Café 山口 Vol.8 kintone×UiPath.pdf
kintone Café 山口 Vol.8 kintone×UiPath.pdf
takashihashimoto14
 
株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)
株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)
株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)
Members_corp
 
20240606_Service Design Exercise_Visual Report_vol.1.pdf
20240606_Service Design Exercise_Visual Report_vol.1.pdf20240606_Service Design Exercise_Visual Report_vol.1.pdf
20240606_Service Design Exercise_Visual Report_vol.1.pdf
jun_suto
 
KGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPI
KGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPIKGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPI
KGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPI
Tsuyoshi Horigome
 
intra-mart Accel series 2024 Spring updates
intra-mart Accel series 2024 Spring updatesintra-mart Accel series 2024 Spring updates
intra-mart Accel series 2024 Spring updates
NTTDATA INTRAMART
 
MMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DX
MMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DXMMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DX
MMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DX
sakanotakashi
 
株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///
株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///
株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///
DAISUKE NAKAMURA
 
Temp agency_Value Core Consulting Co., Ltd.
Temp agency_Value Core Consulting Co., Ltd.Temp agency_Value Core Consulting Co., Ltd.
Temp agency_Value Core Consulting Co., Ltd.
dyasa
 

Recently uploaded (16)

【slideshare】オンライン二次健診サービス_20240607.pptx.pdf
【slideshare】オンライン二次健診サービス_20240607.pptx.pdf【slideshare】オンライン二次健診サービス_20240607.pptx.pdf
【slideshare】オンライン二次健診サービス_20240607.pptx.pdf
 
CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介
CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介
CFO組織の働き方を変える 経理業務変革プラットフォーム 「BlackLine」のご紹介
 
株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介
株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介
株式会社ROMS採用候補者用説明資料。候補者の方向け事業概要・沿革・カルチャーをご紹介
 
LabBase就職ご紹介資料_240605サービス概要説明資料240605.pdf
LabBase就職ご紹介資料_240605サービス概要説明資料240605.pdfLabBase就職ご紹介資料_240605サービス概要説明資料240605.pdf
LabBase就職ご紹介資料_240605サービス概要説明資料240605.pdf
 
研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案
研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案
研究エンパワープラットフォームを提供するLabBaseから理系採用成功に向けたご提案
 
smartcamp_RECRUIT_deck 2024060606 dddddd
smartcamp_RECRUIT_deck 2024060606 ddddddsmartcamp_RECRUIT_deck 2024060606 dddddd
smartcamp_RECRUIT_deck 2024060606 dddddd
 
Service-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipService-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadership
 
【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)
【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)
【公開用】株式会社VISIONARY JAPAN_エンジニアチーム 採用資料(ver2.1)
 
kintone Café 山口 Vol.8 kintone×UiPath.pdf
kintone Café 山口 Vol.8 kintone×UiPath.pdfkintone Café 山口 Vol.8 kintone×UiPath.pdf
kintone Café 山口 Vol.8 kintone×UiPath.pdf
 
株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)
株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)
株式会社メンバーズ「脱炭素アクション100」2023年度実施レポート(2024.6.6)
 
20240606_Service Design Exercise_Visual Report_vol.1.pdf
20240606_Service Design Exercise_Visual Report_vol.1.pdf20240606_Service Design Exercise_Visual Report_vol.1.pdf
20240606_Service Design Exercise_Visual Report_vol.1.pdf
 
KGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPI
KGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPIKGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPI
KGIとKPIについて(営業の目標設定とKPIの商談プロセス) About KGI and KPI
 
intra-mart Accel series 2024 Spring updates
intra-mart Accel series 2024 Spring updatesintra-mart Accel series 2024 Spring updates
intra-mart Accel series 2024 Spring updates
 
MMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DX
MMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DXMMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DX
MMOLHolging株式会社|BtoC、D2C事業グロース支援・インターナルブランディング、採用ブランディング、社員エンゲージメント向上DX
 
株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///
株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///
株式会社ジンザイベース/特定技能外国人紹介に関する提案資料/2024ver///
 
Temp agency_Value Core Consulting Co., Ltd.
Temp agency_Value Core Consulting Co., Ltd.Temp agency_Value Core Consulting Co., Ltd.
Temp agency_Value Core Consulting Co., Ltd.
 

フラットな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