ホームページ >バックエンド開発 >PHPチュートリアル >中国の有名CMS:PHPCMS サイト全体のコード解析解説

中国の有名CMS:PHPCMS サイト全体のコード解析解説

WBOY
WBOYオリジナル
2016-06-13 13:25:57834ブラウズ

中国の有名CMS:PHPCMS サイト全体のコード解析解説

国内有名CMS:PHPCMSサイト全体のコード解析解説

2010-05-11 11:28:00|? カテゴリ: ウェブサイト構築 |? タグ: |フォント サイズ 大、中、小 購読

元の投稿アドレス: http://www.phpchina.com/bbs/thread-47107-1-1.html

著者: ニー・シュエハン

今日から、時間ができたらすぐに PHPCMS サイト全体のコードを詳細に分析します。目的は非常に簡単です。

。 ありがとうございます。コードの説明と分析はすべて私の知識に基づいて説明しています。間違っている場合は修正も歓迎します。よろしくお願いします。
皆さんも応援していただければ幸いです?

まず、PHPCMS のヘッダープログラムファイルについて説明します: include/common.inc.php?? このファイルは、プログラム起動のためのコアファイルです。 引用:

???
??? /**

??? コードの説明と分析: Ni Xuehan 2007-12-20

???*/

??? $mtime =explode(' ', microtime()); ??? $phpcms_starttime = $mtime[1] + $mtime[0];

??? /**

??? スクリプトの実行が開始される時刻を計算します。非常に一般的な書き方です。最終的な決着はまだプログラムの終わりにあります。それについて話したので今から伝えます。

???*/

??? unset($LANG, $_REQUEST, $HTTP_ENV_VARS, $HTTP_POST_VARS, $HTTP_GET_VARS, $HTTP_POST_FILES, $HTTP_COOKIE_VARS);

??? /**

???$HTTP_ENV_VARS $HTTP_POST_VARS グローバル変数を NULL に設定しますか? php4.1.0 以降はデフォルトで $_POST に置き換えられるためです。設定を解除すると、プログラムが下位バージョンで実行できなくなり、セキュリティ上の問題が発生する可能性があります。たとえば、変数注入

???*/

??? set_magic_quotes_runtime(0);

??? //地球上の誰もが知っています。データベースへの文字チャネリングをオフにして、たとえば、私の名前は on'x ですか? ???define('IN_PHPCMS', TRUE);

??? /**

??? プログラムエントリーマーク。なぜこれが必要なのですか?コミュニティに入るときと同じように、警備員は必ず、正面玄関から入ったことを証明するために署名するか、鳥のタグを吊るすように求めます。

???あなたのfan*qiangが侵入して物を盗んだり、損害を与えたりするのを防ぐため。このエントリーマークにもこの機能があります。 ここでは定数 IN_PHPCMS を TRUE として定義し、他のプログラム ファイルでこのマークを確認します。存在しない場合、または真実でない場合は、

??? となると、基本的には泥棒であることは間違いありません。 ファン*チャンと一緒に入る人もいるかもしれません。しかし、どうしてプログラムがこれほどファン*チャンになるのでしょうか? php.ini ファイルでallow_url_fopen オプションが有効になっている限り、include() には URL アドレスを含めることができます。パスワードを含む PHP ファイルがある場合は、このことを考えてください。他の人のためにそれを含める場合。怖いですか?

???*/

???define('PHPCMS_ROOT', str_replace("\", '/', substr(dirname(__FILE__), 0, -8)));

??? /**

???プログラム製品のクロスプラットフォーム用。 PHPCMS_ROOT 定数として定義されたプログラムのインストール ディレクトリ パスを自動的に取得します。将来のプログラムの使用に便利です。皆さんもこれを行うことをお勧めします

???*/

??? PHPCMS_ROOT が必要です。'/include/global.func.php' ?

??? /**

??? グローバル関数 global.func.php ファイルが含まれています。プログラム内でグローバルに使用する必要がある関数がいくつかあることがわかります。 ? 定数 PHPCMS_ROOT はすでに有効です。 このようにして、プログラムは 2 次ディレクトリにリリースされます。サイトのルート ディレクトリ パスを手動で変更する必要はありません。

??? 自分で理解してください。 。 。 。 。

???*/

??? $search_arr = array("/ Union /i","/ select /i","/ update /i","/ outfile /i","/ または /i");

??? /**

??? ("/union /i") これが通常の書き方ですか?通常のルールがわからない場合は、Baidu でチュートリアルを見つけて学ぶことができます。 ここでは詳細には触れません

???*/

??? $replace_arr = array(' 結合 '、' 選択 '、' 更新 '、' 出力ファイル '、' または ');

??? /**

???意味は非常に明確です。 Union: 2 つの SQL ステートメントを結合します。 outfile: 主にデータベース データを他のメディアにエクスポートするために使用されます。

??? なぜこれら 2 つの変数を定義する必要があるのでしょうか? global.func.php ファイル (すでに読み込まれています) には、strip_sql() 関数がありますので、見てみることができます。

???関数strip_sql($string)

??? {

??? グローバル $search_arr,$replace_arr;

??? 戻り is_array($string) ? array_map('strip_sql', $string) : preg_replace($search_arr, $replace_arr, $string);

???}

これら 2 つの変数は ??? 関数でグローバル変数として定義されます。 その後、関数内で直接使用できます。 ? まずはこの機能について説明しましょう。 名前が示すように、この関数は SQL ステートメント内の文字をフィルターし、SQL ステートメントの主要な単語を無効にします。

??? 主にこれらの SQL ステートメントをフィルタリングします。 主にこれらのキーワード: ユニオン選択?これらの SQL ワードは $_GET 送信で非常に簡単に傍受されるためです。

??? この機能は本当に絶妙に書かれています。 ? is_array は、$string が配列であるかどうかを判断します。その場合は、array_map() 関数を使用して、$string 配列内の各ユニットを再帰的にフィルタリングします。各ユニットは文字ですよね。

???strip_sql() が再帰的に呼び出される場合、$string は配列ではなく文字列であるため、is_array() は $string が false でなければならないと判断します。そこで、preg_replace()関数を実行します。この機能はわかりやすいですね。交換したばかりです。

??? */

??? $_POST = ストリップ_sql($_POST);

??? $_GET = ストリップ_SQL($_GET);

??? $_COOKIE = ストリップ_sql($_COOKIE);

??? /**

??? $_POST をフィルタリングするには、strip_sql() 関数を使用しますか? $_COOKIE;

??? 一般的にはオープンソース サイトではありません。 SQL キーワード フィルタリングが通過することはほとんどありません。しかし、これにはリスクも伴います。

???*/

??? unset($search_arr, $replace_arr);

??? /**

??? 使用されているが今後は必要ない変数の設定を解除します。これは良い習慣です。まず、メモリを無駄にしないことです。変数に大量のデータ バイトが格納されている場合、プログラムでそれを使用する必要はありません。次に

??? メモリの無駄になります。プログラムのパフォーマンスが悪い(笑)。本当に書かれています。とにかく、これは私たち全員が学ぶ必要がある良い習慣です。

???*/

??? $magic_quotes_gpc = get_magic_quotes_gpc(); // get_magic_quotes_gpc() は、システムが gpc を自動的に変更するかどうかを検出します。 gpcとは何ですか? GET POST COOKIE には、次のいくつかの点があります。 true または false を返します

??? if(!$magic_quotes_gpc)

??? {

??? $_POST = new_addslashes($_POST);

??? $_GET = new_addslashes($_GET);

???}

??? /**

??? システムが gpc を自動的にリダイレクトするオプションをオンにしているかどうかを確認します。そうであれば、私たちは自動的に考えを変える必要はありません。そうでない場合は、やはり庶民のやり方に頼るしかありません。衣食住は自分で十分に作りましょう。

??? global.func.php ファイルでも定義されているこの関数を見てみましょう。これは実際には、PHP の addslashes() 関数をカプセル化する関数です。 PHP には既に関数があるのに、それを関数にカプセル化する必要があるのはなぜですか?

???理由は簡単です。将来の拡張に備えて変更が容易です。みんなで addslashes() 関数を使って ' を最初から変換するとします。その後、プログラムが将来的に発展するにつれて。もっとフィルタリングしたいかもしれません^ * ( ) など

???それではどうすればいいでしょうか?子どもたちのこれからの成長のために。封印したほうがいいよ。 将来、恋しくなるものがあるかもしれないことを覚えておいてください。それらをモジュールにカプセル化するのが最善です。関数 。親切。 これにより、プログラムの柔軟性が向上します。

??? 関数 new_addslashes($string)

??? {

??? if(!is_array($string)) return addlashes($string);

??? foreach($string as $key => $val) $string[$key] = new_addslashes($val);

??? $string を返します;

???}

??? この関数も非常によく書かれています。文字チャネルまたは配列のフィルタリングやパススルーの使用も検討してください。観てみれば分かるはずです。これは言うまでもありません。私たちはこの考え方と方法を学ぶ必要があります。このようにしてのみ、私たちは進歩することができます。

???ははは。私たちは模倣する方法を知る必要があります。

???*/

??? @extract($_POST, EXTR_OVERWRITE);

??? @extract($_GET, EXTR_OVERWRITE);

??? /**

??? おい。抽出の前に @egg を追加する目的は何ですか? ?エラーを抑制します。それでもわからない場合は。私自身も百度です。

???extract() 関数を使用するのはなぜですか? プログラムで渡された変数を取得するには、通常 $_POST を使用しますか?面倒だと思いませんか?

??? たとえば、$_POST['xx'] を受け入れますか?でも、あまり書きすぎるのも面倒ですよね?面倒な気がする。ここで、渡されたものを $xx 経由で直接取得したいと考えています。何をするか?

??? は、extract() 関数を使用してこのような手法を実装します。 このテクニックは discuz フォーラムでも使用されています。

???*/

??? unset($_POST, $_GET);

??? /**

??? 言うまでもなく、unset() の利点は次のとおりです。 $_POST $_GET 配列は不要になったので解放します。

???*/

????>

??? 明日はお休みです。今日は何か書いています。休み中は書く時間がありません。妻に同行したいのですが、これを見て何が分かりませんか?スレッド内で質問できます。分かりました、お答えします。ありがとうございます

続き: :

2007-12-21

昼食後、コードの分析を始めました。あまり時間はありません。

引用:

??? /**

??? コードの説明と分析: Ni Xuehan 2007 - 12 - 21

???*/

??? PHPCMS_ROOT.'/config.inc.php';

が必要です ??? /**

??? サイト全体の設定パラメータファイルを追加します。一般的なプログラムにはこのファイルがあります。何をするか?たとえば、一部のデータベース接続アドレスなどです。ユーザー名、パスワードなど使用する必要があるパラメータはこのファイルで定義されます。この後、構成が変更されます。このファイルの

を変更するだけです ???変数値は問題ありません。とても便利ではないでしょうか?ははは。ここで require() ロード関数について話しましょう。 require と include はどちらも他の PHP ファイルをロードするために使用されます。しかし、違いがあります。 require 関数: これは「事前解釈」関数です。プログラムがロードされるとすぐに、require 関数が実行されます。そして、含めるのはどうでしょうか?プロセスロード機能です。if などのロジックに include を使用して、他のプログラム フラグメントを動的にロードできます。しかし、requireは機能しません。 */

??? PHPCMS_ROOT が必要です。'/言語/'.$CONFIG['言語'].'/phpcms.lang.php';

??? /**

??? 名前が示すように、これは言語パックをロードします。 PHP の国際化は現在最も進んでいます。 PHP ファイルを使用して直接実装されます。プログラムで使用する中国語情報をphpcms.lang.phpファイルに定義します。次に、プログラムの最初にそれをロードします。プログラムの中にあります

??? このファイル内の変数とすべてを使用できます。それなら簡単です。テンプレートに中国語情報を直接記述する必要はありません。このファイルで定義されている変数に直接置き換えます。それにより国際化を実現します。以上!!! この言語ファイルは自分で開いて考えるのが最善です。ただ知っておいてください。それは非常に単純であることがわかります。

???*/

???define('PHPCMS_PATH', $CONFIG['rootpath']);

???define('PHPCMS_CACHEDIR', $CONFIG['cachedir']);

??? /**

??? $CONFIG['rootpath']? これは、グローバル設定ファイル config.inc.php ファイル内のデータベース情報です。すべての構成情報を待ちます。ここでは定数として定義します。なぜ定数として定義する必要があるのでしょうか?作者がこのように書くことに抵抗を感じていないからです。ふふ。実際には、次のような理由で

??? これら 2 つの変数はよく使用されます。したがって、単純に定数として定義します。使いやすい。もう 1 つのトリック: $CONFIG['rootpath']? 実際には、$CONFIG[rootpath]? と書くこともできますが、これは行わない方がよいでしょう。なぜ。なぜなら、PHP エンジンは最初に rootpath が定数であるかどうかを判断するからです。 $CONFIG[rootpath] が配列であるかどうかは判断されますか?このパフォーマンスは少し悪いです。もう 1 つのテクニックについて話しましょう。なぜほとんどのプログラムは "" 二重引用符の代わりに '' 一重引用符を使用するのでしょうか?この方が効率的であるため、"" を二重引用符で囲みます。

???PHP エンジンは、まず変数が含まれているかどうかを確認し、変数がある場合はそれを説明します。また、'' 一重引用符はこのチェック手順を実行しません。そしてそれはキャラクターとして直接扱われました。したがって、効率には多少の影響があります。

???*/

??? $CONFIG['enablephplog'] ? set_error_handler('phpcms_error') : error_reporting(E_ERROR | E_WARNING | E_PARSE);

??? /**

??? $CONFIG['enablephplog']? エラーログ設定を有効にするかどうか。この設定は、グローバル構成ファイル .config.inc.php にあります。ここでは三項演算子が使用されていますが、これは私が最も好んで使用します。いくつかの簡単な論理的判断。 ? : ; を使用すると、より単純な

を実現できます。 ??? set_error_handler() この関数には優れた背景があります。エラー発生後のphp4の典型的なカスタムプログラムの動作の機能。とても便利です。使い方は? set_error_handler(function) のパラメータも関数です。この機能。エラー後のプログラムの動作を反映します。

???phpcms_error 関数は global.func.php グローバル関数に存在します。

???関数 phpcms_error($errno, $errmsg, $filename, $linenum, $vars)

??? {

??? $filename = str_replace(PHPCMS_ROOT, '.', $filename);

??????? $filename = str_replace("\", '/', $filename);? // 握win平台の \ 换成 /兼容常见系统的路径

??????? if(!define('E_STRICT'))define('E_STRICT', 2048);

??? $dt = date('Y-m-d H:i:s');

??? $errortype = array (

?????????? E_エラー???????????? => 'エラー'、

?????????? E_警告????????? => '警告'、

?????????? E_PARSE???????????? => '解析エラー'、

?????????? E_通知????????? => 「お知らせ」、

?????????? E_CORE_ERROR????? => 'コアエラー'、

?????????? E_CORE_WARNING??? => 「コア警告」、

?????????? E_COMPILE_ERROR?? => 'コンパイル エラー'、

?????????? E_COMPILE_WARNING => 'コンパイル警告'、

?????????? E_USER_ERROR????? => 'ユーザーエラー'、

?????????? E_USER_WARNING??? => 「ユーザー警告」、

?????????? E_USER_NOTICE???? => 「ユーザー通知」、

?????????? E_STRICT????????? => 「実行時通知」

???????????????? );

??? $user_errors = array(E_USER_ERROR, E_USER_WARNING, E_USER_NOTICE);

??? $err = "n";

??? $err .= "t" 。 $dt 。 "n";

??? $err .= "t" 。 $errno 。 "n";

??? $err .= "t" 。 $errortype[$errno] 。 "n";

??? $err .= "t" 。 $errmsg 。 "n";

??? $err .= "t" 。 $ファイル名 。 "n";

??? $err .= "t" 。 $linenum 。 "n";

??? if (in_array($errno, $user_errors))

??? {

??????? $err .= "t" 。 wddx_serialize_value($vars, "変数") 。 "n";

??? }

??? $err .= "
nn";

??? echo $err;

??? error_log($err, 3, PHPCMS_ROOT.'/data/php_error_log.xml');

??? chmod(PHPCMS_ROOT.'/data/php_error_log.xml', 0777);

??? }

??? それはこのタンパク質です。 私はゆっくりと乾かします。 この独自のセキュリティ出力メッセージ関数には 4 つのパラメータが含まれています。 最初のパラメータ $errno は、プログラムがエラーを出力する等のクラスです。 2 番目のパラメータは、プログラムが出力されるインターフェース情報です。 3 番目は、エラーが出力されるプログラムのファイル名です。 > ??? 必要のない実行は、現在の変化状況のニュース写真です。 ? しかし、私は错误日志を生成する必要がありますか? 他は in_array() 関数を使用して (比較的単純なので、ご了承ください) E_USER_ERROR、E_USER_WARNING、E_USER_NOTICE この 3 つの種類のセキュリティ日報情報のみを確認します。n は文書の実行番号、t は形式表です。 ここでは、あまり一般的ではない関数 wddx_serialize_value () を使用しています。 wddx も xml の一種です。 wddx_serialize_value() この関数は、一般的な量を XML 形式で出力します。 。最初のパラメータは次のとおりです。必要な形式で出力される量、2 番目のパラメータは出力される xml の情報です。 以下は error_log() 関数です。この関数は十分に役立ちます。つまり、日報ファイルを作成するのに役立ちます。オープンする必要はありません。方便です。さらに多くの機能があります。書き込みは実行可能です。php5 では、自分自身の出力情報を定義するために extends Exception を使用します。そのため、set_error_handle() の使用を最小限に抑えます。 日報機能が開始されていない場合は、error_reporting(E_ERROR | E_WARNING | E_PARSE) が実行されます。一般的に、問題の情報が先に出力されます。

??? */

??? if($CONFIG['sessionsavepath']) session_save_path($CONFIG['sessionsavepath']);

??? /**

??? セッションのストレージ パスを定義します。セッションは実際には Cookie ですが、セッションはサーバー側で実装されます。安全だが集中力が高い。これを行うメリットは何でしょうか?効率は非常に良いです。仮想ホストを使用している場合。すべての人のセッション Cookie は、php.ini で設定されたデフォルトの場所に配置されます。フォルダーが肥大化すると速度が遅くなります。右。 2つ目は安全性です。 session_start() 関数

の前に忘れずに定義してください。 ???*/

??? session_start();

??? if(function_exists('date_default_timezone_set')) date_default_timezone_set($CONFIG['timezone']);

??? /**

??? php5 にはタイムゾーンの概念が備わっています。记得就行

??? */

??? header('Content-type: text/html; charset='.$CONFIG['charset']);

??? /**

??? ページのエンコーディングを設定します。 ページのエンコーディング。データベースのエンコーディング。ファイルの内部コード。 3つのコードが同じであれば、通常は文字化けは起こりません ファイルの内部コードは何ですか?各ファイルには独自の内部エンコーディングがあります。一般に、UTF8 を使用することをお勧めします。ファイルの内部コードを変更するにはどうすればよいですか? DW または UE を使用できます。カジュアル。データベースのエンコードを指定する必要があります。 MySQL5 には最初から文字セット モードがあり、より多くのプラットフォームと互換性があるように設定するのが最善です。

??? ページのエンコード: これです。一般的な HTML ヘッダー ファイルが利用可能です。それでは、まだ header('Content-type: text/html; charset='.$CONFIG['charset']); が必要ですか?実際、それは必要です。自分で書いたプロンプトレイヤーがいくつかあるからです。または、ファイル内でページエンコーディングが指定されていません。文字化けは発生しやすいので、そうなる前に対策を講じておきたいですね。ヘッダーは過去にエンコードされています。それで大丈夫です。なんと素晴らしいことでしょう。

???*/

??? if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP'), 'unknown'))

??? {

??? $PHP_IP = getenv('HTTP_CLIENT_IP');

??? }

??? elseif(getenv('HTTP_X_FORWARDED_FOR') && strcasecmp(getenv('HTTP_X_FORWARDED_FOR'), 'unknown'))

??? {

??? $PHP_IP = getenv('HTTP_X_FORWARDED_FOR');

??? }

??? elseif(getenv('REMOTE_ADDR') && strcasecmp(getenv('REMOTE_ADDR'), 'unknown'))

??? {

??? $PHP_IP = getenv('REMOTE_ADDR');

??? }

??? elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], 'unknown'))

??? {

??? $PHP_IP = $_SERVER['REMOTE_ADDR'];

??? }

??? preg_match("/[d.]{7,15}/", $PHP_IP, $ipmatches);

??? $PHP_IP = $ipmatches[0] ? $ipmatches[0] : '不明';

??? /**

??? getenv() 関数は環境変数を取得する関数です。環境変数: HTTP_CLIENT_IP はクライアントの IP を取得します。ただし、ユーザーがプロキシ経由でプログラムにアクセスする可能性があります。次に、この時点で環境変数を使用する必要があります:

???HTTP_X_FORWARDED_FOR? getenv('REMOTE_ADDR') $_SERVER['REMOTE_ADDR'] を含め、すべて他の人の IP から取得されます。とにかくルオに触れてください。遭遇したときにそれを手に入れることができれば、それで終わりです。

???*/

??? $PHP_TIME = time();

??? $PHP_SELF = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : (isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME'] : $_SERVER['ORIG_PATH_INFO']);

??? /**

??? 現在実行中のスクリプトの名前を取得する: 最初は少し混乱するように思えます。なぜif elseを使わないのでしょうか? このようなものを見てください。右から左に見るのがベストです。このように理解するのが簡単です。 $_SERVER['SCRIPT_NAME'] $_SERVER['PHP_SELF']? $_SERVER['ORIG_PATH_INFO'] これら 3 つのサーバー グローバル変数は、現在のスクリプト名を取得します。主にサーバーの現在の環境に依存します。存在するものが何であれ、それを受け入れてください。

??? isset() 関数は非常に便利です。変数が定義されているかどうかをテストします。注: $a= NULL; isset($a) は false を返します。 isset 関数と empty 関数の使用法に注意してください。使い方を誤ると大きな問題が発生する可能性があります。説明書は自分で読んでください。

???*/

??? $PHP_QUERYSTRING = $_SERVER['QUERY_STRING'];

??? $PHP_DOMAIN = $_SERVER['SERVER_NAME'];

??? $PHP_REFERER = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';

??? $PHP_SCHEME = $_SERVER['SERVER_PORT'] == '443' ? 'https://' : 'http://'; // サーバーが ssl 接続を起動しているかどうかを検査します。その場合、https://安全な接続を使用して検閲を実行します

??? $PHP_PORT = $_SERVER['SERVER_PORT'] == '80' ? '' : ':'.$_SERVER['SERVER_PORT'];

??? $PHP_SITEURL = $PHP_SCHEME.$PHP_DOMAIN.$PHP_PORT.PHPCMS_PATH;

??? $PHP_URL = $PHP_SCHEME.$PHP_DOMAIN.$PHP_PORT.$PHP_SELF.($PHP_QUERYSTRING ? '?'.$PHP_QUERYSTRING : '');

??? /**

??? 現在のスクリプトの URL を取得します

???*/

??? $db_file = $db_class = 'db_'.$CONFIG['データベース'];

??? if(!define('IN_ADMIN')) //結果が後台にない場合。定数 IN_ADMIN はバックグラウンド フラグ

です ??? {

??? if($CONFIG['dbiscache']) $db_file .= '_cache';

??? if($CONFIG['phpcache'] == '2') // config.inc.php でキャッシュが有効になっている場合

??? {

????? $cachefileid = md5($PHP_SELF.'?'.$PHP_QUERYSTRING); //スクリプト名とその後の取得情報md5を暗号化して以下のキャッシュディレクトリとキャッシュファイルを生成します

????? $cachefiledir = PHPCMS_ROOT.'/data/phpcache/'.substr($cachefileid, 0, 2).'/' // キャッシュディレクトリ

????? $cachefile = $cachefiledir.$cachefileid.'.html' //キャッシュ ファイル: xxx.html 形式

????? if(file_exists($cachefile) && ($PHP_TIME
????? {?? // キャッシュ ファイルが存在し、キャッシュの有効期限が切れていない場合は、キャッシュ ファイル名を返します

?????? $cachefile が必要です;

??????終了;

???????}

???}

??? if($PHP_QUERYSTRING && preg_match("/^(.*).(htm|html|shtm|shtml)$/", $PHP_QUERYSTRING, $urlvar)) //渡された変数を取得します。何の役に立つの?以下の説明をご覧ください

??? {

????? parse_str(str_replace(array('/', '-', ' '), array('&', '=', ''), $urlvar[1]));

???}

???}

??? /**

???上記の部分は比較的複雑です。しかし、それは問題ではありません。ゆっくり説明してください。まず第一に、キャッシュはフロントエンドのみに適用されます。したがって、最初から判断します。このスクリプトは、!define('IN_ADMIN') によってバックグラウンドではなくフォアグラウンドで実行されているかどうかを判断します。

???それでは。次に、顧客設定の config.inc.php ファイルでキャッシュが有効になっているかどうかを確認します。 ==2 オンになります。 .次に、一連のルールを使用してキャッシュのファイル名とディレクトリを検索します。 スクリプト名を使用します: xx.php とその後のパラメータが渡されますか? xx=ee&bb=jj この 2 つの文字の MD5 を使用して、キャッシュディレクトリ。そしてキャッシュファイル。次に、キャッシュ ファイルが存在するかどうか、およびキャッシュ ファイルの有効期限が切れているかどうかを確認します。そうでない場合は、このキャッシュ ファイルの名前を返します。

???それではメインの時間です。最後の if ロジックは何をするのでしょうか? このような Web サイトを見たことがあるかどうかはわかりません: http://www.beihai.com/dd.php/xx-23/cc-22.html これらは実際には擬似静的です。 . URL の最適化に使用されます。まだ非常に静的に見えます。いいね。 しかし、そうしたいかもしれません。そんな住所です。私たちは PHP プログラムを作成します。 get変数を取得するにはどうすればよいですか?最後に、この質問に対する答えは if です。まず URL を削除して、渡された文字を取得します。次に、「/」?「=」を標準のものに置き換えます。 php&xx =23&cc=22 もう理解できるはずです。次に、parse_str() 関数を使用して、xx を $xx=23?? cc から $cc=22??? に変更します。PHP はすべてを考えてくれます。強力な。分かりますか。わかりました。合格した。

??? */

続ける

require PHPCMS_ROOT.'/include/'.$db_file.'.class.php'; // 次の章で詳しく説明するデータベース操作クラスが含まれます

require PHPCMS_ROOT.'/include/tag.func.php' // 遭遇したらお知らせください

require PHPCMS_ROOT.'/include/extension.inc.php' // 遭遇したらお知らせください

$db = new $db_class // データベース クラスをインスタンス化します

$db->connect($CONFIG['dbhost'], $CONFIG['dbuser'], $CONFIG['dbpw'], $CONFIG['dbname'], $CONFIG['pconnect']); //データベースに接続@_@

$db->iscache = $CONFIG['dbiscache'] //SQL キャッシュを有効にするかどうか

; $db->e​​xpires = $CONFIG['dbexpires'] //キャッシュ時間

; if(!cache_read('table.php'))

{

require_once PHPCMS_ROOT.'/include/cache.func.php';

???cache_all(); //すべてのキャッシュを生成します

}

/**

cache_read()関数 キャッシュファイルの読み込み関数はglobal.func.phpに存在します。最初に提供します:

関数cache_read($file, $mode = 'i')

{

$cachefile = PHPCMS_CACHEDIR.$file;

if(!file_exists($cachefile)) return array();

return $mode == 'i' ? include $cachefile : file_get_contents($cachefile);

}

それはとても簡単です。テキスト キャッシュは、一部の大規模なオープンソース PHP プロジェクトでよく見られます。主にデータベースの負荷を軽減するためです。 たとえば、プログラムの起動ファイルでは、バックグラウンド設定の一部の共通情報が php ファイルにキャッシュされます。そうすれば、毎回データベースにアクセスすることなく、将来のプログラムで直接使用できるようになります。ただし、情報は頻繁に更新する必要があります。 PHP ファイルに組み込まれているファイル ロック flock() はあまり役に立たないため、テキスト キャッシュは使用しないことをお勧めします。大規模なシステムでは、複数のユーザーが同時にキャッシュ ファイルに書き込み、アクセスすると、キャッシュ ファイルが破壊される可能性があります。大規模なシステムの場合は、負荷分散を実現するために memcached、mysql5.1 パーティション、および mysql マスター/スレーブを使用することをお勧めします。この機能は非常にシンプルです。自分の目で見てみればわかります。キャッシュおよびモード変数 $mode が i の場合は、それを含めます。そうでない場合は、ファイルを文字列の形式でメモリに読み込みます。

Cache_read() がキャッシュ ファイル 'table.php' を見つけられない場合は false を返し、cache.func.php ファイルをロードします。これには、キャッシュを作成するためのいくつかの関数が含まれています。その後、cache_all() 関数が実行されて、すべての共通情報キャッシュが生成されます。

生成原理を含む phpcms のキャッシュの詳細。詳細な記事はスタートアップファイルcommon.inc.phpが完成したら書く予定です。

*/

$CACHE =cache_read('common.php');

/**

common.php をロードし、変数 (データ) をファイルにキャッシュすることで、毎回データベースから読み取る必要がなくなります。そう

common.php ファイルには何が含まれていますか?上菜:


配列を返します (

? 'モジュール' =>

?配列 (

??? 'phpcms' =>

???配列 (

??????? 'モジュール' => 'phpcms',

??????? '名前' => 'phpcms',

??????? 'スコア' => '1'、

??????? 'iscopy' => '0'、

??????? 'isshare' => '0'、

??????? 'モジュールディレクトリ' => ''、

??????? 'リンクURL' => ''、

??? )、

??? 'メンバー' =>

???配列 (

??????? 'モジュール' => 'メンバー'、

??????? '名前' => '会员'、

??????? 'iscore' => '1'、

??????? 'iscopy' => '0'、

??????? 'isshare' => '0'、

??????? 'モジュールディレクトリ' => 'メンバー'、

??????? 'リンクURL' => '/phpcms/member/',

??? )、

??? '記事' =>

???配列 (

??????? 'モジュール' => '記事'、

??????? '名前' => '文章',

??????? 'iscore' => '0'、

??????? 'iscopy' => '1'、

??????? 'isshare' => '0'、

??????? 'モジュールディレクトリ' => '記事'、

??????? 'リンクURL' => ''、

??? )

?>

これはすべてデータベース サイトから生成されたテキスト保存情報です。私たちは毎回データベース サイトに接続する必要はありません。その一方で、構成情報を取得できるのは、サイトの数だけです。

これは、このテキスト保存ファイルを作成するまでの、テキスト保存の機能です。さらに 1 篇説明します。

*/

$MODULE = $CACHE['モジュール']; // 存在中のデータ

$CHANNEL = $CACHE['チャンネル'];

$PHPCMS = $CACHE['phpcms'];

$FIELD = $CACHE['フィールド'];

unset($CACHE, $ipmatches, $CONFIG['timezone'], $CONFIG['cachedir'], $CONFIG['dbhost'], $CONFIG['dbuser'], $CONFIG['dbpw'], $CONFIG ['pconnect'], $CONFIG['dbiscache'], $CONFIG['dbexpires']);

/

**

設定を解除してください。

*/

if($PHPCMS['enablebanip'] && ip_banned($PHP_IP)) showmessage($LANG['administrator_banned_this_IP']);

/**

$PHPCMS['enablebanip'] とは何ですか?言うまでもなく、あなたはそれを知っているはずです。 IPアクセスのフィルタリング機能を有効にするかどうかをバックグラウンドで設定します。 (phpcmsを使ったことがないので、コードから推測しました。間違っていたらご指摘ください。) ここから、テキストキャッシュにも役割があることがわかります。 ip_banned() 関数とは何ですか?給仕について話しましょう:

関数 ip_banned($ip)

{

global $PHP_TIME; //前に定義したとおり。現在時刻

$ipbanneds =cache_read('banip.php');

if(!is_array($ipbanneds)) return FALSE;

foreach($ipbanneds as $v)

{

? if($v['残業']
? if($ip == $v['ip'] || preg_match("/^".str_replace('.', '[.]', $v['ip'])."$/", $ ip)) TRUE を返します;

}

}

内部ではcache_read()関数も使用されており、ファイルbanip.phpは引き続き読み取られます。ファイル banip.php には、バックグラウンドでフィルタリングする IP のリストが含まれています。

内部のロジックは比較的単純です。自分で消化しました。分からない場合は

と聞いてください showmessage() 関数は、エラー メッセージをカプセル化する関数です。国有化された $LANG['administrator_banned_this_IP'] が見えますか?これは、読書言語パックに含まれているものです。このようにして、プログラムの複数の言語バージョンを作成できます。

*/

$TEMP = $MOD = $CHA = $CATEGORY = $CAT = array();

$ftp = $enableftp = $tags = $html = 0;

/**

変数を初期化します。これは良い習慣なので、私たちはそれを真似すべきです。

*/

if(!isset($mod))

{

$mod = 'phpcms'; //phpcms は默认追加ダウンロード的模块

}

elseif($mod != 'phpcms')

{

isset($MODULE[$mod]) または exit($LANG['module_not_exists']); // 生存中读追加された模块かどうか开启

/**

私はこの書き方がとても気に入っていて、毎日使っています。 ?? xx && dd ; xx および dd? ; AND 演算では、式全体が true になることが必要です。 ; xx || dd ; xx または dd? 1 つの条件が満たされる限り、OR 演算は次の条件を実行しません。こう書くとかっこよくないですか?

*/

$MOD =cache_read($mod.'_setting.php'); // このモジュールのいくつかの常用構成数値の追加を開始します。 phpcms は、対応する各モジュールに 1 つの保存構成ファイルを持っています。@@ 怪不得速度那么快

@include PHPCMS_ROOT.'/langages/'.(define('IN_ADMIN') ? $CONFIG['admin language'].'/'.$mod.'_admin.lang.php' : $CONFIG[' language'].' /'.$mod.'.lang.php');

/**

対応するモジュール言語パッケージをロードします。

*/

}

if(!isset($forward)) $forward = $PHP_REFERER; // 前の URL アドレスを通知します。以降のプログラムではこの量を使用する必要があります

$dosubmit = isset($dosubmit) ? 1:0; //记录有無表单提交过。また後有用

$channelid = isset($channelid) ? intval($channelid) : 0; //记录当前メディア道のid? $channelid に isset がない場合は 0 になります。 intval() は十分に役立ちます。数字と数字を比べると加速も減速もずっと早くなります。覚えておいてください

$skindir = PHPCMS_PATH.'templates/'.$CONFIG['defaulttemplate'].'/skins/'.$CONFIG['defaultskin'] //デフォルトの phpcms スキンをロードします

; if($PHPCMS['enablegzip'] && function_exists('ob_gzhandler'))

{

($CONFIG['phpcache'] || 定義('SHOWJS')) ob_start() : ob_start('ob_gzhandler');

}



{

$PHPCMS['enablegzip'] = 0;

ob_start();

}

/**

$PHPCMS['enablegzip']?? この変数は phpcms_setting.php ファイルに存在します。すでに上で述べました。各モジュールには、対応するモジュール構成キャッシュ ファイル (データベースからコピーされた情報) があります。この変数は、圧縮送信がオンになっているかどうかを示します。

圧縮伝送、その名前を聞いてください。特定のアルゴリズムに従ってデータを圧縮することを意味します。そしてクライアントに送信されます。これにより、限られた帯域幅内でより大量のデータを送信できるようになります。もちろん速度もかなり速くなります。圧縮されたデータがブラウザに到達すると、ブラウザによって自動的に解凍されます。一部の古いバージョンのブラウザでは解凍がサポートされていません。しかし、これまでブラウザを長年使用してきた人が他にいるでしょうか?使用法は非常に簡単です。上記を見てください:

まず、顧客の上司がこのモジュールの圧縮送信をバックグラウンドで選択したかどうかを判断します (そうであれば、対応するテキスト キャッシュ ファイルに当然ロードされています)。 Peugeot: $PHPCMS['enablegzip']? callback 関数 ob_gzhandler は有効ですか? ob_gzhandler は実際には関数ではありません。マニュアルの説明を参照してください。 それはとても簡単です。これは、ob_start() のコールバックとして特別に使用される単なるパラメーター関数です。詳細についてはマニュアルを参照してください。怠惰にしないでください。プログラムの先頭にある ob_start('ob_gzhandler') が判定された場合、圧縮送信が開始されます。次のコードを続けてください:

($CONFIG['phpcache'] || 定義('SHOWJS')) ob_start() : ob_start('ob_gzhandler');

phpcms コードを見ると、次のようになります。 ユーザーがバックグラウンドでの圧縮送信をオンにした場合。そしてユーザーはページ キャッシュをオンにしました。この場合、デフォルトでは圧縮伝送は使用されません。なぜこのように設計されているのかわかりません。テストしてみました。バックグラウンドでの圧縮送信を有効にします。同時に、ページキャッシュが使用されます。問題は見つかりませんでした。 @@

圧縮送信が有効になっていない場合は、セッションを使用する前に ob_start(); ob_start() が必要であり、ob_start() の前にヘッダー ファイルを送信または出力することはできません。例: echo ヘッダーなどは問題ありません。

*/

$_userid = 0;

$_username = '';

$_groupid = 3;

$_arrgroupid = array();

$phpcms_auth = getcookie('auth');

/**

$_userid、$_username、$_groupid? ユーザー情報を記録するこれらの変数を初期化します。初期化しない場合、リスクが非常に大きくなります。 @@ 誰かに $_GET に _userid 変数を与えた場合。その後、変数は上書きされます。しかし、これらの変数に値を与えると、

次に、近接性の原則に従います。変数を取得した場合でも。元の変数値も変更できません。皆さんも自分で考えてみてください。あなたは理解するでしょう。

getcookie() このカスタム関数は、global.func.php ファイルで定義されます。提供:

関数 getcookie($var)

{

グローバル $CONFIG;

$var = $CONFIG['cookiepre'].$var;

return isset($_COOKIE[$var]) ? $_COOKIE[$var] : FALSE;

}

この関数は、設定した cookie の値を抽出するために使用されます。 $CONFIG['cookiepre']? config.inc.php ファイルに設定されます。この関数は非常に単純です。一目で分かりやすいです。

*/

if($phpcms_auth)

{

$phpcms_auth_key = md5($PHPCMS['authkey'].$_SERVER['HTTP_USER_AGENT']);

list($_userid, $_password, $_answer) = $phpcms_auth ?explode("t", phpcms_auth($phpcms_auth, 'DECODE')) : array(0, '', '');

/**

? list() = array(); ユーザーは自分で試すことができます。 わかりました

• phpcms_auth() は、Cookie がクライアント側に存在するため、暗号化および復号化関数です。とても危険です。 ユーザーのパスワードさえも Cookie に保存されているのですが、暗号化しないことは可能でしょうか。ただし、暗号化後は復号化できなければなりません。ユーザー名とユーザーパスワードが必要なので、

に進む必要があります。 ? 入手しました。 この関数は global.func.php ファイルに存在します。このアルゴリズムを理解したい場合は、ご自身で読んでください。とてもシンプルです。 実際、暗号化と復号化は $phpcms_auth_key? 変数の周りで行われます。これは discuz の cookie メカニズムと似ています。

? $phpcms_auth_key = md5($PHPCMS['authkey'].$_SERVER['HTTP_USER_AGENT']);? $PHPCMS['authkey'] を確認すると、バックグラウンドで Cookie 暗号化値が存在すると推定されます。を入力し、この値と $ _SERVER['HTTP_USER_AGENT'](システム情報)

を使用します。 */

$_userid = intval($_userid);

if($_userid < 0) $_userid = 0; //Cookie のユーザー ID が 0 未満の場合に読み取られます

if($_userid) //Cookie によって保存された uid が存在する場合、この ID に従ってデータベース ユーザー テーブルのチェックを開始し、ユーザー情報を取得します

{

? $memberinfo = $db->get_one("SELECT username,password,groupid,arrgroupid,email,chargetype,begindate,enddate,money,point,credit,newmessages FROM ".TABLE_MEMBER." WHERE userid=$_userid LIMIT 0, 1");

? /**

? phpcms によってカプセル化されたデータベース クラスについては、次の章で説明します。 SQL ステートメントを見てみましょう。 勉強もできます。 まず、すべてのフィールドのレコードを取得する場合を除き、* 形式の select * from xx? を使用しないことをお勧めします。必要なフィールドのみをリストします。これは、大量のデータを含むクエリで使用されます。速度が大幅に向上しました。 ???定数: TABLE_MEMBER? テーブル名を定義します。これを行うことでどのようなメリットがあるのでしょうか?考えた結果、将来テーブル名を変更する際の利便性を考慮して定数として定義しました。これはどこから来たのですか。ファイル内で定義されるものと推定されます。会ったら教えてあげるけど、探すのが面倒なんです。

?*/

? if($memberinfo && $memberinfo['password'] == $_password)? // クエリされたパスワードを使用して、Cookie に存在するパスワードと比較します。比較する前に、まずクエリが成功したかどうかを確認します。多くの PHP 者はそれを無視する傾向があります。

? {

?? if($memberinfo['groupid'] == 2)? //ユーザーが所属するグループの ID が 2 の場合、このユーザーは管理者によってアクセスが禁止されます。

?? {

??????????????? mkcookie('auth', '') // Cookie をクリアします

??? showmessage($LANG['userid_banned_by_administrator']) // プロンプト エラー メニュー

?? }

?? @extract($memberinfo, EXTR_PREFIX_ALL, ''); // このトリックも理解してください。ボス: フィールドを直接使用できる変数に変換します。

?? unset($memberinfo, $_password, $_answer);

?? $_arrgroupid = $_arrgroupid ? array_filter(explode(',', $_arrgroupid)) : array();? //フィールドが FALSE であるフィールドを除外します。コールバックパラメータを使用しない array_filter() の使用方法については、マニュアルを参照してください。

?}

? 他

? {

?? mkcookie('認証', '');

?}

? /**

Cookie を読み取り、上記のデータベース ユーザー情報を確認した後。ご利用者情報が正当なものであることを確認した上で。自動的にログインされます。たとえば、phpchina フォーラム。ログインしてもログアウトしません。次回アクセスするときもログインしたままになります。それが原則です。ぜひ真似してください

? mkcookie () 関数の詳細な説明は次のとおりです。

? 関数 mkcookie($var, $value = '', $time = 0)

? {

?? グローバル $CONFIG,$PHP_TIME;

?? $time = $time > 0 ? $time : (empty($value) ? $PHP_TIME - 3600 : 0);

?? $s = $_SERVER['SERVER_PORT'] == '443' ?

?? $var = $CONFIG['cookiepre'].$var;

?? return setcookie($var, $value, $time, $CONFIG['cookiepath'], $CONFIG['cookiedomain'], $s);

?}

? $time? は Cookie の存続時間です。0? の場合、$PHP_TIME が以前に定義されているときに、Cookie は自動的に期限切れになります。 ?? $PHP_TIME -3600? 3600 秒を引きます。 1 時間前ということは、Cookie の設定が無効であることを意味するはずです。

? $s? 変数は SSL セキュア送信を有効にするかどうかを取得します。 CookieにはSSL経由で送信されるパラメータがあります。サーバーにすでに opensll がインストールされている場合、そのような優れたセキュリティ リソースを無駄にすることはできません。

? $var Cookie 名の接頭辞。主に混乱を避けるためです。

? $CONFIG['cookiedomain']? この人は config.inc.php で設定されています。 '/'?? として定義されます。これは、現在のドメイン内のすべてのディレクトリにある PHP プログラムがこの COOKIE にアクセスできることを意味します。COOKIE へのディレクトリ アクセスを制限する方法もあります。詳細については、setcookie() 関数のマニュアルを参照してください。

?*/

?

}

}

unset($db_class, $db_file, $phpcms_auth, $phpcms_auth_key, $memberinfo);

それでは、投稿を続けてください。

phpcms のデータベース クラスと phpcms のテキスト キャッシュの実装について説明します

。 どれも非常に単純な内容ですので、PHPCMS をインストールして読んでいただくと理解が深まります。 理解できない場合は、繰り返し質問してください。

1 つ目はデータベース クラスです。phpcms のデータベースは mysql バージョンと mssql バージョンに分かれています。MSSQL バージョンの主な違いは、ページングによく使用される limit? ステートメントです。 mssql データベース クラス ドライバーは、非常に優れたカプセル化を行っています。SQL ステートメントに関しては、mysql と MSSQL の違いは非常に小さいため、PHPCMS を使用すると、データベースを自由に変換できると言えます。コード内のデータベース クラス ドライバー。 引用:

???
??? /**

???mysqlデータベースクラス。比較的簡単に書かれています。言うことはあまりありません。ご自身で読んで理解してください。

??? それならスキップできます。

??? */

??? 定義済み('IN_PHPCMS') または exit('アクセス拒否');

??? /**

??? これはよく知られたことではありませんか?右。すでに前の章で述べました。前の章の common.inc.php スタートアップ ファイルでも定義されています? IN_PHPCMS?? そこで、次の PHP ファイルで、人為的に「壁をジャンプ」しているかどうかを確認してください。 「はい」の場合、

を中断します ???*/

??? /**

??? * mysql データベース クラス、キャッシュ関数

をサポート ???*/

??? クラス db_mysql

??? {

??? /**

??? * mysql 接続識別子

??? * @var リソース

???*/

??? var $connid;

??? /**

??? * 整数変数は実行された SQL ステートメントの数をカウントするために使用されます

??? * @var int

???*/

??? var $querynum = 0;

??? /**

??? * データベース接続。データベース接続識別子

を返します。 ??? * @param 文字列データベース サーバー ホスト

??? * @param 文字列データベース サーバー アカウント

??? * @param 文字列データベース サーバーのパスワード

??? * @param 文字列データベース名

??? * @param bool 永続的な接続を維持するかどうか、1 は永続的な接続、0 は非永続的な接続です

??? * @return link_identifier

???*/

??? 関数 connect($dbhost, $dbuser, $dbpw, $dbname, $pconnect = 0)

??? {

????? グローバル $CONFIG;

????? $func = $pconnect == 1 ? 'mysql_pconnect' : 'mysql_connect';

????? /**

????? mysql_pconnect()? は通常の接続です。 mysql_connect との違いは、前者の方がマルチプロセス WEB サーバーでより効率的であることです。ただし、トランザクションとデータ テーブルのロックに関連する欠陥もあります。詳細についてはマニュアルをご確認ください。

???????*/

????? if(!$this->connid = @$func($dbhost, $dbuser, $dbpw))

????{

?????? $this->halt('mysql サーバーに接続できません');

???????}

????? // mysql バージョンが 4.1 以降の場合、データベースの文字セット設定を有効にします

??????? if($this->version() > '4.1' && $CONFIG['dbcharset'])

???????{

?????? mysql_query("SET NAMES '".$CONFIG['dbcharset']."'" , $this->
???????}

????? // mysql バージョンが 5.0 以降の場合、sql モードを設定すると、mysql5 データベースには文字セット モードが付属します。設定するだけです

??????? if($this->version() > '5.0')

????{

?????? mysql_query("SET sql_mode=''" , $this->connid);

???????}

????? if($dbname)

????{

?????? if([email=!@mysql_select_db($dbname]!@mysql_select_db($dbname[/email] , $this->connid))

?????? {

??????? $this->halt('データベース '.$dbname);

??????}

???????}

????? $this->connid を返す;

???}

??? /**

??? * データベースを選択

??? * @param 文字列データベース名

???*/

??? 関数 select_db($dbname)

??? {

????? return mysql_select_db($dbname , $this->connid);

???}

??? /**

??? * SQL ステートメントを実行します

??? * @param 文字列 SQL ステートメント

??? * @param string デフォルトは空、オプションの値は CACHE UNBUFFERED

??? * @param int 秒単位のキャッシュライフサイクル

??? * @return リソース

???*/

??? 関数クエリ($sql, $type = '', $expires = 3600, $dbname = '')

??? {

????? $func = $type == 'UNBUFFERED' ? 'mysql_unbuffered_query' : 'mysql_query';

????? /**

????? mysql_unbuffered_query の方が効率的です。节省内存看手册

??????? */

??????? if(!($query = $func($sql , $this->connid)) && $type != 'SILENT')

??????? {

?????? $this->halt('mysql クエリ エラー', $sql);

??????? }

??????? $this->querynum++;

??????? return $query;

??? }

??? /**

??? * SQL ステートメントを実行し、レコードを 1 つだけ取得します

??? * @param 文字列 SQL ステートメント

??? * @param string デフォルトは空、オプションの値は CACHE UNBUFFERED

??? * @param int 秒単位のキャッシュライフサイクル

??? * @戻り配列

???*/

??? function get_one($sql, $type = '', $expires = 3600, $dbname = '')

??? {

??????? $query = $this->query($sql, $type, $expires, $dbname);

??????? $rs = $this->fetch_array($query);

??????? $this->free_result($query);

??????? $rs を返します ;

??? }

??? /**

??? * 結果セットから行を連想配列として取得します

??? * @param リソース データベース クエリ結果リソース

??? * @param 文字列は戻り値の型を定義します

??? * @return 配列

???*/

??? function fetch_array($query, $result_type = mysql_ASSOC)

??? {

??????? return mysql_fetch_array($query, $result_type);

??? }

??? /**

??? * 前の mysql 操作によって影響を受けたレコード行数を取得します

??? * @return int

???*/

???関数影響を受ける_rows()

??? {

??????? return mysql_affected_rows($this->connid);

??? }

??? /**

??? * 結果セット内の行数を取得します

??? * @return int

???*/

???関数 num_rows($query)

??? {

??????? return mysql_num_rows($query);

??? }

??? /**

??? * 結果セット内のフィールドの数を返します

??? * @return int

???*/

???関数 num_fields($query)

??? {

??????? return mysql_num_fields($query);

??? }

??????? /**

??? * @return 配列

???*/

???関数結果($query, $row)

??? {

??????? return @mysql_result($query, $row);

??? }

???関数 free_result($query)

??? {

??????? return mysql_free_result($query);

??? }

??? /**

??? * 前の INSERT 操作で生成された ID を取得します

??? * @return int

???*/

???関数 insert_id()

??? {

??????? return mysql_insert_id($this->connid);

??? }

??????? /**

??? * @return 配列

???*/

???関数 fetch_row($query)

??? {

??????? return mysql_fetch_row($query);

??? }

??????? /**

??? * @return 文字列

???*/

???関数 version()

??? {

??????? return mysql_get_server_info($this->connid);

??? }

???関数 close()

??? {

??????? return mysql_close($this->connid);

??? }

??????? /**

??? * @return 文字列

???*/

???関数エラー()

??? {

??????? return @mysql_error($this->connid);

??? }

??????? /**

??? * @return int

???*/

???関数 errno()

??? {

??????? return intval(@mysql_errno($this->connid)) ;

??? }

??? /**

??? mysql_errno()? 関数も非常に使いやすいです。ぜひ試してみてください

???*/

??????? /**

??? * mysql エラーメッセージを表示します

???*/

???関数停止($message = '', $sql = '')

??? {

??????? exit("mysql Query:$sql
mysql Error:".$this->error()."
mysql Errno:".$this->errno()."
メッセージ:$message");

??? }

??? }

??? ?>

PHPCMS の文本が存在します:

引用:

???
???定義済み('IN_PHPCMS') または exit('アクセス拒否');

??? /**

??? この文書のこの部分はすべて、文書保存の生成に関連する関数です。文書保存は非常に良い方法です。 ,文本搞定。

??? 原理は次のとおりです。私たちは、後台に多数の関連するウェブサイトのパラメータを設定できるわけではありません。これらのパラメータのほとんどは固定されています。すべて変更されず、データベースに保存されます。 > ??? プログラム内の操作を実行するために、毎回データベース アウト パラメータが必要になります。最初に、データ パケットは、最も消費量の多いハードウェア IO リソースの 1 つであり、この例では、データ レベルの継承が可能です。 ??? 我们在程序開始就把握データ库里面の配置都转化を数組等にしますか? 放任?このようにして、毎回データをアクセスすることなく、php ファイルを直接アクセスできます。 php文本缓存其实成了

??? 私はプログラムとデータベースの中間コンポーネントです。独自のテキスト キャッシュを作成する場合、実際に実装する必要があるのは非常に単純です:? データベースを読み取りますか? PHP ファイルに書き込みますか?

をプログラムに含めますか? ??? かかって来い。テキストキャッシュ学習を開始

??? */

??? function queue_all()? //全キャッシュの合計演算関数を生成します

??? {

???cache_table(); //すべてのデータベース テーブル名を生成します。テーブル名はデータベース内の現在の表示に基づいて生成されます。この関数の詳細な分析をご覧ください

??? require_once PHPCMS_CACHEDIR.'table.php' // テーブル定数が含まれます

???cache_common();

???cache_member_group();

??? $modules = キャッシュモジュール();

??? $channelids = キャッシュチャンネル(0);

??? $keyids = array_merge($modules, $channelids);

??? foreach($keyids として $keyid)

??? {

????? $catids = キャッシュ_カテゴリー($keyid);

????? if(is_array($catids))

????{

?????? foreach($catid として $catid)

?????? {

??????? キャッシュカテゴリ($catid);

??????}

???????}

???}

???cache_type(0);

??? TRUE を返します;

???}

??? 関数cache_common()

??? {

??? グローバル $db;

??? $query = $db->query("SELECT module,name,iscore,iscopy,isshare,moduledir,moduledomain FROM ".TABLE_MODULE." WHEREdisabled=0"); // 利用可能なすべてのモジュールをクエリします

???while($r = $db->fetch_array($query))

??? {

????? $r['linkurl'] = '';

????? if($r['module'] != 'phpcms' && $r['iscopy'] == 0) $r['linkurl'] = linkurl($r['moduledomain'] ? dir_path ($r['moduledomain']) : $r['moduledir'].'/');

????? //モジュールがディレクトリに存在する場合は、そのディレクトリアドレスを取得します

????? unset($r['モジュールドメイン']);

????? $key = $r['モジュール'];

????? $data[$key] = $r;

???}

??? $CACHE['module'] = $data; // キャッシュ配列に保存し、後で $CACHE 配列をテキストに書き込みます

??? $data = array();

??? $query = $db->query("SELECT チャネル ID,モジュール,チャネル名,チャネルディレクトリ,チャネルドメイン,チャネルピック,紹介,スタイル,islink,linkurl,cat_html_urlruleid,item_html_urlruleid,special_html_urlruleid,cat_php_urlruleid,item_php_urlruleid,special_php_urlruleid FROM ".TABLE_CHANNEL ." WHEREdisabled=0 ORDER by listorder"); // 利用可能なチャンネルをリストします

???while($r = $db->fetch_array($query))

??? {

????? $r['linkurl'] = linkurl($r['linkurl']);

????? $key = $r['チャンネルID'];

????? $data[$key] = $r;

???}

??? $CACHE['channel'] = $data; // キャッシュ配列

に保存します。 ??? $data = array();

??????? $r = $db->get_one("SELECT 設定 FROM ".TABLE_MODULE." WHERE module='phpcms'");

??? $CACHE['phpcms'] = unserialize($r['setting']);

??? //phpcms モジュールの設定情報をクエリするには、データベース テーブルの内容を参照します。設定フィールドの情報は、serialize 関数によってシリアル化されます。

??? //したがって、取得したコンテンツはシリアル化解除してデコードする必要があります。私はシリアル化関数を使用するのが好きです。配列をデータベースに保存したり、オブジェクトをデータベースに保存したりできます。または、GET を使用してそれを渡すこともできます。

??? //強すぎる。試してみることができます。プロジェクトのどこかで使用する必要があるかもしれません。

??? $fields = array();

??? $result = $db->query("SELECT * FROM ".TABLE_FIELD." ORDER BY fieldid"); //モジュール情報をダウンロードします。

を理解するには、このテーブルのデータを見てください。 ???????while($r = $db->fetch_array($result))

??? {

????? $テーブル名 = $r['テーブル名'];

????? $fields[$tablename] .= ','.$r['name'];

???}

??? $CACHE['フィールド'] = $フィールド;

???cache_write('common.php', $CACHE); //common.php のテキスト キャッシュへの $CACHE 配列の書き込みを開始します。このファイルは自分で開いて内容を確認できます。すべてが明らかです

??????? $CACHE を返します;

???}

??? functioncache_update($action='')//テキストキャッシュを更新します。バックグラウンドで使用するのが最適です。 PHP のファイル ロック ファイル ロックは、一部のプラットフォームではあまり適切ではないためです。会出现多用户同写一个文件从而破坏缓存文件

??? {

???グローバル $db;

??? $data=array();

??? switch($action)

??? {

??????? case 'キーリンク';

?????? $query=$db->query("SELECT linktext,linkurl FROM ".TABLE_KEYLINK." where pass=1");

?????? while($r=$db->fetch_array($query)){

????????? $data[]=$r;

?????? }

???????休憩;

??????? case 'reword';

?????? $query = $db->query("SELECT word,replacement FROM ".TABLE_REWORD." where pass=1");

?????? while($r = $db->fetch_array($query))

?????? {

??????? $data[]=$r;

?????? }

???????休憩;

???????デフォルト:

?????? $actions = array('keylink','reword');

?????? array_map('cache_update', $actions);

?????? TRUE を返します;

??? }

??? cache_write('cache_'.$action.'.php', $data);

??? $data を返す;

??? }

???関数cache_table()

??? {

???グローバル $db,$CONFIG;

??? $query = $db->query("SHOW TABLES FROM `".$CONFIG['dbname']."`");

??? /**

??? データベース内のすべてのテーブル名を表示します

???*/

??? while($r = $db->fetch_row($query))

??? {

??????? $table = $r[0];

??????? if(preg_match("/^".$CONFIG['tablepre']."/i", $table)) //寻找表前缀等 $CONFIG['tablepre'] (在config.inc.php里设置) @ @表前缀还有这个作用嘿嘿

??????? {

?????? $tablename = str_replace($CONFIG['tablepre'], 'table_', $table);

?????? $data[$tablename] = $table;??? //? $data['table_xx'] = xx; 形式?? 只能意会下了

??????? }

??? }

??? $db->free_result($query);? //$db->free_result()? この種のメソッドは、関数 mysql_free_result() を使用し、主にデータ サイズの大きいリクエストを削除するために内部保存されます。

??? if(!is_dir(PHPCMS_CACHEDIR)) // 常用 PHPCMS_CACHEDIR は common.inc.php のページにあります。大家は確認できません。これは、phpcms の保存目録のパスです。ここでは、次のようになります。 >
??? {

??????? dir_create(PHPCMS_CACHEDIR); //如果缓存目录不存在那么就创建

??????? dir_create($CONFIG['templatescachedir']); // 承認後の PHP モジュールのリストを作成し、phpcms モジュール ドライブの書き込みを行います。次の章で承認を開始します。

??????? /**

????? dir_create() 関数はディレクトリ作成関数です。 PHPCMS は単独でパッケージ化されているので、ちょっと見てみました。 phpcms は非常に強力です。この機能では、ftp 経由でディレクトリを作成することもできます。これにより、サーバーがセーフ モードである場合のディレクトリ作成に関するいくつかの問題を解決できます

????? PHP FTP の知識が必要になるため。ということで、以下で解説していこうと思います。

???????*/

??? }

??? cache_write('table.php', $data , 'constant'); //非常に多くの友人がここで定義されている phpcms の規則に到達していません。

??? /**

??? cache_write() 関数は、global.func.php に定義されています。データから取得された数グループの情報を PHP テキストに書き込みます。 废话少说上菜:

???????関数cache_write($file, $string, $type = 'array')

??????? {

?????? if(is_array($string)) //检测 $string 内容は文字窜の呢还是数组的,是数组的那就继续 ..

?????? {

??????? $type = strto lower($type); ?

??????? if($type == 'array')//その後、この関数のモードを再度判断し、数組モードであるかどうか、数組モードであるかどうかを判断します

??????? {

?????????? $string = "";

?????????? // この太字はリンクされています。データベースの情報をドキュメントに書き込んだ時点で PHP 形式での書き込みが削除されました。

?????????? ここでは、var_export() 関数を使用しています。 🎜>
?????????? この関数は、変化する文字形式を返します。この関数は非常に役に立ちます。この関数がない場合は、さらに自分で実装する必要があります。一度テキストを書き込むことで解決されます。この問題が発生する可能性があります。 「これは

」 ?????????? 初学者は
を操作します。 1 つは html で、もう 1 つは本文の

です。 ??????? }

??????? elseif($type == 'constant') //内容形式

??????? {

?????????? $data='';

?????????? foreach($string as $key => $value) $data .= "define('".strtoupper($key)."','".addslashes($value)."');n";

?????????? $string = "";

?????????? コンテンツの形式で記述される場合は、本文に書き込まれるのではなく、コンテンツが常態化されます。

???????}

??????}

?????? $strlen = file_put_contents(PHPCMS_CACHEDIR.$file, $string);//file_put_contents() 関数は PHP5 でのみサポートされており、最も効率的です。

の使用をお勧めします。 ?????? chmod(PHPCMS_CACHEDIR.$file, 0777); ディレクトリを読み取り可能、書き込み可能、​​および実行可能に設定します

?????? return $strlen; // テキストに書き込まれたバイト数を返します

???????}

???? ?

????? キャッシュされたファイルを読み取るためのもう 1 つの操作関数について話しましょう: 料理を提供する

????? 関数cache_read($file, $mode = 'i')

?????? {

??????? $cachefile = PHPCMS_CACHEDIR.$file;

??????? if(!file_exists($cachefile)) return array();

??????? return $mode == 'i' ? include $cachefile : file_get_contents($cachefile);

??????}

?????? 読み取りキャッシュには実際には php キャッシュ ファイルが含まれます。 話したら退出

??? */

??? $data を返します;

???}

??? /**

???phpcms のすべてのデータベース テーブル名は、データベースの現在のテーブル名に基づいた定数で定義されます。これはあまり良いデザインとは思えません。柔軟性が不十分: たとえば、データベース内のテーブル名を変更した場合です。

??? その後、テーブルが見つからないというエラー メッセージが表示されます。そして修理するのがとても面倒です。つまり、テーブル名を気軽に変更することはできません。皆さんにこのように書くことはお勧めしません。 PHP ファイルでテーブル名を定義できます。このようにして、

??? 特定のテーブルの名前を変更するのに非常に便利です。

???*/

??? 関数cache_module($module = '')

??? {

??? グローバル $db;

??? if($module)

??? {

????? $r = $db->get_one("SELECT settings,module,name,iscopy,moduledir,moduledomain FROM ".TABLE_MODULE." WHERE module='$module'"); //モジュール固有の情報

????? if($r['設定'])

????{

????$setting = unserialize($r['setting']); //アンチチャネリングについて話しました。リア面情報は実行後にデータベースに再保存されるため、

??????? }

??????? $setting['名前'] = $r['名前'];

??????? $setting['moduledir'] = $r['moduledir'];

??????? $setting['モジュールドメイン'] = $r['モジュールドメイン'];

??????? $setting['linkurl'] = '';

??????? if($r['module'] != 'phpcms' && $r['iscopy'] == 0)

??????? {

?????? $setting['linkurl'] = linkurl($r['moduledomain'] ? dir_path($r['moduledomain']) : $r['moduledir'].'/');

???????????????キャッシュ_カテゴリー($module);

??????? }

??????? unset($r['moduledomain']);

??????? cache_write($module.'_setting.php', $setting);

??????? $setting を返す;

??? }

???他

??? {

??????? $query = $db->query("SELECT module FROM ".TABLE_MODULE." WHEREdisabled=0 ORDER by moduleid");

??????? while($r = $db->fetch_array($query))

??????? {

??????キャッシュ_モジュール($r['モジュール']);

?????? $modules[] = $r['モジュール'];

?????????? }

??????? $modules を返す;

??? }

??? }

???関数cache_channel($channelid=0)

??? {

???グローバル $db;

??? if($channelid)

??? {

??????? $data = $db->get_one("SELECT * FROM ".TABLE_CHANNEL." WHERE channelid=$channelid");

??????? if($data && !$data['islink'])

??????? {

?????? if($data['setting'])

?????? {

????????????? $setting = unserialize($data['setting']);

??????? unset($data['setting']);

??????? $data = is_array($setting) ? array_merge($data, $setting) : $data;

?????? }

?????? $data['linkurl'] = linkurl($data['linkurl']);

?????? cache_write('channel_'.$channelid.'.php', $data);

??????キャッシュ_カテゴリー($channelid);

?????? $data を返す;

??????? }

??????? }

???他

??? {

??????? $query = $db->query("SELECT チャネル ID FROM ".TABLE_CHANNEL." WHERE islink=0 ANDdisabled=0 ORDER by channelid");

??????? while($r = $db->fetch_array($query))

??????? {

?????? cache_channel($r['channelid']);

?????? $channelids[] = $r['channelid'];

??????? }

??????? $channelids を返す;

??? }

??? }

???関数cache_categorys($keyid)

??? {

???グローバル $db,$PHPCMS,$CHANNEL;

??? $urlpre = '';

??? if(is_numeric($keyid))

??? {

??????? $keyid = intval($keyid);

??????? $module = $CHANNEL[$keyid]['モジュール'];

?????????? $sql = " チャネル ID=$keyid ";

??? }

???他

??? {

?????????? $sql = " module='$keyid' ";

??? }

引用:

??? $catids = $data = array();

??????? $query = $db->query("SELECT module,channelid,catid,catname,style,introduce,catpic,islink,catdir,linkurl,parentid,arrparentid,parentdir,child,arrchildid,items,itemordertype,itemtarget,ismenu, islist,ishtml,htmldir,prefix,urlruleid,item_prefix,item_html_urlruleid,item_php_urlruleid FROM ".TABLE_CATEGORY." WHERE $sql ORDER by listorder,catid");

??????? while($r = $db->fetch_array($query))

??? {

??????? $r['linkurl'] = str_replace($PHPCMS['index'].'.'.$PHPCMS['fileext'], '', $r['linkurl']);

?????????? $r['linkurl'] = $urlpre ? preg_replace("|^".$urlpre."|", '', $r['linkurl']) : linkurl($r['linkurl']);

??????? $catid = $r['catid'];

?????????? $data[$catid] = $r;

??????? $catids[] = $catid;

??????? }

??? if($data)cache_write('categorys_'.$keyid.'.php', $data); //書き込み保存。

??? $catids を返す;

??? }

???関数cache_category($catid)

??? {

???グローバル $db,$PHPCMS;

??? if(!$catid) は FALSE を返します;

??????? $data = $db->get_one("SELECT * FROM ".TABLE_CATEGORY." WHERE catid=$catid");

??? $setting = unserialize($data['setting']);

??? unset($data['setting']);

??? $data = is_array($setting) ? array_merge($data, $setting) : $data;

??? $data['linkurl'] = linkurl(str_replace($PHPCMS['index'].'.'.$PHPCMS['fileext'], '', $data['linkurl']));

??? cache_write('category_'.$catid.'.php', $data);

??? $data を返す;

??? }

???関数キャッシュタイプ($keyid=0)

??? {

???グローバル $db;

??? if($keyid)

??? {

?????????? $result = $db->query("SELECT * FROM ".TABLE_TYPE." WHERE keyid='$keyid'");

?????????? $data = array();

?????????? while($r = $db->fetch_array($result))

?????????? {

?????? $r['紹介'] = $r['紹介']? $r['紹介']:' ';

????????? $data[$r['typeid']] = $r;

?????????? }

?????????? if($data)

?????????? {

?????? cache_write('type_'.$keyid.'.php', $data);

?????????? }

??????? $data を返す;

??? }

???他

??? {

??????? $modules = array();

??????? $query = $db->query("SELECT module FROM ".TABLE_MODULE." WHEREdisabled=0 ORDER by moduleid");

??????? while($r = $db->fetch_array($query))

??????? {

?????? $modules[] = $r['モジュール'];

?????????? } ?

??????? $channelids = array();

??????? $query = $db->query("SELECT チャネル ID FROM ".TABLE_CHANNEL." WHERE islink=0 ANDdisabled=0 ORDER by channelid");

??????? while($r = $db->fetch_array($query))

??????? {

?????? $channelids[] = $r['channelid'];

??????? }

??????? $modulechannels = array_merge($modules,$channelids);

??????? foreach($modulechannels as $m)

??????? {

?????? $result = $db->query("SELECT * FROM ".TABLE_TYPE." WHERE keyid='$m'");

?????? $TYPE = array();

?????? while($r = $db->fetch_array($result))

?????? {

??????? $r['紹介']

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。