dedecms コード調査 (1) オープニング
dedecms この CMS システムは比較的強力で、比較的完全なコンテンツ公開とコンテンツ静的システム
を備えており、独自の独自のタグ システムとテンプレートを備えていることを誰もが知っておく必要があると思います。システム。テンプレート システムは、他の CMS システムが模倣するのが難しいものでもあります。この
には、依然としてある程度の開発スキルとスキルが必要です。
この一連の記事では、dedecms のシステムを研究し、どのような優れた点があるかを詳しく調べます。
まず dedecms の機能を理解することをお勧めします。まずは実際に使ってみて、システムの機能を全体的に理解してください。
この記事では、まず dedecms のコードと機能アーキテクチャについて説明します。
実際、dedecms には、アーキテクチャの観点から言えば、アプリケーション アーキテクチャ パターンはありません。これは、単なる最も単純な PHP アプリケーションです。さまざまな PHP ファイルにアクセスし、
さまざまなシステム機能を管理します。ディレクトリを見れば、各ディレクトリが何に使用されているかは誰でも推測できます。 include ディレクトリにはシステムのいくつかのパブリック関数とクラスが含まれ、
plus ディレクトリにはプラグインが含まれ、template ディレクトリにはテンプレートが含まれ、dede ディレクトリは管理バックエンド ディレクトリです。
インクルードディレクトリを開いて、そこにどんな良いものが入っているか見てみましょう。
カレンダー、時間を選択するためのjs
キャプチャ、検証コード、またはオープンソースコンポーネント
コードは無意味で、ページをめくるテキストだけ
データには、サウンド、単語セグメント、フォント、画像など、システムによって使用されるいくつかのリソースが含まれています、など。
ダイアログ 一部の AJAX ポップアップ ウィンドウのコンテンツ部分であると推定されます。これについては、
inc でいくつかの個別の関数を見つけたときに説明します。なぜ
payment 支払いインターフェイス
taglib を個別に配置する必要があるのかを検討します。これは、dedecms タグが保存されている場所です。見てください。中には dedecms と思われるファイルがたくさんあります。テンプレートには
tpllib テンプレート ライブラリとマークされていますか?まだ理解していませんが、研究が深まるにつれて理解できるようになると思います。インクルード ディレクトリ内のその他のファイルは、一般的に使用される関数やテンプレート システムなど、おそらく最も基本的な機能ファイルです。
を使って話してください
dede ディレクトリ (dedecms の管理ディレクトリ) を開いて見てください。名前を見れば、たくさんのものが入っています。
関数管理ファイル。関数ごとに 1 つのファイル。最も独創的なウェブサイト開発モデルで作られています。それを効率的と呼びましょう。結局のところ、PHPwind
やdiscuzも似たような手法で開発されています。
プログラム全体は基本的にこれらのことについてです。機能については説明しません。dedecms に詳しくない友人には、dedecms のバックグラウンド管理機能を見てもらうことをお勧めします。これは、dedecms をよりよく理解して分析するのに役立ちます。
尚、今回のコード解析は主にページ生成、表示、テンプレート処理、ラベル処理の部分を解析していますが、この
システムも今後さらに解析していきたいと考えています。関数コードはクールです。
最後に、このコード分析の旅から皆さんが何かを得られることを願っています。
Sourcejoyのdedecmsコード研究(2)インデックスからスタート
さて続きまして、今日は主にdedecmsのエントリーコードについてです。
2
まず、index.php を開いて、中身を確認します。ルートディレクトリのindex.phpを開きます。そこに表示されるのはifステートメントです。
/data/common.inc.php が存在するかどうかを確認します。存在しない場合は、インストール インターフェイスに移動します。
/data/ に移動して、このディレクトリと common.inc.php を見てみましょう。
/data/ を開くと、アップロードされた一時ディレクトリ、テンプレート キャッシュ、圧縮された一時ディレクトリ、さまざまなデータベースに
システム構成情報を保存するキャッシュ ファイルなど、多くのディレクトリとファイルが含まれています。混乱の一言です~
さて、common.inc.php を開いてみましょう。ああ、データベース接続に関連する変数を保存しているだけであることがわかりました。平たく言えば、dedecms
のデータベース接続設定ファイルで、システムインストール後に生成されると思われます。したがって、/index.php はそれが存在するかどうかを確認します。
/index.php に戻り、引き続き下を見てみましょう。2 番目の if ステートメントは、GET リクエスト「upcache」が存在するかどうかを判断し、存在しない場合は、ホームページのキャッシュを更新します。 html with 301。これは dedecms の静的ホームページでもあります (dedecms のフロントエンド ページはシステムによって生成された静的ページであることを思い出してください)。
次に何を勉強すべきか考えてみませんか?はい、これは GET リクエスト「upcache」が存在するときにホームページのキャッシュを更新する小さなコードです。
コードは次のとおりです:
require_once (dirname(__FILE__) . "/include/common.inc.php");
require_once DEDEINC."/arc.partview.class.php";
$GLOBALS['_arclistEnv'] = 'index ';
$row = $dsql->GetOne("Select * From `dede_homepageset`");
$row['templet'] = MfTemplet($row['templet']);
$pv = new PartView( );
$pv->SetTemplet($cfg_basedir . $cfg_templets_dir . "/" . $row['templet']);
$pv->SaveToHtml(dirname(__FILE__).'/index.html ');
include(dirname(__FILE__).'/index.html');
exit();
最初に /include/common.inc.php をロードします。これは、おそらく他のシステム関数をロードするいくつかの一般的な関数とファイルです。クラス。
次に、DEDEINC."/arc.partview.class.php" が再度ロードされます。前回の検証で、定数 DEDEINC に注目してください。dedecms のディレクトリ構造を観察すると、arc.partview.class.php は /include ディレクトリにありますが、/include/common.inc.php のロードは機能しません
DEDEINC 定数。DEDEINC が common.inc.php で定義されていることを示します。この定数は後で使用できます。これは、common.inc.php の一般的な機能がシステム操作の基本部分であり、すべてがこの中に含まれていることを証明しています。急いで common.inc.php に入り、
index.php の更新されたキャッシュ コードを読み続ける必要はありません。
3 番目の文はグローバル変数を設定します: $GLOBALS['_arclistEnv'] = 'index';
4 行目はテーブル 'dede_homepageset' のすべてのレコードを取得します もちろん、データベースを見ると、
はありません。 "dede_homepageset" "このテーブルは、テーブル名の前半をテーブル名のプレフィックスに置き換えるデータベース操作関連の関数であると判断します。これはどれも重要ではありません。重要なことは、この文を通じて、ホームページの関連構成情報。データベース内の dede_homepageset
テーブルを開きます。基本的に 1 つのレコードと 2 つのフィールドしかありません。もう 1 つは生成されたホームページの場所です。静的ファイル。
戻って前のコードの分析を続けます
$row['templet'] = MfTemplet($row['templet']);
$row['templet'] は MfTemplet を通じて何らかの方法で変換されたようです関数。後で調べるために MfTemplet 関数に注目します。
次のステップは、新しい PartView クラスを作成することです。名前を見ると、先ほど arc.partview.class.php をロードした目的がわかります。
この PartView クラスが何を行うかについては、引き続きコードを見てみましょう。次の 2 行を読めば、誰もが
$pv->SetTemplet($cfg_basedir . $cfg_templets_dir . "/" . $row['templet']);
3
$pv->SaveToHtml( dirname (__FILE__).'/index.html');
ビュー オブジェクト (PartView クラスのインスタンス。これをビュー オブジェクトと呼びます) を作成し、テンプレートを設定し、SaveToHtml を介して指定された場所に最後に生成されたページを書き込みます。方法。
ホームページが生成されたら、次のステップは生成された静的ファイルをインクルード形式で表示し、終了してページ解析を中断します。
この時点で、/index.php は分析されています。
最初に /data/common.inc.php を渡して、dedecms がインストールされているかどうか、またはデータベース構成情報が定義されているかどうかを判断し、後続の操作の基礎を築きます。
次に、GET リクエスト「upcache」があるかどうかを確認し、ある場合は /include/common.inc.php をロードしてシステムを初期化し、
partview クラスの関連メソッドを呼び出して静的ホームページ ファイルを生成します。最後に表示します。
この観点から見ると、dedecms にはそれほど多くの秘密はありません~
しかし、私たちの記事にはいくつかの疑問も残っています:
1) /include/common.inc.php がロードされた後、そこでどのような作業が行われますか?
2) /include/arc.partview.class.php は何をするものですか? /include/ の下にある arc で始まる多くのファイルは何ですか?
3) MfTemplet 関数は文字列テンプレート ファイル パスに対して正確に何をしますか?
4) partview クラスの関連メソッドの秘密は何ですか?
これらの疑問を持ってこの記事を終了し、次の記事でこれらの謎を一つずつ明らかにしていきます。
sourcejoy の dedecms コード調査 (3) Partview の混乱
前回、dedecms のindex.php ファイルから多くの情報を学び、いくつかの疑問も提起しました。この記事は以前の質問から始まります。
dedecms の続きを見てみましょう。 。
まず、index.php ファイルについての以前の研究で要約した内容を確認しましょう。
最初にcommon.inc.phpをロードし、次にテンプレートを整理し、静的ページを生成し、静的ページにジャンプします。
次に、common.inc.php の内容を見てみましょう。 /include/common.inc.php を開くと、中のコメントがより明確になります。構造について大まかに話しましょう。
まず、一連の定数を定義します。次に、セキュリティ対策を講じ、PHP システム環境をいくつか設定する必要があります。コード内のコメントは非常にわかりやすく書かれています。
次のステップは、dedecms のシステム構成パラメーター ファイルをインクルードすることです: require_once(DEDEDATA."/config.cache.inc.php");
ファイル名を見ると、この構成ファイルは構成のキャッシュである可能性があると推測されます。データベース内の情報。
次に、データベース構成情報ファイルがロードされます: require_once(DEDEDATA.'/common.inc.php');
このファイルはデータベース内の情報に基づいて生成されるキャッシュではなく、dedecms のインストール時に生成されます。前回の記事では、
index.php ファイルから dedecms がインストールされているかどうかを確認することは、このファイルが存在するかどうかを確認することであると述べました。
次に、サイトのルート ディレクトリ、テンプレート ディレクトリ、プラグイン ディレクトリ、データ ディレクトリなどの多くのディレクトリを整理し、多くの変数も整理しました。最後に、データベース操作クラス dedesql.class.php と共通関数ファイル common.func.php がロードされました
4
さて、common.inc.php の謎が明らかになりました。最も基本的なこと。
次に、dedecms のキーとなる arc.partview.class.php を確認する必要があります
channelunit.class.php、typelink.class.php、ftp.class.php がロードされます
以下は、パートビュークラスLa
index.php ではpartview クラスの SetTemplet メソッドと SaveToHtml メソッドが使用されているため、より深く掘り下げやすくするために、これら 2 つのメソッドから始めます。
最初にpartviewのコンストラクターを見てみましょう。
DedeTagParseクラスのインスタンスを作成しました。名前はタグ解析クラスです。次に、いくつかのパラメータを設定します。
次に、新しい TypeLink クラスを作成し、一連のパラメーターを設定します。とても混乱しました。
SetTemplet を見てください。ああ、これはとても簡単です。
まず、DedeTagParse クラスの LoadTemplet メソッドを使用してテンプレートを読み込みます。
次に、Fields 配列のいくつかの要素を設定します。
最後に、ParseTemplet メソッドを呼び出します。
ParseTemplet メソッドは、$GLOBALS 配列の多数の要素を取得し、MakeOneTag 関数を呼び出します。わかりにくいです
SaveToHtml メソッドを見てみましょう。最初のステップはディレクトリを作成し、最後に DedeTagParse の SaveTo メソッドを使用してファイルに保存します。
う~ん、迫力がないですね。
見たものを振り返って考えるしかありません〜
さて、ホームページを生成するために、理解できないpartviewクラスを作成し、一見万能に見えるDedeTagParseメソッドを呼び出してテンプレートを解析して生成しました静的ファイル。
以上です。
他にも関数やクラスが混在していますが、何といってもこのDedeTagParseに注目して、次回は重点的に解析していきたいと思います。
今日はここまでです、鳥の〜はごちゃごちゃしすぎて構造が全くありません〜
sourcejoyのdedecmsコード研究(4)パートビューを歩き続ける前に
、沼に落ちたように無限の変数と配列要素が見えました、何か不可解です私たちの前に置かれました。現在も、私たちはパーツビューの泥沼から抜け出す方法を見つけようと、懸命に前進し続けています。
前の記事では、partview クラスをランダムに分析しましたが、その中には大量の変数が含まれていました。
最も明確なのは、ホームページを生成するためのいくつかの重要な場所しかわかっていなかったということです。 DedeTagParse クラスの LoadTemplet メソッドと SaveTo メソッドを呼び出します。 partview クラスによって定義されたファイル ヘッダーには、いくつかのファイルが含まれています。partview を避けて、最初にこれらの含まれているファイルを見てみましょう。
require_once(DEDEINC.'/channelunit.class.php');
require_once(DEDEINC.'/typelink.class.php');
require_once(DEDEINC.'/ftp.class.php');
5
ftp. Class.php は言うまでもなく、ftp 関連の操作クラスです。以前にパートビューのコードを見たときに、静的ファイルを生成するときに ftp
関連のメソッドが使用されていることがわかりました。これにより、リモートからファイルを書き込むことができるようです。 FTP の操作方法については、実際には PHP の関数ライブラリに ftp をはじめとする関連関数がカプセル化されています。コードは非常に単純なので、詳細は説明しません。
typelink.class.php、partview コードでも見ましたので、開いて見てください。コードを簡単に確認すると、各メソッドが指定されたタイプのリンク HTML 文字列を要求していることがわかります。
実際のところ、dedecms では type が列を指すのではないかと漠然と感じています。これが事実かどうかはわかりません。
もう一度channelunit.class.phpを見てみましょう。
中には ChannelUnit クラスの定義があり、この ChannelUnit クラスは使用されていないことがわかりました。だからまだ彼に会いに行かないでください。 2 つのファイルが追加されていることに気付きました:
require_once(DEDEINC."/dedetag.class.php");
require_once(DEDEINC."/channelunit.func.php");
dedetag.class。それを開いて、ほら、これは非常に複雑ですが、テンプレートを解析してファイルを生成するために使用される DedeTagParse クラスが含まれていることがわかりました。はは、まず覚えておいてください。
後でゆっくり勉強します。
channelunit.func.phpにはどのような関数がありますか?それを開いて見てください。この種の情報を取得するための変数といくつかの関数が存在します。MfTemplet と MakeOneTag という 2 つの関数が、index.php で使用されていることがわかりました。戻って、index.php を開いて、それがどのように呼び出されているかを確認します。値 .htm はテンプレート ファイルのパスです。次に、MfTemplet 関数が何を行うかを見てみましょう。
//テンプレートディレクトリのルール
function MfTemplet($tmpdir)
{
$tmpdir = str_replace("{style}",$GLOBALS['cfg_df_style'],$tmpdir);
$tmpdir = ereg_replace("/{1, }","/",$tmpdir);
return $tmpdir;
}
コメントには「テンプレート ディレクトリのルール」と書かれています。コードをもう一度見てください。ああ、少し理解できたみたいです。テンプレートのパスを置き換えるだけです { style} は、グローバル変数
$GLOBALS['cfg_df_style'] の値です。おそらく、異なるテンプレート セットの使用に関係があると思われます。それが大きな重要性を持たない場合、私たちはそれを研究し続けることはありません。
partview クラスの ParseTemplet メソッドにある別の関数 MakeOneTag を見てみましょう。このメソッドは名前に基づいてテンプレートを解析します。このメソッドのコードのほとんどは、それが何を行うかは明らかではありません。文はMakeOneTag関数を呼び出します。この関数は主にテンプレートを解析するために使用されるようです。次のように使用します:
MakeOneTag($this->dtp,$this);
最初のパラメータは DedeTagParse クラスの強度であり、2 番目のパラメータは Partview クラス インスタンスのハンドルです。
channelunit.func.php のこの関数が何をするのか見てみましょう。
うーん、はっきりと分かっていないことが多いので、大まかにしか見ることができず、落ち込んでいます。
これは、/include/taglib/ の下にある lib サフィックスを持つすべてのファイルを走査し、ファイル パスを配列に追加してから、DedeTagParse クラスの CTag を走査します。
6
DedeTagParse クラスを学習していないため、このセクションは利用できません。とりあえずは理解できますが、それは小さな進歩であると考えられます。パートビューに戻ってもう一度見る必要があるようです。
コンストラクターは特別なものではなく、DedeTagParse クラスのインスタンスを作成し、いくつかの設定を行うだけです。 index.php は、partview インスタンスの作成後に SetTemplet メソッドを実行することがわかります。SetTemplet メソッドをもう一度見てみましょう。
ここでDedeTagParseクラスインスタンスのLoadTempletメソッドを呼び出しています。 どうやらここからコクーンを剥がす必要があるようです。
もう分析できません~
次回のためにいくつかの質問を残してください。
1) DedeTagParseクラスのLoadTempletメソッドについて説明します。
2) MakeOneTag は一体何をしているのでしょうか?
さらに先に進むには、DedeTagParse クラスの LoadTemplet メソッドを徹底的に理解するしかないようです。現時点ではまだ混乱しています。
sourcejoy の dedecms コード研究 (5) は DedeTagParse から始まります
以前、私たちは dedecms の周辺部にいて、さまざまなグローバル変数とさまざまな呼び出しに混乱していましたが、重要な手がかりである DedeTagParse クラスをつかんで、それを理解するために研究しました。多くのことを理解することができます。
この NB の DedeTagParse クラスを見てください。
まず、コンストラクターを見てみましょう。これは特別なものではなく、一連の初期化パラメーターを設定するだけです。
次に LoadTemplet メソッドを探してみましょう。
調べてみると、LoadTemplet メソッドが実際には LoadTemplate メソッドを指していることがわかりました。著者の英語はそんなに下手なのでしょうか?
LoadTemplate メソッドを見てください。
まず SetDefault メソッドを使用していくつかの初期変数を設定します:
$this->SourceString = '';
$this->CTags = '';
$this->Count=-1;
次にテンプレートを判断しますファイルが存在するかどうか。次に、さまざまな状況に応じて $this->SourceString に値を割り当て、$this->ParseTemplet(); メソッドを呼び出します。
このコードを見ると、作成者の開発スキルを向上させる必要があることがわかります。これはすでに 5.6 ですが、コードのリファクタリングはまだひどいです。なぜ $this->ParseTemplet(); ができないのでしょう。
if の外側に配置されますか?
ファイルが存在しない場合、$this->SourceString に「ファイルが存在しません」という文を入れて、$this->ParseTemplet(); を呼び出すのは非常に簡単です。
ファイルが存在する場合、fgets はファイルの内容を読み取り (問題、file_get_contents を使用しないのはなぜですか)、次に別の if を使用して
$this-> の戻り値を通じてキャッシュがあるかどうかを判断します。 LoadCache($filename) が true を返した場合は、キャッシュされたテンプレートが読み取られたことを意味し、空の文字列を返します (どうすればよいでしょうか?戻り値が無責任すぎます)。 false を返した場合は、$this を呼び出します->ParseTemplet(); 再度テンプレートを解析します。
LoadTemplate もほぼ同じです。テンプレート ファイルの内容を読み取り、キャッシュがあるかどうかを確認するだけです。キャッシュがある場合、テンプレートは解析されません。それでおしまい。
次に、$this->LoadCache メソッドを見てみましょう。すごい量のコードがあります。
7
まず、$this->IsCache を使用してキャッシュが許可されているかどうかを判断します (この属性は DedeTagParse クラスがインスタンス化されるときに設定され、テンプレート キャッシュ パラメーター $cfg_tplcache が dedecms のシステム構成に追加されるかどうかに関連します)。これは DedeTagParse のクラスのコンストラクターに反映されます。dedecms のインストール後、デフォルトのシステム構成は true なので、ここでのデフォルトは true です)。これが false の場合、$this->LoadCache は続行せずに false を返します。 . LoadTemplate
メソッドでは、この戻り値に基づいて解析テンプレートが決定されます。
$this->IsCache を渡した後、プログラムは続行します。以下は、現在のテンプレート ファイルに対応するキャッシュを見つけることです。
dedecms のファイル キャッシュは少し特殊で、テンプレート キャッシュ ディレクトリ (data/tplcache) を観察すると、同じ名前のファイルが多数あることがわかります。 。コードから確認してみましょう。
前述したように、LoadCache メソッドで $this->IsCache レベルを渡しました。次に、次のコードを見てみましょう。
$cdir = dirname($filename);
$cachedir = DEDEROOT.$cfg_tplcache_dir;
$ckfile = str_replace($cdir,'',$filename).substr(md5($filename),0,16).'.inc';
$ckfullfile = $cachedir. '/'.$ckfile ;
$ckfullfile_t = $cachedir.'/'.$ckfile.'.txt';
最初の 3 つの文は、キャッシュ ファイル名をスペルなしで取得する方法です。ディレクトリにアクセスし、それを md5 でハッシュし、そのハッシュを取得します。文字列の最初の 16 文字を取得し、
の後に「inc」サフィックスを追加します。
文4は完全なキャッシュファイル名を取得するものです。
5 番目の距離は、別のファイル名のようです。これは、キャッシュ ファイル名の後にサフィックス「.txt」を追加することです
上記で 2 つのファイル名が得られましたが、2 番目のファイル名が何であるかはわかりません。続けましょう以下のコードを見てみましょう。
$this->CacheFile = $ckfullfile;
$this->TempMkTime = filemtime($filename);
if(!file_exists($ckfullfile)||!file_exists($ckfullfile_t))
{
return false;
}
最初の文は現在のテンプレートのキャッシュを指定しますファイル
2 番目の文は、ファイルの最終変更時刻を読み取り、時間属性を設定します。これはまだ明確ではありません。
次の if ステートメントは、テンプレートの 2 つのキャッシュ ファイル (上で結合した 2 つのファイル) が見つからない場合に false を返し、LoadTemplate メソッドでテンプレートを解析します。
テンプレートのキャッシュ ファイルが利用可能であると想定し、コードの確認を続けます。次のコード スニペットはコメント化されており、テンプレートの最終更新時刻を検出するものです。コードは非常に単純で、上記の $ckfullfile_t 変数で指定された txt ファイルを開いて、内容を比較します。キャッシュ変更時刻を含むコンテンツ。元の .txt ファイルは、キャッシュされたファイルの保存時間を保存するために使用されます。時間が一致しない場合は、false を返し、LoadTemplate メソッドにテンプレートを解析させます。
キャッシュが有効であると想定しているので、続行できます。
キャッシュが有効な場合、キャッシュされたファイルが含まれます。
これはキャッシュ ファイルに基づいて詳細に分析されるので、index.htm テンプレートが読み込まれていると仮定します。tplcache で、
8
サフィックスが inc である、index.htm で始まるファイルを見つけて開きます。
これは抜粋です:
$z[0]=Array("global","",236,264);
$z[0][4]['name']="cfg_soft_lang";
$z[1] =Array("グローバル","",277,303);
$z[1][4]['name']="cfg_webname";
$z[2]=Array("グローバル","",347,377) ;
$z[2][4]['name']="cfg_description";
$z[3]=Array("グローバル","",414,441);
$z[3][4][' name']="cfg_keywords";
......
LoadCache メソッドに戻ります。
先ほども述べたように、テンプレートキャッシュファイルがインクルードされているので、次のif文でキャッシュファイル内の情報配列「$z」が正常かどうかを判定します。正常であれば、このforeachループが実行されます。 。コードを見てみましょう。
foreach($z as $k=>$v){
$this->Count++;
$ctag = new DedeTAg();
$ctag->CAttribute = new DedeAttribute();
$ctag-> ;IsReplace = FALSE;
$ctag->TagName = $v[0];
$ctag->InnerText = $v[1];
$ctag->StartPos = $v[2];
$ctag ->EndPos = $v[3];
$ctag->TagValue = '';
$ctag->TagID = $k;
if(isset($v[4]) && is_array($v[ 4])){
$i = 0;
foreach($v[4] as $k=>$v){
$ctag->CAttribute->Count++;
$ctag->CAttribute-> ;Items[$k]=$v;
}
}
$this->CTags[$this->Count] = $ctag;
}
これは、キャッシュ情報配列を走査し、各 $zこのソースコードを見ると、$z 配列要素の 0 がタグ名 (TagName) であることがわかりました。 、1は内部テキスト(InnerText)、2は開始位置(StartPos)、
3は終了位置(EndPos)です。新しい DedeTag オブジェクトの tagID は配列インデックスです。
ここにはループもあります。これは、$z 配列の各要素の 4 番目のサブ要素です。次に、関連する値を現在の DedeTAg オブジェクトの DedeAttribute オブジェクトに割り当てます。
これを見ると、私たちは何かを理解しているようです。
1) tplcache に保存されるのは、解析されたテンプレートではなく、情報配列の束です。
2) 情報配列には、テンプレート ページに含まれるすべてのタグの情報が格納されます。
3) 上記のループは、実際にキャッシュ内のタグ情報を DedeTAg オブジェクトに読み書きし、それを現在の DedeParse クラスの CTags 配列に保存します。現時点では、DedeParse の現在のインスタンスがテンプレートのコンテンツを取得します。 $this->SourceString)、テンプレート上のすべてのタグ情報 ($this->CTags
)。
上記の操作が完了したら、LoadCache メソッドについては終了です。キャッシュの読み取りが完了したので、安全に LoadTemplate メソッドに戻って分析を続行できます。
sourcejoy の dedecms コード調査 (6) ParseTemplet アルゴリズム分析
国慶節の連休中に体調を崩し始めましたが、回復してから、フラフラになりながら、ようやく更新を続けることができました。 。今日は dedecms の最も重要なこと、テンプレート分析について話します。
まず dedecms タグを見てください。誰もが次のことを考えています:
{dede:arclist row=10 orderby=pubdate type='image.' imgwidth='143' imgheight='106'}
{ /dede:arclist}
上記のタグを参照することでさらに分析することができます。
ここでは、dedecm のタグ形式、タグ形式、タグの種類をすでに理解していることを前提としています。
分析を始めましょう
まず、メソッドの前に初期化される最も基本的な変数のいくつかを見てみましょう:
1) タグの開始シンボルと終了シンボル。例: "{" と "}"
$TagStartWord = $this->TagStartWord;
$TagEndWord = $this->TagEndWord;
2) 一時変数を設定して、見つかった新しいタグの開始位置と終了位置をテンプレート内で一時的に保存します。
$sPos = 0; $ePos = 0;
3) 完全なラベルの開始文字列と終了文字列を設定します。例: "{dede:" this form
$FullTagStartWord = $TagStartWord.$this->NameSpace.":";
$sTagEndWord = $TagStartWord."/".$this->NameSpace.":";
$eTagEndWord = "/".$TagEndWord;
ここで、終了部分には 2 種類あり、1 つは {aa:ff /} の単一構造タグに似ており、もう 1 つは {aa:fff に似ていることに注意してください。 }{ /aa:fff} は構造タグに準拠します
4) タグの実際の文字列 ({dede:) の長さとテンプレート全体の長さを取得します
$tsLen = strlen($FullTagStartWord);
$sourceLen=strlen ($this->SourceString) ;
上記は初期変数設定部分です。
次のステップは簡単な判断で、テンプレート全体の長さがラベルの開始文字列の長さに 3 を加えた値を超えていない場合は終了します。
if( $sourceLen return;
}
なぜ 3 を追加する必要があるのですか (つまり、テンプレートの長さは、少なくともラベル開始文字列の長さに 4 を加えたものである必要があります) ?
10
記述できる最短のタグを見てみましょう:
{dede:a/}
コロンの後には可能な限り短い文字列である 3 があり、3 未満の場合は最小のタグですら Complete にすることができません。したがって、この判断をするのに、
が等しい限り、個人的には不要だと思います。
それでは、次の 2 つの文を読み続けてください:
$cAtt = new DedeAttributeParse();
$cAtt->charToLow = $this->CharToLow;
DedeAttributeParse クラスを作成し、CharToLow 属性を設定します。 name はタグ属性解析クラスである必要があり、charToLow は
文字列を自動的に小文字に変換するかどうかです。
次のステップは長い for ループで、テンプレート文字列の各文字を走査して、テンプレート内のタグを分析して抽出します。
for($i=0; $i この for ループがどのように分析されるかを見てみましょう
まず、現在見つかったタグの名前を保存する一時変数を定義します
$ tTagName = ' ';
以下は判断です。コメントは非常に明確ですが、まだ理解できていないので、まずそのような判断があることを知っておく必要があります
//この判断を下さないと、私たちはマーク
if($i-1 >= 0){
$ss = $i-1;
}else{
$ss = 0;
}
は、接続された 2 つを識別できません。変数 $ss については、後で注意してください。
以下はタグの検索です
$sPos = strpos($this->SourceString,$FullTagStartWord,$ss);
$isTag = $sPos;
で指定された位置から始まるテンプレート文字列の最初の位置を検索します$ss 「{dede:」と同様のタグヘッダーの位置を指定し、$isTag 変数を strpos の戻り値に設定します。これは、タグが見つかった場合にそれを意味することを明確に示す必要があります。本当です、どのキャラクターでもありません。
ここでは、検索の開始位置を設定するために $ss が使用されていることがわかります。
続きを読んでみましょう
次のif文は、先頭文字がラベルで始まる場合の補足のようでしょうか?
この文はどういう意味ですか?それは余計なことですが、もっと良い方法があるはずです。もう言うことはありません。
以下の if は、タグが見つからない場合はループせず、説明がないことを意味します。
またサブループです
for($j=($sPos+$tsLen);$jTagMaxLen);$j++)
$tsLen 前に述べたように、はタグヘッダー({dede:)の長さです
すると、このforの説明は、タグヘッダーの次の文字から開始してタグの最大長で終了するまでの間のすべての文字を走査することであるようです。タグ名を探しています
タグの名前を見つけるために、もう一度 for ループ内をいくつか見てください。
if($j>($sourceLen-1)){
break;
}else if( ereg("[/ trn]",$this->SourceString[$j]) || $this->SourceString [$j] == $this->TagEndWord ){
break;
}else{
$tTagName .= $this->SourceString[$j];
11 http://www.pprar.com
}
このforのif文、名前の終わりには文字位置がテンプレートの単語の1つ後ろの場合と、スペース、改行、タブ文字、/
などが入っている場合の2通りがあります。見つかった、またはタグの終了文字が見つかった (例: "}")
この for ループを通じて、タグの名前が見つかり、変数 $tTagName に保存されます。
以下は $tTagName 変数が空かどうかを判断するための非常に長い if ステートメントで、空の場合はループから抜け出します (タグが間違っています)。しかし、飛び出す前に $i が設定されています。読めません。
次の重要なポイントは、タグ名を見つけることです。
最初にいくつかの変数を設定します
$i = $sPos+$tsLen;
$endPos = -1;
$fullTagEndWordThis = $sTagEndWord.$tTagName.$TagEndWord;
ループテンプレート文字列のポインタ$iを先頭にジャンプしますタグ名 場所。次に、変数 $endPos を -1 に設定して、タグ終了文字 ({/dede:xxx}) を結合します
次のステップは、$eTagEndWord (/})、$FullTagStartWord ({dede:)、$fullTagEndWordThis の 3 つの場所を見つけることです。 ({/dede:xxx})
$e1 = strpos($this->SourceString,$eTagEndWord, $i);
$e2 = strpos($this->SourceString,$FullTagStartWord, $i);
$e3 = strpos($this-> SourceString,$fullTagEndWordThis,$i);
$e1 はタグ名が見つかった後に最初の「/}」が出現する位置、$e2 は最初の「{dede:」が出現する位置、$e3 はfirst {/dede:xxx} が出現する位置。ここで、$e3 値を取得するとき、$fullTagEndWordThis は、現在見つかっているタグにちなんで名付けられた終了文字列であることに注意してください。
次の文は、$e1 $e2 $e3 の値を統一するため、探しているラベル文字列が見つかった場合はこれら 3 つの変数の位置が保存され、見つからなかった場合は - 1 が保存されます。 $e2 = トリム($e3);
$e1 = ($e1=='' ? '-1' : $e1);
$e2 = ($e2=='' ? '-1' : $e2);
$e3 = ($e3=='' ? '-1' : $e3);
次のステップこれら 3 つの値に基づいて何らかの処理を実行することです。何を対処すればよいでしょうか?まずこのコードを見てみましょう:
//not found '{/tag:'
if($e3==-1) {
$endPos = $e1;
$elen = $endPos + strlen($eTagEndWord) ;
}
//見つかりません '/}'
else if($e1==-1) {
$endPos = $e3;
$elen = $endPos + strlen($fullTagEndWordThis);
}
//見つかりました'/}' で '{/dede:'
else{
//if '/}' が '{dede:'、'{/dede:' に近く、終了タグは '/}'、else は '{ /dede:'
if($e1 $endPos = $e1;
$elen = $endPos + strlen($eTagEndWord);
}else{
12
$ endPos = $e3;
$elen = $endPos + strlen($fullTagEndWordThis);
}
}
dedecms タグを終了するには 2 つの方法があることがわかっています。1 つは (/})、もう 1 つは ( {/ dede:xxx}) の場合、
これら 2 つの末尾がない場合は、テンプレート内のタグが不完全であるという 1 つの問題のみを意味します。この if ステートメントは、ラベルを終了するには 2 つの方法のいずれかが必要であることを前提としています。
ifの最初の分岐は、$e3が-1、つまり(/})が存在すると仮定すると、このようにラベル終了文字位置変数$endPosが変数$e1の値に設定され、 、
ラベルは最後に $endPos に (/}) を加えた長さの終了位置がわかります。
if ステートメントの 2 番目のブランチは最初のブランチと似ていますが、({/dede:xxx}) が見つかると想定されている点が異なります。
if ステートメントの else 部分は、両方が見つかることを前提としています (これは可能ですか?)。(/}) 終了文字が次のラベルの開始位置
よりも高い位置にある場合は、さらなる分析が必要です。位置は前であり、$e3 の終了文字 ({/dede:xxx}) よりも前です。つまり、現在見つかっている (/}) が現在のタグの終了文字であることを意味します。それ以外の場合は、({ /dede:xxx) }) こういうこと。
$e1 $e2 $e3 の変数設定と if ステートメントにより、最終的に、現在のラベル終了文字の開始位置と終了位置である $endPos と $elen の 2 つの変数が取得されます。
以下は別の if ステートメントで、endPos が -1 であるかどうかによって、現在のタグが正しく終了しているかどうかを判断します。正しく終了しない場合は、テキストを出力してループを終了します。たとえば、テンプレート分析をより迅速に行うために、テンプレート分析を実行する前に、誤ったタグをエラー メッセージに置き換えたり、構文が正しいかどうかをチェックしたりするなど、この設計を改善できるでしょうか。
さらに下を見ると、さらに 2 つの変数が設定されています。
$i = $elen;
$ePos = $endPos;
現在のループが探しているラベルが見つかったので、メインループのループ変数 $i が次のラベルの開始位置に設定されます。
現在のラベル $ePos の終了文字の開始位置を設定します。
現在のラベルの開始位置と終了位置が決定されました。次に、ラベルのプロパティを分析しましょう。
$attStr = '';
$innerText = '';
$startInner = 0;
3 つの変数、タグ内に 2 つのものがあり、1 つは属性文字列、もう 1 つはコンテンツ文字列であることがわかりました。 $startInner 変数は、コンテンツ文字列が始まるかどうかを示します (ブール値を使用しないのはなぜでしょうか)。
次の for ループは、ラベル名の末尾から終了文字の前の部分までの文字列の抽出を開始します。
for($j=($sPos+$tsLen);$j ループ内で属性文字列とコンテンツ文字列がどのように抽出されるかを見てください。
if($startInner==0 && ($this->gt;SourceString[$j]==$TagEndWord && $this->gt;SourceString[$j-1]!="\") ){
$startInner=1 ;
続行;
}
if($startInner==0){
$attStr .= $this->SourceString[$j];
}else{
$innerText .= $this->SourceString[$j] ];
}
そうですね、2 つの if ステートメントが使用されます。最初のステートメントは、コンテンツ文字列が開始されているかどうかを判断するために使用されます。 2 番目の if ステートメントは、コンテンツ文字列の開始インジケーターに基づいて判断され、
13
コンテンツ文字列と属性文字列をそれぞれ読み取ります。
個人的には、特別な識別子を使用して切り詰めた方が速いと思います。
ここで別の質問があります: コンテンツ文字列が始まるかどうかをどのように判断するか?
最初の if を見てみましょう
if($startInner==0 && ($this->SourceString[$j]==$TagEndWord && $this->SourceString[$j-1]!="\" ) )
$startInner==0 この文はフィルターです。コンテンツ文字列を読み取る場合、キーは && の後の括弧内のコンテンツです。
現在の文字がタグの終了文字$TagEndWord(})で、終了文字の前の文字がバックスラッシュでない場合、属性部分は終了しています
バックスラッシュの場合は、テンプレートコンテンツなどであることを意味します。
上記の for ループを通じて、現在のタグの属性とコンテンツを抽出し、
$cAtt->SetSource($attStr);
if($cAtt->cAttributes-) の分析を開始しました。 > ;GetTagName()!=''){
$this->Count++;
$CDTag = new DedeTag();
$CDTag->TagName = $cAtt->cAttributes->GetTagName();
$ CDTag->StartPos = $sPos;
$CDTag->EndPos = $i;
$CDTag->CAttribute = $cAtt->cAttributes;
$CDTag->IsReplace = FALSE;
$CDTag- > ;TagID = $this->Count;
$CDTag->InnerText = $innerText;
$this->CTags[$this->Count] = $CDTag;
}
属性分析クラス La による分析次に、DedeTag タグ クラスのインスタンスを作成し (つまり、タグ オブジェクトを作成し)、現在のタグのすべての属性をこの
タグ オブジェクトに入れます。
タグ名、開始位置、終了位置、属性配列、内部文字列などが含まれます。
次に、この新しいタグ オブジェクトを DedeTagParse クラスの CTags 配列に配置します。
このようなタグの解析が完了し、一番外側のforループが終了しました。ループごとに解析できるタグは 1 つだけであり、タグの数だけループできることがわかります。
テンプレート全体の解析が完了した後、キャッシュが許可されている場合は、再度 SaveCache メソッドを呼び出して、現在のテンプレートのタグ情報をキャッシュ ファイルまたは中間情報ファイルに保存します。
テンプレート分析が完了したので、すべての情報が利用可能になり、LoadTemplate メソッドに戻って続行できます。
sourcejoyのdedecmsコード研究(7) MakeOneTag
最近忙しすぎてWebサイトの更新ができず、本も長い間読んでいませんでした。今日自由な時間があれば、まだ終わっていない仕事を続けてください。今日は前回に引き続き、dedecms
の静的ページ生成処理についてお話します。
簡単に復習すると、以前は、ホームページの動的ファイルのindex.phpがホームページのテンプレートを初期化するためにarc.partview.class.phpを呼び出していましたが、ホームページのテンプレートを設定する際に、arc.partview.class.phpがDedeTagParseを呼び出していました。そして、テンプレートのキャッシュまたはシリアル化されたファイルを生成します。テンプレートは解析されましたが、この解析はテンプレート内のすべてのタグの位置とそのパラメータを記録するだけであり、これらのことは次に行われると推定されます。
partview の SetTemplet メソッドに戻り、$this->dtp->LoadTemplet($temp); という文から見てみましょう。
14
if($this->TypeID > 0) の下の if ステートメントは、現在のページの「パンくずナビゲーション」とタイトルを設定します。 dedecms を使用したことがあり、dedecms システムの操作に精通している場合は、この if の配列要素 $this->Fields['title'] がページ テンプレートのフィールド配列の多くの場所で使用されていることを知っているはずです。ウール生地を使用しています。
2 つの変数を設定した後、ParseTemplet を呼び出してテンプレートを解析します。
この ParseTemplet は非常にシンプルで、多くのグローバル変数がページ内で使用されていることが一目で分かります
。 ParseTemplet メソッドの最後の文である MakeOneTag($this->dtp,$this); に気付きました。これまでの内容は実質的なものではないため、これは非常に重要です。この機能を見つけて見てください。
まず MakeOneTag 関数のパラメーターを見てみましょう。最初の 2 つのパラメーターは参照によって渡され、2 番目のパラメーターは渡された
partview のインスタンスです。
ループの使用を開始して、システムが所有するすべてのタグのリストを取得します
$dh = dir(DEDEINC.'/taglib');
while($filename = $dh->read()){
if(ereg (".lib.",$filename)){
$alltags[] = str_replace('.lib.php','',$filename);
}
}
$dh->Close();
コードは非常に単純です。/include/taglib ディレクトリを走査し、ファイル規則に従ってファイル名を取得し、すべてのタグの配列を形成します。
次のステップは、partview クラスでインスタンス化された DedeTagParse のインスタンスの CTags 属性を走査し、現在のテンプレートを解析する大きな foreach 配列です。
DedeTagParse の以前の分析から、CTag が実際にはすべてテンプレートで使用されていることがわかります。これはタグとそのパラメータの単なるコレクションです。ここでは、値の割り当てや置換などを行うために、これらのテンプレートのタグを調べ始めます。
この foreach が何をするのか見ていきましょう。
まずループ内の現在のラベルの名前を取得します。
次のステップは、フィールドという名前のラベルに対する操作です。
フィールドタグの場合は、まずタグのname属性を取得します。名前が配列の場合は、DedeTagParseのAssignメソッドを使用してパーツビューを割り当てます。Fields 配列は、タグ名に対応する value 属性に割り当てられます (詳細については、「割り当てコード」を参照してください。比較的単純であるため、ここでは省略します)。ラベル名属性が配列でない場合は、
partview の Fields 配列で指定された名前の値を、ラベルの対応する値に割り当てます。以下の else は他の判断を行うのに非常に簡単で、その後フィールド タグが解析されるため、フィールド タグが変数と同等であることがわかります。解析後、ループ分析を続けます。ラベル。
次の 2 つの if は、arclist に多数のタグ名があることがわかります。
次のステップは、テンプレート内のタグに対応するシステム タグがあるかどうかを確認することです。存在する場合は、それらを対応するファイルにロードします。 、対応する関数を呼び出し、関数の戻り値をテンプレート タグに対応する値に代入します。
このようにして、テンプレート全体のタグに値が割り当てられました。
システム内のタグ(/include/taglib/配下のタグ解析ファイル)は、実際にはデータベースのデータを読み込み、データを整理して出力する機能です。
このセクションはここで終了します。主に、分析されたテンプレート タグが最終データにどのようにバインドされるかについて説明します。実際、テンプレート分析中に、現在のテンプレートで使用されているすべてのタグをすでに取得しているため、次に必要なのは、タグを走査し、さまざまなタグ関数を呼び出し、関数の戻りデータを取得することだけです。
気配りのある友人の中には、まだすべてのデータが揃っていないことに気づく人もいるでしょう。静的ファイルを生成するにはどうすればよいですか?
これについては次のセクションで説明します。
15
添付ファイル: dedecms (v5.6) システムディレクトリ
a /* HTML を生成するディレクトリ */
|data /* プログラムによって生成された共通データを保存するディレクトリ */
| |admin /* の一般的な設定を保存します作成者、クイック ナビゲーション、ソースなどのシステム バックグラウンド。テキスト形式で保存されます*/
| |backupdata /* データベース バックアップ ストレージ ディレクトリ。システム バックグラウンド設定で変更できます*/
| |cache /* システム キャッシュ*/
| |enums /* 生成されたキャッシュと js ファイル */
| |js /* 列 js 呼び出しによって生成された js ファイル */
| |mark /* 画像ウォーターマーク設定ディレクトリ */
|モジュール インストール パッケージがシステム バックグラウンドで保存されるディレクトリ。通常、ファイル名は暗号化されます。 */
| |rss /* 生成された RSSmap が保存されるファイル ディレクトリ */
|ログイン後にセッションが生成されます。ディレクトリは書き込み可能である必要があります。 */
| テキスト データ、システム バックグラウンドでテキスト データ ストレージ ディレクトリとして保存されます。 */
|キャッシュは通常、これらの動的ページです*/
| |ziptmp /* 圧縮キャッシュ ディレクトリ*/
|dede / * システム バックエンド管理ディレクトリ*/
| |inc
| |templets|テンプレート保存ディレクトリ*/
|images
| |images
|include /* システムコアクラスライブラリ*/
|日付編集ボックスから飛び出すカレンダーボックス*/
| |code /* datalistcp 動的ページングクラス コーディング言語パッケージ */
| |data /* シソーラスのデフォルト検証コードなどのシステムコア設定データ */
| Dialog /* システム ダイアログ ボックスの保存ディレクトリ。エディタの選択はサムネイルと同様です。 File *
| |FCKeditor /* エディタの保存ディレクトリ。オープン ソース エディタ FCK を使用します。 |editor
| | | | | | | | | | | | | |fck_image
| | |js
|
| |taglib /* テンプレートで使用されるタグが保存されるディレクトリです */
| |channel /* いくつかの特殊なフィールドを解析する拡張関数ライブラリ */
| |
| |tpllib /* 動的テンプレート タグ、通常は動的呼び出しページで使用されます*/
|install /* インストール ディレクトリ*/
| |templates
|member / * メンバー センター ディレクトリ*/
| | ||pay
| |js
| |支払いインターフェイスの設定*/ | |nps
| | |yeepay
| | コーヒー
| | | |画像
| | |画像
| | |templets
|plus /* システム プラグイン ディレクトリ*/
| |images
| |paycenter
| |アリペイ
|| |task
|special /* 特別なトピックの保存ディレクトリ*/
| |default /* システムのデフォルトのテンプレートのディレクトリ*/
| photo
| |js
| |style /* デフォルトのテンプレートに保存される CSS スタイル*/
| |plus /* プラグイン ページのテンプレート ファイルの保存ディレクトリ*/
|
| |wap /* wap モジュールのスタイル ディレクトリ*/
|uploads /* ファイルのアップロード保存ディレクトリ*/
| |flink /* フレンドリー リンクの画像*/
| /* サムネイル*/
| |media /* マルチメディア ストレージ ディレクトリ*/
| |soft /* ソフトウェア*/
| |userup /* アバターなどのユーザー ファイル ストレージ
http://www.bkjia.com/PHPjc/732359.htmlwww.bkjia.com

PHP and Python each have their own advantages, and the choice should be based on project requirements. 1.PHPは、シンプルな構文と高い実行効率を備えたWeb開発に適しています。 2。Pythonは、簡潔な構文とリッチライブラリを備えたデータサイエンスと機械学習に適しています。

PHPは死にかけていませんが、常に適応して進化しています。 1)PHPは、1994年以来、新しいテクノロジーの傾向に適応するために複数のバージョンの反復を受けています。 2)現在、電子商取引、コンテンツ管理システム、その他の分野で広く使用されています。 3)PHP8は、パフォーマンスと近代化を改善するために、JITコンパイラおよびその他の機能を導入します。 4)Opcacheを使用してPSR-12標準に従って、パフォーマンスとコードの品質を最適化します。

PHPの将来は、新しいテクノロジーの傾向に適応し、革新的な機能を導入することで達成されます。1)クラウドコンピューティング、コンテナ化、マイクロサービスアーキテクチャに適応し、DockerとKubernetesをサポートします。 2)パフォーマンスとデータ処理の効率を改善するために、JITコンパイラと列挙タイプを導入します。 3)パフォーマンスを継続的に最適化し、ベストプラクティスを促進します。

PHPでは、特性は方法が必要な状況に適していますが、継承には適していません。 1)特性により、クラスの多重化方法が複数の継承の複雑さを回避できます。 2)特性を使用する場合、メソッドの競合に注意を払う必要があります。メソッドの競合は、代替およびキーワードとして解決できます。 3)パフォーマンスを最適化し、コードメンテナビリティを改善するために、特性の過剰使用を避け、その単一の責任を維持する必要があります。

依存関係噴射コンテナ(DIC)は、PHPプロジェクトで使用するオブジェクト依存関係を管理および提供するツールです。 DICの主な利点には、次のものが含まれます。1。デカップリング、コンポーネントの独立したもの、およびコードの保守とテストが簡単です。 2。柔軟性、依存関係を交換または変更しやすい。 3.テスト可能性、単体テストのために模擬オブジェクトを注入するのに便利です。

SplfixedArrayは、PHPの固定サイズの配列であり、高性能と低いメモリの使用が必要なシナリオに適しています。 1)動的調整によって引き起こされるオーバーヘッドを回避するために、作成時にサイズを指定する必要があります。 2)C言語アレイに基づいて、メモリと高速アクセス速度を直接動作させます。 3)大規模なデータ処理とメモリに敏感な環境に適していますが、サイズが固定されているため、注意して使用する必要があります。

PHPは、$ \ _ファイル変数を介してファイルのアップロードを処理します。セキュリティを確保するための方法には次のものが含まれます。1。アップロードエラー、2。ファイルの種類とサイズを確認する、3。ファイル上書きを防ぐ、4。ファイルを永続的なストレージの場所に移動します。

JavaScriptでは、nullcoalescingoperator(??)およびnullcoalescingsignmentoperator(?? =)を使用できます。 1.??最初の非潜水金または非未定されたオペランドを返します。 2.??これらの演算子は、コードロジックを簡素化し、読みやすさとパフォーマンスを向上させます。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

DVWA
Damn Vulnerable Web App (DVWA) は、非常に脆弱な PHP/MySQL Web アプリケーションです。その主な目的は、セキュリティ専門家が法的環境でスキルとツールをテストするのに役立ち、Web 開発者が Web アプリケーションを保護するプロセスをより深く理解できるようにし、教師/生徒が教室環境で Web アプリケーションを教え/学習できるようにすることです。安全。 DVWA の目標は、シンプルでわかりやすいインターフェイスを通じて、さまざまな難易度で最も一般的な Web 脆弱性のいくつかを実践することです。このソフトウェアは、

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

Dreamweaver Mac版
ビジュアル Web 開発ツール

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境
