sql >> データベース >  >> RDS >> Mysql

AJAXによって呼び出されたPHPファイルからSQLSELECTステートメントをどのようにエコーしますか?

    JSONとして返すAJAXを扱うとき、私が使用する1つのトリックは、出力バッファリングを利用することです。 JSONデータを台無しにするため、必要なものをエコーし​​たり出力したりすることはできません。たとえば、

    ob_start(); //turn on buffering at beginning of script.
    
    .... other code ...
    
    print_r($somevar);
    
    .... other code ...
    
    $debug = ob_get_clean();  //put output in a var
    $data['debug'] = $debug;
    
    header('Content-Type: application/json');
    echo json_encode($data); //echo JSON data.
    

    これは、スクリプトからの出力をJSONデータにラップして、形式が乱れないようにすることです。

    次に、JavaScript側でconsole.logを使用できます

    $.post(url, input, function(data){
       if(data.debug) console.log(data.debug);
    });
    

    console.log()を使用したデバッグに慣れていない場合 、通常はF12を押すことができます ほとんどのブラウザでデバッガを開きます。次に、そこで出力が「コンソール」に送信されます。 IE9には、console.log()に少し問題がありました。 思い出したとしても、遠くに行きたくないのです。

    注: 本番環境に移行するときは、コードにこのようなものを残さないように注意してください。この行をコメントアウトするのは非常に簡単です。

    //$data['debug'] = $debug;
    

    そして、デバッグ情報は本番環境では公開されません。これを自動的に行う方法は他にもありますが、ローカルで開発してからサーバーに公開するかどうかによって異なります。たとえば、$_SERVER['SERVER_ADDR'];で切り替えることができます これは::1になります または127.0.0.1 それがローカルであるとき。これにはいくつかの欠点があります。主に、サーバーアドレスはコマンドラインインターフェイス(CLI)から利用できません。したがって、通常は、サイトがどの「モード」にあるかを示すグローバル定数に関連付けます(共通のエントリポイント、通常はindex.phpに含まれます)。

    if(!defined('ENV_DEVELOPMENT')) define('ENV_DEVELOPMENT','DEVELOPMENT');
    
    if(!defined('ENV_PRODUCTION')) define('ENV_PRODUCTION','PRODUCTION');
    
    if(!defined('ENVIRONMENT')) define('ENVIRONMENT',ENV_DEVELOPMENT);
    //site is in Development mode, uncomment for production
    //if(!defined('ENVIRONMENT')) define('ENVIRONMENT',ENV_DEVELOPMENT);
    

    次に、それを確認するのは簡単なことです:

    if(ENVIRONMENT == ENV_PRODUCTION ) $data['debug'] = $debug;
    

    エラー報告の使用方法を知っている場合は、

    を使用してそれに結び付けることもできます。
     if(ini_get('display_errors') == 1) $data['debug'] = $debug;
    

    表示エラーがオンの場合にのみデバッグが表示されます。

    お役に立てば幸いです。

    更新

    コメントで言及したので、これはクラスにラップされた例です(これは簡略化されたバージョンなので、これをテストしませんでした)

    class LibAjax{
        public static function respond($callback, $options=0, $depth=32){
            $result = ['userdata' => [
                  'debug' => false,
                  'error' => false
            ]];
    
            ob_start();
    
             try{
    
                 if(!is_callable($callback)){
                    //I have better exception in mine, this is just more portable
                    throw new Exception('Callback is not callable');
                 }
    
                 $callback($result);
             }catch(\Exception $e){
                  //example 'Exception[code:401]'
                 $result['userdata']['error'] = get_class($e).'[code:'.$e->getCode().']';
                //if(ENVIRONMENT == ENV_DEVELOPMENT){
                //prevents leaking data in production
                    $result['userdata']['error'] .= ' '.$e->getMessage();
                    $result['userdata']['error'] .= PHP_EOL.$e->getTraceAsString();
                //}
             }
    
             $debug = '';
             for($i=0; $i < ob_get_level(); $i++){
                 //clear any nested output buffers
                 $debug .= ob_get_clean();
             }
             //if(ENVIRONMENT == ENV_DEVELPMENT){
                 //prevents leaking data in production
                  $result['userdata']['debug'] = $debug;
            //}
             header('Content-Type: application/json');
             echo self::jsonEncode($result, $options, $depth);
       }
    
       public static function jsonEncode($result, $options=0, $depth=32){
           $json = json_encode($result, $options, $depth);
           if(JSON_ERROR_NONE !== json_last_error()){
               //debug is not passed in this case, because you cannot be sure that, that was not what caused the error.  Such as non-valid UTF-8 in the debug string, depth limit, etc...
               $json = json_encode(['userdata' => [
                  'debug' => false,
                  'error' => json_last_error_msg()
               ]],$options);
           }
           return $json;
       }
    
    }
    

    次に、AJAX応答を作成するときは、次のようにラップします($ resultは参照によって渡されるため、returnを実行する必要はありません。例外の場合は、代わりに$resultを「リアルタイム」で更新します。完了時の)

    LibAjax::respond( function(&$result){
         $result['data'] = 'foo';
    });
    

    クロージャーに追加のデータを渡す必要がある場合は、useを使用できることを忘れないでください このようなステートメント。

    $otherdata = 'bar';
    
    LibAjax::respond( function(&$result) use($otherdata){
         $result['data'][] = 'foo';
         $result['data'][] = $otherdata;
    });
    

    サンドボックス

    これは、出力のキャッチを処理し、環境が正しい(コメントアウトされている)場合はデバッグに入れます。出力が本番環境でクライアントに送信されないように、何らかの保護を実装するようにしてください。十分に強調することはできません。また、例外をキャッチしてエラーを発生させます。また、ヘッダーとエンコーディングも処理します。

    これの大きな利点の1つは、JSONの構造が一貫していることです。これにより、(クライアント側で)if(data.userdata.error) 次に、バックエンドに例外があります。ヘッダー、JSONエンコーディングなどを微調整するための1つの場所を提供します...

    PHP7の1つの注意点は、(例外の代わりに)Throwableインターフェースを追加する必要があるか追加する必要があることです。 ErrorクラスとExceptionクラスをキャッチする場合、または2つのキャッチブロックを実行する場合。

    私がAJAXをたくさんやっていて、これをいつも書き直すことにうんざりしているとしましょう。私の実際のクラスはこれよりも広範囲ですが、それがその要点です。

    乾杯。

    UPDATE1

    これは通常、正しいヘッダーをブラウザに返さないためです。送信する場合(json_encodeを呼び出す直前)

    header('Content-Type: application/json');
    

    これにより、ブラウザはどのタイプのデータを取得しているかを知ることができます。ほとんどの人が忘れていることの1つは、Webではすべての応答がテキストで行われることです。画像やファイルのダウンロードやウェブページですら。それはすべて単なるテキストであり、そのテキストを特別なものにするのはContent-Typeです。 ブラウザがそれを認識していること。

    headerについて注意すべきことが1つあります ヘッダーを送信する前に何も出力できないということです。ただし、これは私が投稿したコードでうまく機能します。そのコードはすべての出力をキャプチャし、ヘッダーが送信された後に送信するからです。

    元のコードを更新してヘッダーを作成しました。後で投稿した、より複雑なクラスに追加しました。ただし、これを追加すると、JSONを手動で解析する必要がなくなります。

    最後に言及しなければならないのは、JSONが返されるかテキストが返されるかどうかを確認することです。出力バッファリングが開始される前にエラーが発生した場合でも、テキストを取得できます。

    これを行うには2つの方法があります。

    データが解析する必要のある文字列の場合

    $.post(url, {}, function(data){
        if( typeof data == 'string'){
            try{
                data = $.parseJSON(data);
            }catch(err){
                data = {userdata : {error : data}};
            }
        }
        if(data.userdata){
              if( data.userdata.error){
                   //...etc.
              }
        }
        //....
    }
    

    または、ヘッダーとその常にJSONがある場合は、少し単純です

    $.post(url, {}, function(data){
        if( typeof data == 'string'){
            data = {userdata : {error : data}};
        }
        if(data.userdata){
              if( data.userdata.error){
                   //...etc.
              }
        }
        //....
    }
    

    お役に立てば幸いです。

    UPDATE2

    このトピックは頻繁に取り上げられるため、上記のコードの修正バージョンをGitHubに配置しました。ここで見つけることができます。

    https://github.com/ArtisticPhoenix/MISC/blob/master /AjaxWrapper/AjaxWrapper.php



    1. MySQLgroup_concatとwhere句

    2. Postgres CSV COPY from/importはCSVヘッダーを尊重していません

    3. リンクサーバーのOLEDBプロバイダーMicrosoft.Jet.OLEDB.4.0のインスタンスを作成できませんnull

    4. uidにもかかわらずDjangopostsaveシグナルが2回呼び出される