ホームページ > バックエンド開発 > PHPチュートリアル > PHP MVCフレームワークから開発(1)

PHP MVCフレームワークから開発(1)

WBOY
リリース: 2016-06-13 13:14:56
オリジナル
779 人が閲覧しました

独自の PHP MVC フレームワークを開発する (1)

このチュートリアルは、John Squibb の『Build a PHP MVC Framework in an Hour』から翻訳されたものですが、元のアドレス: http://johnsquibb.com/tutorials

このチュートリアルでは、誰もが MVC モードを使用した PHP アプリケーション開発の基本概念を習得できます。このチュートリアルは 3 つの部分に分かれており、これは最初の部分です。

現在、誰もが使用できる人気のフレームワークが数多く市場に出ていますが、mvc モデルを使用すると、アプリケーションの開発に費やす時間を大幅に削減でき、プロジェクトのソース コードをより適切に整理できます。 、その中には、他のプロジェクトでも使用できるモジュールもあります。ここで、簡単な MVC フレームワークの書き方を教えたいと思います。このプロジェクトは非常にシンプルで軽量であるため、ベストプラクティスではない可能性があり、安全でもありません。実際のアプリケーションでは改善する必要があります。

使用されるテクノロジー: PHP、オブジェクト指向開発手法。

開始

まず、Web サイトのルート ディレクトリに 3 つのフォルダーを作成します

    モデル
  • ビュー
  • コントローラー

次に、ルート ディレクトリに新しいファイルを作成します:

    index.php

プロジェクト構造は次のようになります

§ Web サイトのルート ディレクトリ

§index.php

§ モデル/

§ ビュー/

§ コントローラー/


index.php は Web アプリケーション全体のエントリ ポイントであり、すべてのユーザー リクエストはそれを通過します。ユーザーリクエストをコントローラーフォルダーに保存されている対応するコントローラーにディスパッチするためのコードを作成します。その後、次のメソッドを使用してページジャンプを実現できます:

    http://あなたのドメイン名.com/index.php?page1
  • http://あなたのドメイン名.com/index.php?page2
  • http://youドメイン名 .com/index.php?page3
フロントエンドコントローラーのindex.phpを設定します

まず、アプリケーション全体でアクセスできるように、index.php で Web サイトのルート ディレクトリと Web サイトのドメイン名を定義します。

<?php

//应用的根目录就是index.php的父目录
define("SERVER_ROOT", dirname(__FILE__));

//你的域名.comm 是你的服务器域名
define('SITE_ROOT' , 'http://你的域名.com');
ログイン後にコピー

任意の PHP ファイルで Web サイトのルート ディレクトリを定義すると、他のディレクトリにある PHP ファイルを簡単に参照できます。これは、index.php がエントリ ファイルであるため、アプリケーション全体でその中で定義された PHP ファイルにアクセスできるためです。変数。

ルーターの router.php を設定します (ユーザーリクエストを対応するコントローラーに転送します)

controllers ディレクトリに「router.php」という名前の新しいファイルを作成します。このファイルはすべてのページリクエストを処理するために使用されます。家のルーターが、家のすべてのコンピューターにインターネットをルーティングする役割を果たしていると想像してください。 router.php ファイルは、受信ページリクエストをindex.phpに受け取り、そのリクエストを別のコントローラにディスパッチします。

route.php のコード:

<?php

//获取所有请求
$request = $_SERVER['QUERY_STRING'];
ログイン後にコピー
このコードは、アプリケーションに渡されるリクエスト パラメーターを取得します。 QUERY_STRING は、「?」以降のすべての文字列です。

    http://yourdomain.com/index.php?page1
上記のアドレスは、コード内で「page1&action=login」を取得します。page1 を次のパラメーターから分離するには、次のコードをroute.phpに追加する必要があります。

次に、index.php に Route.php を導入する必要があります。

//解析$request变量,得到用户请求的页面(page1)和其它GET变量(&分隔的变量)如一个请求http://你的域名.com/index.php?page1&article=buildawebsite,则被解析为array("page1", "article=buildawebsite")
$parsed = explode('&' , $request);

//用户请求的页面,如上面的page1,为$parsed第一个变量,shift之后,数组为array("article=buildawebsite")
$page = array_shift($parsed);

//剩下的为GET变量,把它们解析出来
$getVars = array();
foreach ($parsed as $argument)
{
    //用"="分隔字符串,左边为变量,右边为值
    list($variable , $value) = split('=' , $argument);
    $getVars[$variable] = $value;
}

//这是测试语句,一会儿会删除
print "The page your requested is '$page'";
print '<br/>';
$vars = print_r($getVars, TRUE);
print "The following GET vars were passed to the page:<pre class="brush:php;toolbar:false">".$vars."
";
ログイン後にコピー
すべてがうまくいけば、ブラウザを開いて次のように入力できます:

<?php
/**
 * 定义文档路径
 */
define("SERVER_ROOT", dirname(__FILE__));
define('SITE_ROOT' , 'http://你的域名.com');
/** 
 * 引入router.php 
 */
 require_once(SERVER_ROOT . '/controllers/' . 'router.php');
?>
ログイン後にコピー


http://yourdomain.com/index.php?news&article=howtobuildaframework

次の出力が表示されます

上記の出力がない場合は、サーバー構成が正しいかどうかを確認し、コードにエラーがないかどうかを確認してください。

The page you requested is 'news'
	The following GET vars were passed to the page:

	Array
	(
		[article] => howtobuildaframework
	)
	
ログイン後にコピー

次に、上記の情報を直接出力する代わりに、router.php がページを生成できるように、Web サイトにページを追加しましょう。


コントローラーの作成

コントローラーフォルダーに「news.php」という名前の新しいファイルを作成し、次のクラスを定義します:

<?php
/**
 * 这个文件处理文章的查询,并提供文章
 */
class News_Controller
{
    /**
     * $template变量会保存与此控制器相关的"view(视图)"的文件名,不包括.php后缀 
     */
    public $template = 'news';

    /**
     * 此方法为route.php默认调用
     * 
     * @param array $getVars 传入到index.php的GET变量数组
     */
    public function main(array $getVars)
    {
        //测试代码,以后会删除
        print "We are in news!";
        print '<br/>';
        $vars = print_r($getVars, TRUE);
        print 
        (
            "The following GET vars were passed to this controller:" .
            "<pre class="brush:php;toolbar:false">".$vars."
" ); } }
ログイン後にコピー
route.php のテスト コードをコピーし、それを main 関数に配置したことに注意してください。次に、route.php のコードを変更しましょう:

<?php
/**
 * 此文件会把所有的传入参数分派到相应的控制器中
 */

//获取请求参数
$request = $_SERVER['QUERY_STRING'];

//解析请求页面和其它GET变量
$parsed = explode('&' , $request);

//页面是第一个元素
$page = array_shift($parsed);

//剩余的为GET变量,也把它们解析出来
$getVars = array();
foreach ($parsed as $argument)
{
    //split GET vars along '=' symbol to separate variable, values
    list($variable , $value) = split('=' , $argument);
    $getVars[$variable] = $value;
}

//构成控制器文件路径
$target = SERVER_ROOT . '/controllers/' . $page . '.php';

//引入目标文件
if (file_exists($target))
{
    include_once($target);

    //修改page变量,以符合命名规范(如$page="news",我们的约定是首字母大写,控制器的话就在后面加上“<strong>_Controller”</strong>,即News_Controller)
    $class = ucfirst($page) . '_Controller';

    //初始化对应的类
    if (class_exists($class))
    {
        $controller = new $class;
    }
    else
    {
        //类的命名正确吗?
        die('class does not exist!');
    }
}
else
{
    //不能在controllers找到此文件
    die('page does not exist!');
}

//一但初始化了控制器,就调用它的默认函数main();
//把get变量传给它
$controller->main($getVars);?>
ログイン後にコピー
http://yourdomain.com/index.php?news&article=howtobuildaframework に再度アクセスすると、News_Controller から出力された情報が表示されます。現在、エラーを処理するために die() を使用していることに注意してください。他のより適切なエラー処理で制御できますが、現時点では http://yourdomain.com/index.php などの他のページにアクセスしてみてください。 ?books の場合、「ページが存在しません!」というエラーが表示されます。 News_Controller を完成させるモデルを作成します。読者が読むためのニュース スニペットがいくつかあると仮定すると、News_Controller コントローラーがモデルを呼び出して、関連するニュース スニペットがデータベースに保存されているかファイルに保存されているかに関係なく、それらを取得する必要があります。次のコードを使用して、モデル フォルダー「news.php」に新しいファイルを作成します:



<?php
/**
 * 新闻模型为新闻控制器做复杂的后台操作
 */
class News_Model
{
    public function __construct()
    {
        print 'I am the news model';
    }
}
ログイン後にコピー

现在,我们需要对新闻控制器稍做一些更改,打开controllers里的news.php,把News_Controller类的main函数的代码改为如下,这样,我们就会在“News_Model”初始化时,看到打印在屏幕上的信息:

public function main(array $getVars)
{
    $newsModel = new News_Model;
}
ログイン後にコピー
现在刷新页面,你会看到:

Fatal error: Class 'News_Model' not found in /var/www/mvc/controllers/news.php on line xx
	
ログイン後にコピー
等一下,这不是我们想要的结果!我们正试图去加载一个不存在的类。那么原因就是我们并没有引入/models/news.php文件。为了解决这个问题,让们重新来看一下router.php,然后在它的顶部添加一些代码:

//当类初始化时,自动引入相关文件
function __autoload($className)
{
    //解析文件名,得到文件的存放路径,如News_Model表示存放在models文件夹里的news.php(这里是作者的命名约定)
    list($filename , $suffix) = split('_' , $className);

    //构成文件路径
    $file = SERVER_ROOT . '/models/' . strtolower($filename) . '.php';

    //获取文件
    if (file_exists($file))
    {
        //引入文件
        include_once($file);        
    }
    else
    {
        //文件不存在
        die("File '$filename' containing class '$className' not found.");    
    }
}
ログイン後にコピー
这个函数重载了PHP内置的autoload函数。当我们试图去初始化一个不存在的类时,这个‘魔术方法’允许我们拦截php所执行的动作。通过使用__autoload函数,我们能够告诉php寻找包含此类的文件的位置。假设你遵循了这篇文章中类和文件名的命名约定,那么每当你初始化一个类时,你就不必手动去引入包含此类的文件了!

保存route.php,再刷新一次浏览器,你会看到:

I am the news model
ログイン後にコピー

让我们在新闻模型类里定义一些函数来提供文章。现在,我们只简单的定义了一个数组,并保存一些文章,然后提供一个函数,让控制器从中根据标题获取一篇文章。修改models/news.php:


<?php
/**
 * 新闻模型为新闻控制器做复杂的后台操作
 *
 */
class News_Model
{
    /**
     * 文章数组. key为文章标题, 值为相应的
     * 文章。
     */
    private $articles = array
    (
        //文章1
        'new' => array
        (
            'title' => 'New Website' ,
            'content' => 'Welcome to the site! We are glad to have you here.'
        )
        ,
        //2
        'mvc' => array
        (
            'title' => 'PHP MVC Frameworks are Awesome!' ,
            'content' => 'It really is very easy. Take it from us!'
        )
        ,
        //3
        'test' => array
        (
            'title' => 'Testing' ,
            'content' => 'This is just a measly test article.'
        )
    );

    public function __construct()
    {
    }

    /**
     * 根据标题获取文章
     * 
     * @param string $articleName
     * 
     * @return array $article
     */
    public function get_article($articleName)
    {
        //从数组中获取文章
        $article = $this->articles[$articleName];
    
        return $article;
    }

}?>

ログイン後にコピー
现在修改controllers/news.php中的main函数:

public function main(array $getVars)
{
    $newsModel = new News_Model;
    
    //获取一篇文章
    $article = $newsModel->get_article('test');
    
    print_r($article);
}
ログイン後にコピー
现在我们并没有考虑过滤用户输入的问题,因为我们现在只是为了尽快让大家掌握PHP MVC的基本内容,所以我们现在不必太关心这些。

如果访问如下网址:

§ http://yourdomain.com/mvc/index.php?news&article=test

你会看到如下输出:

Array ( [title] => Testing [content] => This is just a measly test article. ) 
ログイン後にコピー

创建视图(VIEW

现在我们已经有控制器和模型了,只差一个视图。视图是表现层,它是你的应用中,与用户接触最频繁的部分。之前我提到过,视图是提供与业务逻辑分离的用户接口,有很多方法可以做到这个。你可以使用模板引擎Smarty或其它类似的。你也可以写一个自己的模板引擎,但那肯定是相当艰巨的任务。最后,你可以使用原生php视图。

对于目前来说,php视图足够了。这个就像以前php与html代码混合编程一样,但是有一点不同是,我们的业务逻辑已经和视图分离了。看一下如下代码:

<html>
    <head></head>
    <body>
        <h1>Welcome to Our Website!</h1>
        <hr/>
        <h2>News</h2>
        <h4><?=$data['title'];?></h4>
        <p><?=$data['content'];?></p>
    </body>
</html>
ログイン後にコピー

注意,嵌入的php标签利用了PHP 快捷操作符。这样就能够把我们的内容直接输出到HTML里面了。在views文件夹里新建一个文件“news.php”,把上述代码拷贝进来。现在我们有了视图文件,但是我们需要一个与视图交互的方法。在models文件夹里新建一个文件“view.php”,添加如下代码:


<?php
/**
 * 在我们的MVC框架中,处理视图的功能
 */
class View_Model
{
    /**
     * 保存赋给视图模板的变量
     */
    private $data = array();

    /**
     * 保存视图渲染状态
     */
    private $render = FALSE;

    /**
     * 加载一个视图模板
     */
    public function __construct($template)
    {
        //构成完整文件路径
        $file = SERVER_ROOT . '/views/' . strtolower($template) . '.php';
    
        if (file_exists($file))
        {
            /**
             * 当模型对象销毁时才能渲染视图
             * 如果现在就渲染视图,那么我们就不能给视图模板赋予变量
             * 所以此处先保存要渲染的视图文件路径
             */
            $this->render = $file;
        }        
    }

    /**
     * 接受从控制器赋予的变量,并保存在data数组中
     * 
     * @param $variable
     * @param $value
     */
    public function assign($variable , $value)
    {
        $this->data[$variable] = $value;
    }

    public function __destruct()
    {
        //把类中的data数组变为该函数的局部变量,以方便在视图模板中使用
        $data = $this->data;
    
        //渲染视图
        include($this->render);
    }
}
ログイン後にコピー

现在,最后一件要做的事就是从News_Controller里加载视图。修改controllers/news.php:

<?php
/*
 *这个文件处理文章的查询,并产生新闻文章* 
 */
 class News_Controller{ 
    /** 
     * $template变量会保存与此控制器相关的"view(视图)"的文件名,不包括.php后缀
     * 
     */
     public $template = 'news'; 
    /**
     * 此方法为route.php默认调用
     * 
     * @param array $getVars 传入到index.php的GET变量数组 
     */ 
     public function main(array $getVars) {
         $newsModel = new News_Model; 
         //获取一片文章 
         $article = $newsModel->get_article($getVars['article']); 
         //创建一个视图,并传入该控制器的template变量 
         $view = new View_Model($this->template); 
         //把文章数据赋给视图模板 
         $view->assign('title' , $article['title']); 
         $view->assign('content' , $article['content']); 
     }
}
?>
ログイン後にコピー


再加载页面,你就能够看到你的视图模板中的变量,已经被正确的替换掉了。好了,你的简单的MVC框架已经搭建好了,下面我会继续讲《开发自己PHP MVC框架(二)》
関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート