14

私はPHPフレームワークを作成していますが、いくつか疑問があります...

フレームワークは、次の方法で URL を受け取ります。 http:/web.com/site/index

最初のパラメーターを使用してコントローラーをロードし ( site)、特定のアクションをロードします ( index)。

フレームワークをベース URL にインストールした場合は問題なく動作しますが、次のようなサブフォルダーにインストールした場合: http://web.com/mysubfolder/controller/action

私のスクリプトはそれを controller =mysubfolderおよび action =として解析しcontrollerます。

それ以上のサブフォルダーがある場合、結果は最悪になります。

これは私のルートコードです:

Class Route
{
    private $_htaccess = TRUE;
    private $_suffix = ".jsp";

    public function params()
    {
        $url='';

        //nombre del directorio actual del script ejecutandose.
        //basename(dirname($_SERVER['SCRIPT_FILENAME']));

        if($this->_htaccess !== FALSE):
            //no está funcionando bien si está en un subdirectorio web, por ej stynat.dyndns.org/subdir/
            // muestra el "subdir" como primer parámetro
            $url = $_SERVER['REQUEST_URI'];
            if(isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING'])):
                $url = str_replace("?" . $_SERVER['QUERY_STRING'], '',$url);
            endif;
        else:
            if(isset($_SERVER['PATH_INFO'])):
                $url = $_SERVER['PATH_INFO'];
            endif;
        endif;

        $url = explode('/',preg_replace('/^(\/)/','',$url));
        var_dump($url);

        var_dump($_GET);

    }
}

ご協力いただきありがとうございます。

4

12 に答える 12

2

独自のフレームワークを作成している場合でも、このルーティングコンポーネントのように、堅牢で十分にテストされ、文書化されたコンポーネントを再利用しない理由はありません。

PHP の依存関係管理の標準となったComposerを使用するだけで問題ありません。必要な数のコンポーネントをスタックに追加します。

ここには、独自のフレームワークを作成する方法に関する必読 のガイドがあります。

于 2012-11-17T16:18:42.497 に答える
2

基本パスがありません。ルーティング スクリプトは、検出されたパターンまたはルートを検出するときにどこから開始する必要があります。

擬似コード:

 //set the base URI
$base_uri = '/base';
//remove the base URI from the original uri. You can also REGEX or string match against it if you want
$route_uri = str_replace($base_uri,'',$uri);
//perform route matching $route_uri, in your code a simple explode

$url = explode('/',preg_replace('/^(\/)/','',$route_uri));

同じハーネス (index.php) を使用している限り、.htaccess の RewriteBase の有無にかかわらず、これを使用できます。

さらに、preg_match や preg_match_all などの正規表現関数を使用して、ルート マッチ手順を改善できます。一致するパターンを定義し、結果が一致する文字列の配列になるようにします - http://php.net/manual/en/function.preg-match.phpを参照してください。

于 2012-11-16T10:47:45.197 に答える
2

はい、私はそれを修正する方法を知っていると思います。

(免責事項:あなたがこれのほとんどを知っていることは知っていますが、いくつかの落とし穴を知らないかもしれない他の人のためにすべてを説明するつもりです)

PATH_INFO と .htaccess の使用

次のようなパスに移動した場合、phpにはトリックがあります。

http://web.com/mysubfolder/index.php/controller/action

$_SERVER['PATH_INFO']変数に「/controller/action」を取得します

次に、.htaccess ファイル (または同等のファイル) を取得して、php スクリプトに現在のフォルダーの深さを伝える必要があります。

これを行うには、.htaccess ファイルを「mysubfolder」に入れます。

mysubfolder
    .htaccess
    index.php

.htaccess には以下が含まれている必要があります。

RewriteEngine on

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

# otherwise forward it to index.php
RewriteRule (.*) index.php/$1

(参照としてyii フレームワークのマニュアルを使用しました。また、 html5 ボイラープレートの使用をお勧めします)

基本的に、URL の特定のポイントですべてを index.php にリダイレクトするように設定します。

今あなたが訪問した場合:http://web.com/mysubfolder/index.php/controller/action

これで、正しいパス「/controller/action」を取得できます$_SERVER['PATH_INFO']

http://web.com/mysubfolder/パスが mysubfolder/index.php を要求するため、.htaccess ファイルは書き換えを無視するため、http ://web.com/mysubfolder/ にアクセスしても何の価値もありませんこれは実際に存在し、拒否されます ありがとうございます。RewriteCond %{REQUEST_FILENAME} !-f

ifset関数

これには、この非常に便利な関数を使用できますifsetor(どこで入手したか覚えていません)。

function ifsetor(&$variable, $default = null) {
    return isset($variable)? $variable: $default;
}

存在するかどうかわからない変数への参照を取得し、存在しない場合は通知やエラーをスローせずにデフォルトを提供します。

これを使用して PATH_INFO 変数を安全に取得できます

index.php で

function ifsetor(&$variable, $default = null) {
    return isset($variable)? $variable: $default;
}
$path = ifsetor($_SERVER['PATH_INFO'],'/');
var_dump($path);

php 5.4には、通知を気にしない場合に使用できるこの新しい短い3進形式もあります(私は気にします)

$path = $_SERVER['PATH_INFO']?:'/';

QUERY_STRING の処理

技術的には、URL を取得していません。これは単なるパス部分であり、たとえば次の場合に query_string は含まれません。

http://web.com/mysubfolder/index.php/test?param=val

$path 変数で「/test」のみを取得します。クエリ文字列を取得するには、$_SERVER['QUERY_STRING']変数を使用します

index.php

function ifsetor(&$variable, $default = null) {
    return isset($variable)? $variable: $default;
}
$path = ifsetor($_SERVER['PATH_INFO'],'/');
$fullpath = ($_SERVER['QUERY_STRING'])? $path.'?'.$_SERVER['QUERY_STRING']:$path;
var_dump($fullpath);

しかし、それはあなたのニーズに依存するかもしれません

$_SERVER['QUERY_STRING'] 対 $_GET

また、変数は、クエリ文字列から重複したパラメーターを保持するため、変数とは異なることに注意してください。次に例を示します$_SERVER['QUERY_STRING']$_GET$_REQUEST

このページにアクセスする

http://web.com/mysubfolder/controller/action?foo=1&foo=2&foo=3

$_SERVER['QUERY_STRING']あなたに次のようなものを与えるつもりなら

?foo=1&foo=2&foo=3

変数は次の$_GETような配列になります。

array(
    'foo'=>'3'
);

.htaccess がない場合

SCRIPT_NAME を有利に使用してみることができます

list($url) = explode('?',$_SERVER['REQUEST_URI']);
list($basepath) = explode('index.php',$_SERVER['SCRIPT_NAME']);
$url = substr($url,strlen($basepath));

あなたが私のようなものを爆破するのが好きなら:)

あなたの場合

Class Route
{
private $_htaccess = TRUE;
private $_suffix = ".jsp";

public function params()
{
    $url='';

    //nombre del directorio actual del script ejecutandose.
    //basename(dirname($_SERVER['SCRIPT_FILENAME']));

    if($this->_htaccess !== FALSE):
        //no está funcionando bien si está en un subdirectorio web, por ej stynat.dyndns.org/subdir/
        // muestra el "subdir" como primer parámetro
        list($url) = explode('?',$_SERVER['REQUEST_URI']);
        $basepath = dirname($_SERVER['SCRIPT_NAME']);
        $basepath = ($basepath==='/')? $basepath: $basepath.'/';
        $url = substr($url,strlen($basepath));
    else:
        if(isset($_SERVER['PATH_INFO'])):
            $url = $_SERVER['PATH_INFO'];
            $url = preg_replace('|^/|','',$url);
        endif;
    endif;

    $url = explode('/',$url);
    var_dump($url);

    var_dump($_GET);


}
}

これが役立つことを願っています

PSお返事遅くなってすみません(;_;)

于 2013-06-06T19:47:17.230 に答える
0

ある時点で、$ _ SERVER ['HTTP_HOST']を確認する必要があります。プログラマー/ユーザーによって定義された構成変数は、アプリが配置されているサブフォルダーを示し、関心のない部分をから削除します。 URLの残りの部分。

いくつかのヒントについては、codeigniterformusのこのフォーラム投稿を確認してください。

CodeIgniterは、別の異なる方法を使用して、コントローラー/メソッドを内部でルーティングします。値によってルーティングを行い$_SERVER['PATH_INFO']ます。次のようなURLを使用しますmyapp.com/index.php/controller/method

uriにindex.phpが表示されないようにするには、Apacheの書き換えルールに依存する必要がありますが、それでもCIは優れたソリューションだと思います。インデックスファイルの場所がわかれば、解析の煩わしさをすべて回避できます。 URL。

于 2012-09-14T14:51:20.937 に答える
0

アプリケーション構成スクリプト内に、アプリケーションが実行されるパスに設定される変数を配置します。

別の方法は、そのパスを動的に設定することです。

部品前

$url = explode('/',preg_replace('/^(\/)/','',$url));

$url事前定義されたアプリケーション パスを使用して、文字列から場所 (サブフォルダー) パスを取り除きます。

于 2012-09-25T13:10:52.030 に答える
0

ディレクトリを作成/myBaseDirectory/publicし、そこにファイルを配置しますindex.php
これが機能するのは、Apache がこのディレクトリをベース ディレクトリのように認識するためです。

于 2015-12-23T12:33:41.360 に答える
0

あなたが何をしているのかを正しく理解している場合、1つの解決策は、あなたがしていることを続けることですが、メインルーティングスクリプトのパスも取得することです(たとえば、 realpath() を使用して)。

最後のフォルダー (またはその前のフォルダーなど) が最初の URL 項目 (または別のセクション) と一致する場合は、それを無視して次の項目に進みます。

ちょうど私の2セント:-)。

于 2012-09-22T22:43:03.763 に答える
0

これは私がloader.phpを実装した方法です

   <?php
/*@author arun ak
auto load controller class and function from url*/
class loader
{
    private $request;
    private $className;
    private $funcName;

    function __construct($folder    = array())
    {   
        $parse_res  = parse_url($this->createUrl());
        if(!empty($folder) && trim($folder['path'],DIRECTORY_SEPARATOR)!='')
         {
            $temp_path  = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
            $folder_path    = explode(DIRECTORY_SEPARATOR,trim($folder['path'],DIRECTORY_SEPARATOR));
            $temp_path      = array_diff($temp_path,$folder_path);

                if(empty($temp_path))
                {
                    $temp_path =    '';
                }
         }else
         {
            if(trim($parse_res['path'],DIRECTORY_SEPARATOR)!='')
            {
             $temp_path = explode(DIRECTORY_SEPARATOR,trim($parse_res['path'],DIRECTORY_SEPARATOR));
            }
                 else
             $temp_path ='';
         }
        if(is_array($temp_path))
        {   
            if(count($temp_path) ==1)
            {
                array_push($temp_path,'index');
            }
            foreach($temp_path as $pathname)
            {   
                $this->request .= $pathname.':';
            }
        }
        else $this->request = 'index'.':'.'index';

    }

 private function createUrl()
 {  
    $pageURL  = (@$_SERVER["HTTPS"] == "on") ? "https://" : "http://";
    $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
    return $pageURL;
 }
 public function autolLoad()
 {
    if($this->request) 
    {   
        $parsedPath = explode(':',rtrim($this->request,':'));
        if(is_file(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php'))
        {
            include_once(APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'_controller'.'.php');
            if(class_exists($parsedPath[0].'_controller'))
            {
                $class  = $parsedPath[0].'_controller';
                $obj    = new $class();
                //$config       = new config('localhost','Winkstore','nCdyQyEdqDbBFpay','mawinkcms');
                //$connect  =  connectdb::getinstance();
                //$connect->setConfig($config);
                //$connection_obj = $connect->connect();
                //$db               = $connect->getconnection();//mysql link object
                //$obj->setDb($db);
                $method = $parsedPath[1];
                if(method_exists ($obj ,$parsedPath[1] ))
                {
                    $obj->$method();
                }else die('class method '.$method.' not defined');

            }else die('class '.$parsedPath[0]. ' has not been defined' );

        } else die('controller not found plz define one b4 u proceed'.APPLICATION_PATH.DIRECTORY_SEPARATOR.'controllers'.DIRECTORY_SEPARATOR.$parsedPath[0].'.php');

     }else{ die('oops request not set,i know tis is not the correct way to error :)'); }
 }

}

今私のインデックスファイルに

//include_once('config.php');
include_once('connectdb.php');
require_once('../../../includes/db_connect.php');
include_once('view.php');
include_once('abstractController.php');
include_once('controller.php');
include_once('loader.php');
$loader = new loader(array('path'=>DIRECTORY_SEPARATOR.'magsonwink'.DIRECTORY_SEPARATOR.'modules'.DIRECTORY_SEPARATOR.'admin'.DIRECTORY_SEPARATOR.'atom'.DIRECTORY_SEPARATOR));
$loader->autolLoad();

モジュールの概念は使用していません。コントローラーのアクションとビューのみがレンダリングされます。

于 2012-09-28T08:20:24.193 に答える
0

「車輪の再発明は間違っている」という主張は忘れてください。彼らは私たちの車輪を使う必要はありません。私は少し前に同じ道を歩いていて、私が得たものにとても感謝しています.

あなたの特定の問題に対する答えになると、それも直面した場合、非常に簡単な解決策があります。ルートフォルダーの.htaccessの改行です...

以下の行をルート .htaccess ファイルに追加するだけです。(サブフォルダーが「サブフォルダー」の場合)

RewriteRule subfolder/ - [L]

これにより、このフォルダーはディレクティブの書き換えから切り離されます

この方法を使用すると、フレームワークのインスタンスをいくつでもインストールできます。ただし、これをフレームワーク駆動にしたい場合は、フレームワーク内で .htaccess を作成/変更する必要があります。

于 2012-11-24T01:19:33.043 に答える
0

私は OOP を使用しませんが、サブディレクトリにいるかどうかを動的に検出する方法の一部を示すことができます。短くしすぎて、すべてのコードを投稿するのではなく、その一部のみを説明します。

そこで、.htaccessすべてのリクエストを redirect.php に送信することから始め、そこで$_SERVER['REQUEST_URI']変数をつなぎ合わせます。正規表現を使用して、どの部分をキーにし、何を値にするかを決定し (0-9 で始まるものを値として割り当て、az で始まるものをキーとして割り当てることによってこれを行います)、 array を作成し$GET[]ます。

次に、redirect.php へのパスを確認し、それを配列と比較して$GET、実際の URL の開始位置を決定します。この場合、どのキーがコントローラーであるかを判断します。次のようになります。

$controller = keyname($GET, count(explode('/', dirname($_SERVER['SCRIPT_NAME']))));

これで、URL の最初の部分ができました。関数は次のkeyname()ようになります。

/*************************************
 *  get key name from array position
 *************************************/
function keyname ($arr, $pos)
{
    $pos--;
    if ( ($pos < 0) || ( $pos >= count($arr) ) )
          return "";  // set this any way you like

    reset($arr);
    for($i = 0;$i < $pos; $i++) next($arr);

    return key($arr);
}

リンクを正しく指すようにするには、次のfixpath()ような関数を使用します。

print '<a href="'.fixpath('/admin/logout').'">link</a>';

そして、これはその関数がどのように見えるかです:

/*************************************
 *   relative to absolute path
 *************************************/
function fixpath ($path)
{
    $root = dirname($_SERVER['SCRIPT_NAME']);
    if ($root == "\\" || $root == ".") {
        $root = "";
    }
    $newpath = explode('/', $path);
    $newpath[0] .= $root;
    return implode('/', $newpath);    
}

それが助けになり、あなたにインスピレーションを与えることができることを願っています。

于 2012-11-19T23:06:14.553 に答える
0

あなたはあなたがhtaccess正しく持っていると確信していますか?

フレームワークを に配置している場合は、 inファイルを からにsubfolder変更する必要があると思います。次のようになります。RewriteBasehtaccess//subfolder/

# on root
RewriteBase /

#on subfolder
RewriteBase /subfolder/

あなたの場合、それは私が不思議に思うことができる唯一のものです...

于 2012-10-02T09:05:31.090 に答える
-1

基本的に、最初のスラッシュの後に URL 文字列を取得し、それを配列に分解します (区切り記号として「/」を使用します)。

次に、要素を慎重にarray_shiftし、変数として保存します

item 0: controller
item 1: the action / method in that controller
item 2 thru n: the remaining array is your params
于 2012-08-02T23:21:24.043 に答える