ホームページ >バックエンド開発 >PHPチュートリアル >PHP Webサイトデザインの悩みを徹底解説_PHPチュートリアル

PHP Webサイトデザインの悩みを徹底解説_PHPチュートリアル

WBOY
WBOYオリジナル
2016-07-21 14:53:19947ブラウズ

PHPは恥ずかしいです。とても壊れていましたが、訓練されたアマチュアはそれを賞賛しました。 PHP はいくつかの些細な改善策を行っていましたが、私はそれを忘れることにしました。

はじめに

私は変な気性を持っています。いろいろなことについて文句を言います。私はこの地球上のほとんどのテクノロジーが好きではありません。

PHP は使いにくいだけでなく、私が望むものには適していないか、最も満足のいくものではないか、私の信念に反しています。私が避けたい言語の良い点も、気に入っている悪い点もすべて話すことができます。ぜひ聞いてみてください

php だけが例外です。 PHP が抽象化するほとんどすべてのものは断片化されています。言語、フレームワーク、そしてエコシステム全体を含めて混乱しています。悪口だけはあちこちに壊れているので、かろうじて挙げることができます。 PHP に関する苦情の複雑なリストをまとめようとするたびに、些細な詳細に脇道にそれてしまい、深く掘れば掘るほど、より衝撃的な事実が見つかります。

PHPは恥ずかしい。とても壊れていましたが、訓練されたアマチュアはそれを賞賛しました。 PHP はいくつかの些細な改善策を行っていましたが、私はそれを忘れることにしました。

でも、私は自分のシステムからこんなものを取り除かなければなりません、それだけです、これが最後の試みです。

比喩を作る

何気なくメルに苦情を言っただけですが、彼女はそれを公開するよう主張しました。

PHP の何が問題なのかさえ分かりません。なぜなら、それは大丈夫だからです。工具箱があるように考えてください。たくさんのツール。見た目は大丈夫、標準的なもの。

ネジを抜くと、奇妙な頭が 3 つあります。まあ、これはあなたにとってあまり役に立ちませんが、いつか役に立つでしょう。

ハンマーを取り出すと、両側に鋭い爪がありました。それでも効果はあります、つまり両端の真ん中で斜めに打つことができます。

バイスを取り出しますが、側面には鋸歯状の部分がありません。表面は平らで滑らかです。それほど便利ではありませんが、それでも機能するので、問題ありません。

続けても大丈夫です。道具箱の中身は奇妙で曖昧ですが、価値がないわけではありません。全体的に大きな問題はなく、ツールはすべて揃っています。

さて、これらの道具を使っている大工がたくさんいて、彼らがあなたにこう言うと想像してください。「これらの道具の何が問題なのですか? 私たちは皆、それらを使っていますが、とてもうまくいきます!」。職人が建てた家を見せてもらいます。扉は五角形で、屋根は曲線を描いています。玄関のドアをノックするとドアが内側に落ちてしまい、あなたがドアを壊したと彼らは苦情を言います。

これがPHPの問題です。

ポジション

私は、言語の生産性と使いやすさには次の性質が重要であると考えていますが、PHP はそれらを大規模に損なうものです。もしあなたがこのどれにも同意しないのであれば、私たちが同意するとは到底思えません。

言語は予測可能でなければなりません。人間の思考をコンピュータの実行に反映する媒体であるため、重要なのは、プログラムに対する人間の理解が実際に正しくなければならないということです。

言葉は一貫していないといけない。似ているものは似ていて、違うものは違って見えるはずです。言語の一部を学習すれば、残りの部分は簡単に理解できるはずです。

言葉は簡潔でなければなりません。新しい言語は、古い言語からそれほど悪くない形式を継承する必要があります。 (マシンコードを書くこともできます。) 新しい言語では、新しい独自の形式を織り込むことを避けるように努めるべきです。

言語は信頼できるものでなければなりません。言語は問題を解決するためのツールであり、新しい問題を引き起こすことはできるだけ避けるべきです。いかなる「罠」も、大きな混乱を招くことになります。

言語はデバッグ可能でなければなりません。何か問題が発生した場合、プログラマーはそれを修正しなければならず、私たちは必要な支援を得る必要があります。

私の立場は:

PHP は驚きに満ちています: mysql_real_escape_string、E_ACTUALLY_ALL

PHPの不一致: strpos、str_rot13

PHP には特別な形式が必要です: error-checkingaroundCAPIcalls, ===

PHPがおかしい: ==。 for($fooas&$bar)

PHP は不明瞭です: デフォルトではスタック トレースや致命的なエラーはなく、複雑なエラー報告が行われます

なぜこれらのカテゴリーに当てはまるのかを一つの質問で説明できないと、際限なく説明してしまいます。読者はご自身で考えていただけると思います。

こういうことについて私に話すのはやめてください

私は有利な議論をたくさん知っています。という反論もよく聞きます。これは会話を即座に停止させるだけです。こんなくだらないことを私に与えるのはやめてください。

「良い開発者はどんな言語でも良いコードを書ける」とか、悪い開発者とか言わないでください。 .バーバーバー。これは意味がありません。優れた職人は石やハンマーを使って釘を打つことができますが、石を使っている職人を何人見たことがありますか? 優れた開発者の条件の 1 つは、道具の選択が上手であることです。

何千もの例外や癖を覚えるのが開発者の仕事だなんて言わないでください。はい、コンピュータは愚かなので、これはどのシステムでも必要です。これは、システムが上限なしで異常な金額を受け入れることができるという意味ではありません。 PHP には例外があるだけでは十分ではありません。言語に取り組み始めると、実際にプログラムを作成するためにさらに労力を費やす必要があります。私のツールはアプリの作成に積極的には役立ちません。

「それがCAPIの仕組みだ」とは言わないでください。提供できるのはいくつかの文字列ヘルパー関数と C 用のラッパーだけであるのに、地球上での高級言語の目的は何でしょうか。そうであれば、C ライブラリさえあります。

「変なことをしたら自業自得」なんて話はしないでください。 2 つのプロパティが存在する場合、いつか誰かがそれらを一緒に使用する理由を見つけるでしょう。繰り返しますが、これは C ではありません。ここには仕様がなく、「未定義の動作」も必要ありません。

PHP を使用した Facebook と Wikipedia についてはもう気にしないでください。それらは Brainfuck で書くこともできますが、十分に賢く、これらをいじくり続ける限り、いつでも問題を克服できます。プラットホーム。誰もが知っているように、他の言語で書かれた場合、開発時間は半分または 2 倍に短縮される可能性があります。これらの数字だけを引き出すことに意味はありません。

神様、もう私に何も話さないでください! リストされたビューがあなたの PHP に悪影響を及ぼさないのであれば、それは問題ではありません。ですから、オンラインで無意味な議論をするのはやめて、私がそれを証明するためにクールでハンサムなサイトを開発し続けてください。不正解です。

こっそり言っておきますが、私は Python がとても好きです。あなたが本当に聞きたくないことでも、喜んで話します。完璧であることを求めているわけではありません。長所を活かして短所を避け、自分が望む最高のものをまとめようとしているだけです。

PHP

言語コア

CPANは「Perlの標準ライブラリ」と呼ばれています。これは Perl の標準ライブラリについて多くを語っているわけではありませんが、強力なコアがあれば強力なものを構築できるという考えを表しています。

基本原則

PHP は元々、明らかに非プログラマー向けに設計されました (暗黙的に、非プロフェッショナルなプログラム)。そのルーツから抜け出すのは困難でした。 PHP 2.0 ドキュメントから抜粋されたダイアログ:

型ごとに異なる演算子を区別し始めると、言語を使用し始めると複雑になります。たとえば、文字列に「==」を使用することはできず、「eq」を使用する必要があります。特に PHP のようなスクリプト言語ではこのようなことは見当たりません。そのほとんどは非常に単純であり、ほとんどの場合、プログラマーではない人は、あまりお金をかけずに、少量の基本的なロジック構文を備えた言語が必要なだけです。学習曲線が長い。

PHP は前進し続けるために必要なことは何でもします。何もないよりは何でもいいです。

これは正しい設計原理ではありません。初期の PHP は Perl の影響を受けており、多くの標準ライブラリは C を参照し、OO 部分は C++ や Java のように設計されていました。

PHP は他の言語から多くのインスピレーションを得ていますが、他の言語に慣れている人にとってはまだ理解するのが難しいです。 (int) は C のように見えますが、int は存在​​しません。ネームスペースの使用法。新しい配列構文では [key=>value] が使用されます。これは、他の言語でハッシュ リテラルを定義する方法とは異なります。

弱い型付け(つまり、文字列/数値/その他の間のサイレント自動変換)は非常に複雑です。

少数の新機能は新しい構文で実装されており、ほとんどの作業は関数または関数に似たものを通じて実行されます。クラスのサポートに加えて、これには当然新しい演算子とキーワードが必要です。

このページにリストされている問題には公式の解決策があります - オープンソース プログラミング言語を修正する Zend の取り組みに資金を提供したい場合。

道は長く、旅も長い。 PHP ドキュメントのどこかから抜粋した次のコードを考えてみましょう。

@fopen('http://example.com/not-existing-file', 'r');

どうなるの?

PHPを--disable-url-fopen-wrapperでコンパイルすると動作しません。 (ドキュメントには、「動作しない」とはどういう意味なのかが記載されていません。null を返し、例外をスローしますか?)

これはPHP5.2.5で削除されたことに注意してください。

php.iniでallow_url_fopenが無効になっている場合は動作しません。 (なぜですか?知る方法はありません。)

@ なので、存在しないファイルに対する警告は出力されません。

ただし、php.iniにscream.enabledが設定されていれば、また印刷されます。

または、ini_set を使用して手動で Cream.enabled を設定する場合。

ただし、error_reportingレベルが設定されていない場合は別です。

印刷される場合、正確な宛先は、やはり php.ini または ini_set の display_errors に依存します。

コンパイル時のフラグ、サーバー側の設定、プログラム内の設定を見ずに、この関数呼び出しの動作を説明することはできません。これらは組み込みの動作です。

言語にはグローバルな状態と暗黙的な状態がたくさんあります。 mbstring はグローバル文字エンコーディングを使用します。 func_get_arg のようなものは通常の関数のように見えますが、現在実行中の関数に対してのみ動作します。エラー/例外処理はデフォルトでグローバルです。 register_tick_function は、ティック (フック?) ごとに実行するグ​​ローバル関数を設定します。何?!

スレッドのサポートはありません。 (上記のことを考えれば、驚くべきことではありません。) これは、組み込みフォーク (後述) の欠如と相まって、並列プログラミングを非常に困難にしています。

実際にはPHPの一部でエラーコードが生成されます。

json_decode は不正な入力に対して null を返しますが、null は JSON デコードの正当なオブジェクトでもあります。この関数は、使用するたびに json_last_error を呼び出さない限り、非常に信頼性が低くなります。

array_search、strpos、およびその他の同様の関数は、位置 0 で見つかった場合は 0 を返しますが、それ以外の場合は見つかりません。 falseを返します

最後の部分を少し拡張してみましょう。

Cではstrposなどの関数は見つからない場合は-1を返します。これを確認せずに添え字とともに使用しようとすると、おそらくガベージ メモリに到達し、プログラムがクラッシュする可能性があります。 (おそらく、それは C です。誰にもわかりません。少なくともそれに対処するツールはあると思います)

つまり、Pythonでは、要素が見つからない場合、同等の.indexメソッドは例外をスローします。この状況を確認しないと、プログラムがクラッシュします。

PHP では、この関数は添字として FALSE を使用するか、他の処理に使用すると、=== 比較を除いて、PHP は黙って 0 に変換します。プログラムはクラッシュしません。strpos やその他の同様の関数が使用されるすべての場所に正しいボイラープレート処理コードを忘れずに含めない限り、警告なしで間違ったロジックが実行されます。

それは最悪です! プログラミング言語は私に役立つ単なるツールです。ここで、PHP は私に罠を仕掛け、私が飛び込むのを待っています。私はこれらの退屈な文字列操作と等価比較に常に注意しなければなりません。 PHP は地雷原です。

PHPパーサーについてはたくさんの話を聞いてきましたが、その開発者は世界中から来ています。 PHP コアの開発に従事している人、PHP コアをデバッグする人、コア開発者とコミュニケーションをとっている人もいます。ストーリーは評価されません。

繰り返しになるので、ここに文を挿入する必要があります。PHP はアマチュアのコミュニティです。それを設計したり、そのために働いたり、自分が何をしているのかを知っている人はほとんどいません。 (ああ、親愛なる読者の皆さん、あなたはもちろん究極の例外です!)成長して他のプラットフォームに移行したいと思う人は、コミュニティ全体の平均を下げます。ここが PHP の最大の問題です。絶対的な盲目は失明につながります。

さて、戻って現実と向き合いましょう。

オペレーター

==役に立たない。

"foo"==TRUE、そして"foo"==0…でも、もちろんTRUE!=0です。

== は可能であれば両側を数値に変換します。つまり、可能であれば浮動小数点に変換されます。そのため、大きな 16 進文字列 (パスワードハッシュなど) は、同じではない場合でも true と比較されることがあります。 JavaScript でもこれはできません。

なぜか「6」==「6」、「4.2」==「4.20」、「133」==「0133」。ただし、0133 は 8 進数であるため、133!=0133 であることに注意してください。

=== は値と型を比較します...オブジェクトを除き、これは両側が実際に同じオブジェクトである場合にのみ当てはまります! オブジェクトの場合、== は値 (または各プロパティ) と型を比較します。 == は、非オブジェクト型の動作を比較します。楽しいですか?

サイズを比較するのはあまり良くありません。

動作も一貫性がありません: NULL 比較演算子は、最初に長さによって、次に要素によってという 2 つの異なる方法で配列を並べ替えようとします。要素数が同じでもキーが異なる場合、それらは比較できません。

オブジェクトの比較は、他の比較よりも多くのことを行います...ただし、以下でもない、より大きいでもないものを除きます。

よりタイプセーフな == 比較には、=== があります。タイプセーフな < 比較については、何もありません。通常は、どうやっても「123」<「0124」です。型キャストも役に立ちません。

上記の動きはクレイジーですが、明らかに Perl の文字列 paris を拒否しており、PHP は + をオーバーロードしません。通常のコネクタです。

[] 添字演算子は、{} と綴ることもできます。

[]は文字列や配列だけでなく、あらゆる変数に使用できます。エラー警告なしで null を返します。

[]は単一の要素しか取得できません。

foo()[0]は構文エラーです。 (PHP5.4で修正されました)

他の言語の (文字通り) 同様の演算子とは異なり、?: は左結合です。したがって:

$arg = 'T';

$vehicle = ( ( $arg == 'B' ) ? 'バス' :

( $arg == 'A' ) '飛行機' :

( $arg == 'T' ) '電車' :

( $arg == 'C' ) '車' :

( $arg == 'H' ) '馬' :

「足」 );

echo $vehicle;

プリントホース

変数

変数は宣言できません。存在しない変数は、初めて使用するときに null 値で作成されます。

グローバル変数は使用する前にグローバルに宣言する必要があります。これは上記の自然な結果であり、完全な理由ですが、明示的な宣言がなければ、グローバル変数を読み取ることさえできません。PHP は、その場所に同じ名前のローカル変数を暗黙的に作成します。他の言語が同様の方法でスコープの問題を処理しているのを見たことがありません。

引用符はありません。 PHP のいわゆる参照は真のエイリアスです。これは、Perl の参照とは異なり、間違いなく一歩後退しており、Python のようにオブジェクト識別子を渡すことはありません。

検出して逆参照する明確な方法はありません。

「参照」は変数を言語内で一意にする。 PHP は動的に型指定されるため、変数は通常、関数定義、変数構文、代入を変更する参照を除いて型指定されません。変数が参照されると (これはどこでも発生する可能性があります)、参照のままになります。逆参照に必要な変数値を検出する明確な方法はありません。

はい、嘘をつきました。一部の「SPLtype」は変数でも機能します: $x=newSplBool(true);$x="foo"; は失敗します。これは静的型付けに少し似ています。ご自身の目で確認してください。

未定義の変数(配列になる)内に存在しないキーへの参照を取得できます。存在しない配列を使用すると通常は noice が発行されますが、これは発行されません。

関数を通じて定義された定数は、文字列を取ると呼ばれます。これ以前には、それらは存在しませんでした。 (これは実際には定数を使用した Perl の動作をコピーしている可能性があります。)

変数名は大文字と小文字が区別されます。関数名とクラス名はそうではありません。メソッドにキャメルケースを使用するのは奇妙です。

構造

array() といくつかの同様の構造は関数ではありません。 $func="array";$func(); は機能しません。

配列のアンパックは list($a,$b)=... 操作を使用して完了できます。 list() は、配列と同様、関数に似た構文です。なぜ実際に専用の構文がないのか、また名前がなぜこれほど混乱しているのかわかりません。

(int) は明らかに C のように設計されていますが、言語には int と呼ばれるものはありません。これを試してください。var_dump(int) は機能しません。解析エラーが発生します。パラメータはキャスト演算子のように見えます。

(integer)は(int)のエイリアスです。 (bool)/(boolean) および (float)/(double)/(real) もあります。

配列に変換するための (配列) 演算子と、オブジェクトに変換するための (オブジェクト) 演算子があります。これは魅力的に聞こえますが、多くの場合、使用例があります。(array) を使用して、単一の要素またはリストである関数パラメーターを同じように扱うことができます。しかし、誰かが単一のオブジェクトを渡した場合、それを配列に変換すると、実際にはオブジェクトのプロパティを含む配列が生成されるため、これは信頼できません。 (オブジェクトに変換して反転演算を行います。)

include() などの関数は基本的に C の #include であり、他のファイルのソース コードをファイルに転送します。 PHP コードにもモジュール システムはありません。

入れ子になった関数やローカルスコープの関数やクラスなどは存在しません。それらはすべてグローバルなものです。ファイルをインクルードすると、その変数は現在の関数スコープにインポートされます (ファイルに変数にアクセスできるようになります)。ただし、関数とクラスはグローバル スコープに格納されます。

$foo[]=$bar を使用して配列に追加します。

echoは関数ではありません。

empty($var) は極端すぎて、変数以外の関数として動作しません (例:empty($var||$var2))。これは解析エラーです。一体なぜそのようなことがあり、なぜパーサーは空について知る必要があるのでしょうか?

if(…):…endif; などの冗長な構文ブロックもいくつかあります。

エラー処理

PHP の固有の演算子は @ (実際には DOS から借用したもの) で、エラーを隠します。

PHPエラーではスタックトレースが提供されません。それらを生成するにはプロセッサをインストールする必要があります。 (ただし、致命的なエラーではありません - 以下を参照してください。)

PHP 解析エラーは通常、解析ステータスのみをスローし、それ以外は何もスローしないため、デバッグが非常に困難になります。

PHPパーサーとは、例えば:: は内部的には T_PAAMAYIM_NEKUDOTAYIM、<< 演算子は T_SL と言いましたが、上で述べたように、:: または << は間違った場所に表示されます。

ほとんどのエラー処理では、サーバー ログにエラー ログが 1 行出力されますが、誰もそれを見ることなく処理が続行されます。

E_STRICT はそのように見えますが、実際にはあまり保護されておらず、実際に何を行うかを示すドキュメントはありません。

E_ALL には、E_STRICT を除くすべてのエラー カテゴリが含まれます。

何が許可され、何が許可されていないのかについては、奇妙さと矛盾があります。 E_STRICT がここでどのように適用されるかわかりませんが、これらは正しいです:

$foo->x など、存在しないオブジェクトのプロパティにアクセスしようとしています(警告)

変数は関数名、変数名、クラス名として使用します。 (無言)

未定義の定数を使用しようとしています。 (注意)

非オブジェクト型のプロパティにアクセスしようとしています。 (注意)

存在しない変数名を使用しようとしています。 (注意)

2<"foo"(非表示)

foreach(2as$foo);(警告)

以下は機能しません:

$foo::x.(fatalerror) など、存在しないクラス定数にアクセスしようとしています

文字列定数を関数名、変数名、クラス名として使用します。 (解析エラー)

明示的に定義された関数を呼び出そうとしています。 (致命的なエラー)

ブロックまたはファイルの最後のステートメントにアセミコロンを残します。(解析エラー)

リストおよびその他の準組み込みマクロをメソッド名として使用します。 (解析エラー)

関数の戻り値にアクセスするには、foo()[0] などの添え字を使用します。 (解析エラー; 5.4 で修正されました)

リストの他の場所に、他の奇妙な解析エラーの良い例がいくつかあります

__toString メソッドは例外をスローできません。実行しようとすると、PHP は例外をスローします。 (これは実際には致命的なエラーであり、例外的にパスされる可能性があります...)

PHPエラーとPHP例外は全く別の種類です。彼らは対話することができません。

PHPエラー(内部的にはtrigger_errorと呼ばれます)はtry/catchではキャッチできません。

同様に、例外は、set_error_handler によってインストールされたエラー ハンドラーを通じてエラーをトリガーすることはできません。

代わりに、mod_pho モジュール内の try ブロックでプログラム エントリをラップすることはできないため、キャッチされなかった例外を処理できる別の set_Exception_handler があります。

致命的なエラー (例: newClassDoesntExist()) は何もキャッチできません。完全に無害な操作が多数実行されると、致命的なエラーが発生し、物議を醸す理由でプログラムを終了せざるを得なくなる可能性があります。シャットダウン関数は引き続き実行されますが、スタック トレースを取得できず (最上位で実行されます)、プログラムがエラーによって終了したか、プログラムの通常の動作によって終了したかを判断するのが困難です。

finally 構造がないため、パッケージ化コード (プロセッサーの登録、コードの実行、プロセッサーの登録解除、モンキーパッチ、テストの実行、アンモンキーパッチ) が醜く、書くのが難しくなります。 OO と例外は Java パターンを大量にコピーしていますが、最終的には「PHP のコンテキストではあまり役に立たない」ため、これは意図的なものです。

機能

関数呼び出しはかなり高価なようです。

一部の組み込み関数は、まあ、奇妙な方法で参照を返す関数と対話します。

他の場所で述べたように、関数のように見えるもの、または関数であるべきように見えるものの多くは、実際には言語の一部であり、したがって通常の関数のようには機能しません。

関数パラメータには「型ヒント」を含めることができますが、これは基本的に単なる静的型です。すべての組み込み関数がこの型を使用しているにもかかわらず、パラメーターを int、string、object、またはその他の「コア」型にすることはできません。おそらく、PHP には int が存在しないためです。 (上記の (int) の説明を参照してください)。また、多数の組み込み関数 (mixed、number、または callback) で使用される特殊な擬似型装飾も使用できません。

したがって、以下、

関数 foo(string $s) {}

foo("hello world");

エラーエラー:

PHPCatchablefatalerror: Argument1passedtofoo()mustbeaninstanceofstring、stringgiven、callin…

「型ヒント」は実際には存在しないことに気づくかもしれません。プログラムには文字列クラスがありません。 ReflectionParameter::getClass() を使用して型ヒントを動的にテストしようとすると、型が存在しないことがわかり、型名を取得することは事実上不可能になります。

関数の戻り値は推論できません

現在の関数のパラメータを別の関数(ディスパッチ、珍しいことではありません)に渡すことは、call_user_func_array(‘other_function’, func_get_args()) によって完了します。しかし、 func_get_args は実行時に致命的なエラーをスローし、関数の引数として使用できないことを訴えます。これはなぜ型エラーなのでしょうか? (PHP5.3 で修正されました)

クロージャは各変数に明示的に「closed-over」という名前を付ける必要があります。なぜパーサーはそれを回避する方法を考えないのでしょうか (それは、avariableever を使用すると、明示的に指定されない限りそれが作成されるからです)。

クローズドオーバー変数は、他の関数パラメータと同じセマンティクスで「渡されます」。この場合、配列や文字列などが値によってクロージャに渡されます。 &.

を使用しない場合

クロージャ変数は自動的にパラメータを渡し、ネストされたスコープがないため、クラスで定義されているかどうかにかかわらず、クロージャはプライベートメソッドを指すことができません。 (おそらく 5.4 で修正されるでしょうか? わかりません。)

この関数には名前付きパラメータがありません。実際には「コードの臭いを引き起こす」という理由で開発者によって拒否されました。

ドキュメントでそのことが指摘されている場合でも、デフォルトを持つ関数引数は持たない関数引数の前に現れることがあります

両方とも奇妙で役に立たない。(それでなぜ許可するの?)

関数に追加のパラメータを渡しても無視されます(例外をスローする組み込み関数を除く)。欠落している引数は null とみなされます。

「変数」関数には func_num_args、func_get_arg、func_get_args が必要です。そのような構文はありません。

○○

PHP の機能部分は C に似るように設計されていますが、オブジェクト指向 (ほほ) 部分は Java に似るように設計されています。これがどれほど不協和音であるかはあまり強調したくありません。大文字を含むグローバル関数、キャメルケースで名前が付けられた重要な組み込みクラス、および getFoo のような Java スタイルのプロパティ アクセサーをまだ見つけていません。これは動的言語ですよね。Perl、Python、Ruby にはすべて、コードを通じて「プロパティ」にアクセスするという概念があります。PHP には、不格好な __get などがあります。型システムは低レベル Java 言語を中心に設計されており、Java と PHP は同じ時代に意図的に多くの制限を設けて Java をコピーしています。

クラスはオブジェクトではありません。メタプログラミングでは、関数と同様に、文字列名を介してそれらを指定する必要があります。

組み込み型はオブジェクトではなく、(Perl とは異なり) オブジェクトのように見せることはできません。

Instanceofは演算子ですが、非常に後から追加されたものであり、ほとんどの言語は特殊な関数と構文を持っています。 Java の影響を受けていますか? (そうであるかどうかはわかりません)

でも、is_a関数はあるんです。これには、オブジェクトが実際に文字列名のクラスになることを許可するかどうかを指定するオプションのパラメーターがあります。

Get_class は関数です。typeof 演算子はありません。 is_subclass_of もあります

ただし、これは組み込み型では機能しません(繰り返しますが、int は関係ありません)。この方法では、is_int などが必要になります。

右辺値は変数またはリテラルである必要があり、式にすることはできません。そうしないと、解析エラーが発生します。

クローンはオペレーター?!

OOデザインはPerlとJavaを混ぜ合わせたモンスターです。

オブジェクトのプロパティは $obj->foo を経由しますが、クラスのプロパティは $obj::foo を経由します。これを行う言語も、その使用法も見たことがありません。

ただし、インスタンス メソッドは静的に呼び出すことができます (Class::method)。他のメソッドから呼び出された場合、現在の $this に対する通常のメソッド呼び出しとして扱われます。そう思います。

新規、プライベート、パブリック、保護、静的など。 Java 開発者を説得したいですか? 個人的な好みの問題であることはわかっていますが、なぜこれらのことが動的言語に必要なのかわかりません。C++ では、そのほとんどはアセンブリおよびコンパイル時の名前解決に関するものです。

サブクラスはプライベートメソッドをオーバーライドできません。サブクラスによってカバーされるパブリック メソッドも表示されず、スーパークラスのプライベート メソッドは個別に呼び出されます。モックオブジェクトをテストする場合などに問題が発生します。

list() は特殊な構文 (関数ではない) であり、パーサーが混乱するため、メソッドに「list」などの名前を付けることはできません。このあいまいさの理由は不明ですが、クラスは問題なく機能します。 ($foo->list() は構文エラーではありません。)

コンストラクターのパラメーターを解析するときに例外がスローされた場合 (例: newFoo(bar()) や bar() throws)、コンストラクターは呼び出されませんが、デストラクターは呼び出されます。 (PHP5.3で修正)

__autoload 関数と解析関数で例外が発生すると、致命的なエラーが発生します。

コンストラクターやデストラクターはありません。 __construct は、Python の __init__ のような初期化関数です。クラスを呼び出してメモリを適用したり、オブジェクトを作成したりすることはできません。

デフォルトの初期化関数はありません。 parent::__construct() を呼び出すときに、親クラスが独自の __construct メソッドを定義していないと、致命的なエラーが発生します。

OO は言語仕様の一部であるイテレータ インターフェイス (...as... など) をもたらしますが、このインターフェイスには実際には組み込み実装 (配列など) がありません。配列イテレータが必要な場合は、ArrayIterator でラップする必要があります。イテレータがファーストクラスのオブジェクトとして機能する組み込みの方法はありません。

クラスは文字列に変換する方法をオーバーロードできますが、数値やその他の組み込み型に変換する方法はオーバーロードできません。

文字列、数値、配列にはすべて文字列変換メソッドがあります。この言語はこれに大きく依存しています。関数とクラスは文字列です。ただし、__toString が定義されていない場合、組み込みオブジェクトまたはカスタム オブジェクト (またはクロージャ) を文字列に変換しようとするとエラーが発生し、エコーさえも失敗する可能性があります。

等価演算や比較演算をオーバーロードすることはできません。

インスタンス メソッドの静的変数はグローバルであり、その値はクラスの複数のインスタンス間で共有されます。

標準ライブラリ

Perl「何か​​をコンパイルする必要があります」。 Python は「電池付属」です。 PHP は「キッチンのシンク、カナダ産ですが、蛇口のブランドはすべて C」です。

概要

型システムはありません。 PHP をコンパイルすることはできますが、php.ini を介して何をロードするかを指定する必要があります。オプションは存在するか (コンテンツをグローバル名前空間に挿入する)、拡張子によって存在しません。

名前空間は最近の機能であるため、標準ライブラリはまったく破壊されていません。グローバル名前空間には何千もの関数があります。

ライブラリのいくつかの部分は非常に矛盾しています。

アンダースコアとアンダーラインなし: strpos/str_rot13、php_uname/phpversion、base64_encode/urlencode、gettype/get_class

「to」ペア 2: ascii2ebcdic、bin2hex、deg2rad、strto lower、strtotime

オブジェクト+動詞と動詞+オブジェクト:base64_decode、str_shuffle、var_dumpversuscreate_function、recode_string

パラメータの順序: array_filter($input, $callback) vsarray_map($callback,$input)、strpos($haystack,$needle) vsarray_se

アーチ($針,$干し草の山)

接頭辞の混乱: usleepvsmicrotime

名前に含まれるさまざまな機能で大文字と小文字が区別されます。

配列関数の約半分はarray_で始まります。残りはそうではありません。

キッチンのシンク。ライブラリには次のものが含まれます:

Bind ImageMagick、bind GraphicsMagick(ImageMagickの派生)、いくつかの関数はEXIFデータを検出できます(ImageMagickはすでにこれを行うことができます)

bbcode、いくつかの非常に特殊なタグを解析する関数。いくつかのフォーラム パッケージで使用されます。

XML パッケージが多すぎます。 DOM(OO)、DOMXML(not)、libxml、SimpleXML、「XMLParser」、XMLReader/XMLWriter、その他私が認識できないものは省略されています。もちろん、いくつかの違いはありますが、それを理解するのは自由です。

2 つの特別なクレジット カード プロセッサ、SPPLUS と MCVE がバインドされています。

MySQL データベースにアクセスする 3 つの方法: mysql、mysqli、および PDO のいくつかの抽象化。

Cの影響

独自のシンボルが必要です。 PHP は、動的に型付けされた高レベル言語です。そして、標準ライブラリの多くの部分は、次のような CAPIS の単なる薄いラッパーにすぎません:

「出力」パラメータですが、PHP はアドホック ハッシュを返したり、複数のパラメータを簡単に返したりできます。

PHP には 8 年間例外処理機能があったにもかかわらず、少なくとも 12 個の関数が、特定のサブシステムの最後のエラーを取得するように設計されています (以下を参照)。

同じパラメータを持つ mysql_escape_string がすでに存在するにもかかわらず、mysql_real_escape_string が存在します。これは単に MySQLCAPI の一部であるためです。

グローバル動作は非グローバル関数(MySQLなど)です。複数の MySQL 接続を使用するには、接続ハンドルを各関数呼び出しに明示的に渡す必要があります。

ラッパーは本当に、本当に、本当に薄いです。たとえば、dba_firstkey を呼び出さずに dba_nextkey を呼び出すと、セグメンテーション違反が発生します。

isupper などの代わりに、同様の名前を持つ C 文字関数をマップする ctype_* 関数 (ctype_alnum など) が多数あります。

ジェネリック主義

関数が 2 つのわずかに異なることを実行する場合、PHP は 2 つの関数を作成します。

Perl では、どのようにして逆ソートを行うことができますか? Python では、.sort(reverse=True) を使用できます。 PHP には、rsort() と呼ばれる特別な関数があります。

Cerror に似た関数:curl_error、json_last_error、openssl_error_string、imap_errors、mysql_error、xml_get_error_code、bzerror、da

te_get_last_errors、他にありますか?

並べ替え関数: array_multisort、arsort、asort、ksort、krsort、natsort、natcasesort、sort、rsort、uasort、uksort、usort

テキスト検索関数: ereg、eregi、mb_ereg、mb_eregi、preg_match、strstr、strchr、stristr、strrchr、strpos、stripos、strrpos、strripos、m

b_strpos、mb_strrpos、および置換を行うバリエーション

多数のエイリアスがあります: strstr/strchr、is_int/is_integer/is_long、is_float/is_double、pos/current、sizeof/count、chop/rtrim、implode/join、die/exit、trigger_error/user_error...

scandir は、現在指定されているディレクトリ内のファイルのリストを返します。この関数は、(潜在的に有益な) ディレクトリ順に返す代わりに、ソートされたファイルのリストを返します。アルファベット順の逆順で返すオプションのパラメータがあります。これらは明らかに並べ替えには十分ではありません。

str_split は文字列を同じ長さのチャンクに分割します。 chunk_split は、文字列を同じ長さのチャンクに分割し、それらをセパレータで連結します。

圧縮ファイルの読み取りには、形式に応じて別の関数セットが必要です。 bzip2、LZF、phar、rar、zip、gzip/zlib など、異なる API を備えた関数のセットが 6 つあります

引数の配列を使用して関数を呼び出すのは非常に面倒なので (call_user_func_array)、printf/vprintf や sprintf/vsprintf などの関連関数があります。これらは同じことを行いますが、一方は複数の引数を受け取り、もう一方は引数の配列を受け取ります。

本文

/e(eval)フラグを付けたpreg_replaceは、一致する部分を置換対象の文字列に置き換えてevalします。

strtok の設計は明らかに C 関数と同等ですが、これは多くの理由から悪いアイデアであると考えられてきました。 PHP は簡単に配列を返すことができますが (これは C では扱いにくいです)、hackstrtok(3) の多くの使用法 (どこかの文字列を変更する) はここでは使用できません。

parse_str はクエリ文字列を解析します。関数名からは手がかりがありません。代わりに、登録する配列を渡さない限り、 register_globals を実行し、クエリ文字列をローカル スコープ変数にダンプします。 (もちろん何も返されません)

空のセパレーターに遭遇すると、explodeは分割を拒否します。このアプローチを採用する他のすべての文字列分割実装は、文字列を文字に分割することを意味すると考えられています。PHP には、紛らわしい str_split と呼ばれる分割関数がありますが、「文字列を配列に変換する」と説明されています。

日付のフォーマットには、CAPIと同様にローカルロケールを扱うstrftimeがあります。もちろん、完全に異なる構文を持ち、英語でのみ使用される日付もあります。

「gzgetss—gzファイルの行ポインタを取得し、HTMLタグを削除します。」 この一連の関数の概念を知って、私は死にます。

mbstring

それはすべて「マルチバイト」に関するものであり、文字セットの問題を解決します。

まだ通常の文字列を処理しています。グローバルな「デフォルト」文字セットが 1 つあります。一部の関数では文字セットを指定できますが、これはすべてのパラメータと戻り値に依存します。

ereg_* 関数が提供されていますが、これらは非推奨です。 preg_* は、いくつかの PCRE 固有のタグを使用して UTF-8 を理解できるので幸運です。

システムとリフレクション

テキストと変数を中心に、たくさんの関数があります。圧縮と抽出は氷山の一角にすぎません。

PHP を動的にする方法はいくつかありますが、一見しただけでは明らかな違いや相対的な利点はありません。クラス ツールはカスタム クラスを変更できません。ランタイム ツールはカスタム クラスを置き換えることができ、あらゆるカスタムを変更できます。リフレクション* クラスは、関数やクラス プロパティをレポートするための独自の関数が多数あります。これらのサブシステムは独立していますか、関連していますか、冗長ですか?

get_class($obj)はオブジェクトのクラス名を返します。 get_class() は、呼び出された関数のクラスの名前を返します。それはさておき、同じ関数がまったく異なることを行います: get_class(null)... は後者のように動作します。したがって、確率変数に直面した場合、それを信頼することはできません。びっくりしてください!

stream_* クラスを使用すると、fopen やその他の組み込みのファイル処理に似たもので使用するカスタム ストリーム オブジェクトの実装が可能になります。いくつかの内部的な理由により、「通知」を実装できません。

register_tick_functionはクロージャオブジェクトを受け入れることができます。 unregister_tick_function は機能せず、クロージャを文字列に変換できないことを示すエラーがスローされます。

php_uname は、現在のオペレーティング システムに関連することを示します。

fork と exec は組み込まれていません。これらは pcntl 拡張機能から来ていますが、デフォルトでは含まれていません。 Popen は pid ファイルを提供しません。

session_decode は PHP セッション文字列を読み取るために使用されますが、アクティブなセッションがある場合にのみ機能します。結果を値を返すのではなく、$_SESSION にダンプします。

雑貨

curl_multi_execはエラー発生時にcurl_errorを変更しませんが、curl_errorを変更します。

mktimeのパラメータは時、分、秒、月、日、年の順です

データ操作

プログラムはデータを噛んで吐き出すだけです。 awk から Prolog、C に至るまで、多くの言語がデータ操作を中心に設計されています。言語がデータを操作できない場合、その言語は何もできません。

数字

整数は、32 ビット プラットフォームでは符号付き 32 ビット数値です。同時代の PHP とは異なり、自動の bigint プロモーションはありません。したがって、CPU アーキテクチャに応じて、数学演算の結果が異なる場合があります。大きな整数を選択できる唯一の方法は、GMP または BC ラッパー関数を使用することです。 (開発者は、新しい別個の 64 ビット型を構築した可能性があります。それはクレイジーです。)

PHP は 0 から始まる 8 進数の構文をサポートしているため、012 は 10 になります。ただし、08 は 0.8 (または 9) になり、それ以降の数字は消えます。 01c は構文エラーです。

Piは関数です。または、定数 M_PI があります。

べき乗演算子はなく、pow 関数のみです。

本文

Unicodeはサポートされていません。本当に信頼できるのは ASCII 作品だけです。上で述べた mbstring 拡張機能がありますが、これは少しヒットです。

これは、組み込みの文字列関数を使用して UTF-8 テキストを処理するのは危険であることを意味します。

同様に、ASCII 以外では、大文字と小文字を比較するという概念はありません。大文字と小文字を区別する関数の拡張バージョンはありますが、それらは é と É が等しいとはみなしません。

変数内のキーを補間することはできません。たとえば、「$foo['key']」は構文エラーです。また、引用符を外したり (どこでも警告が生成されます!)、${…}/{$…}

を使用することもできません。

「${foo[0]}」が正解です。 「${foo[0][0]}」は構文エラーです。 Perl に似た構文 (根本的に異なる 2 つの言語) の不正コピー?

配列

残念ですね。

この人はリストデータ型の役割を果たし、ハッシュを操作し、セットをソートし、リストを解析し、時々奇妙な組み合わせを作ります。どのように動作するのでしょうか? どのような方法でメモリを使用するのでしょうか? いいえ、とにかく他の選択肢があります。

=> は演算子ではありません。これは、array(...) および foreach 構造内にのみ存在する特別な構造です。

-1 は 0 と同様に有効なキー値であっても、負の値でのインデックス付けは機能しません。

これは言語レベルのデータ構造ですが、短い構文はありません。array(…) が短い構文です。 (PHP5.4 では「リテラル」[...] が導入されました。)

=> 構造は Perl に基づいており、引用符なしで foo=>1 を使用できます。 PHP では、これを行うと警告が表示されます。引用符なしでハッシュ文字列キーを作成する方法はありません。

配列処理関数は、リスト、ハッシュ、またはその 2 つの組み合わせを操作する必要があるため、混乱したり、不安定に動作したりすることがあります。 「配列の異なる部分を計算する」配列のグループ化を検討してください。

$first = array("foo" => 123, "bar" => 456);

$sec = array("foo" => 456, "bar" => 123);

echo var_dump(array_diff($first, $second));

このコードは何をするのでしょうか? array_diff がパラメータをハッシュとして扱う場合、同じキーは明らかに異なります。リストとして見ると、値の順序が異なります。

実際、array_diff はそれらをセットとして扱うため、順序を無視して値のみを比較するため、それらは等しいと見なされます。

同様に、array_rand もキーをランダムに選択するときに奇妙な動作をします。これは、リストから何かを選択する必要があるほとんどのユースケースでは役に立ちません。

PHP コードの多くはキーの順序に依存していますが、:

array("foo", "bar") != array("bar", "foo")

array("foo" => 1, "bar" => 2) == array("bar" => 2, "foo" => 1)

2 つの配列が混在するとどうなるでしょうか? それを理解するのは読者に任せます。 (分かりません)

array_fill は長さ 0 の配列を作成できません。代わりに警告を発行し、false を返します。

すべての(多くの...)ソート関数は適切に動作し、何も返しません。ソートされた配列の新しいコピーを作成したい場合は、配列を自分でコピーしてからソートし、その配列を再度使用する必要があります。

しかし、array_reverseは新しい配列を返します。

ソートされたものといくつかのキーと値のペアは、関数の引数を処理するための強力な方法のように思えますが、そんなことはありません。

配列ではありません

標準ライブラリには、「高速ハッシュ」と「特定の強力な型」のハッシュ構造 OO 実装が含まれています。ただし、詳しく見てみると 4 つのカテゴリがあり、それぞれがキーと値のペアの種類の異なる組み合わせを処理します。組み込みの配列実装がこれらの非常に一般的なケースを最適化しない理由や、その相対的なパフォーマンスがどのようなものであるかは明らかではありません。

配列をラップしてオブジェクトのように見せる ArrayObject クラス (4 つの異なるインターフェイスを実装) があります。カスタム クラスは同じインターフェイスを実装できます。しかし、メソッドの数は限られており、そのうちの半分は組み込み配列関数のように見えず、組み込み配列関数は ArrayObject またはその他の配列のような型を操作する方法を知りません。

機能

関数はデータではありません。クロージャは実際にはオブジェクトですが、通常の関数はオブジェクトではありません。それらをそのままの名前で参照することもできません。var_dump(strstr) は警告を発し、文字列リテラル「strstr」を意味していると推測します。文字列と「関数」参照の違いを区別しようとしても、わかりません。

create_function は基本的に eval のラッパーです。通常の名前で関数を作成し、グローバルにインストールします (したがって、ガベージ コレクションされることはありません。ループ内で使用しないでください)。これはクロージャではないため、実際には現在のコンテキストについては何も知りません。名前には NUL バイトが含まれているため、通常の関数と競合することはありません (ファイル内のどこかに NUL があると PHP のパーサーが失敗するため)。

__lambda_func という名前の関数を宣言すると、create_function が壊れます。実際の実装では、__lambda_func という名前の関数を作成し、内部的に壊れた名前に名前を変更します。

rtは致命的なエラーをスローします。

その他

1 を生成するには、NULL に (++) を使用します。NULL を生成するには、NULL に (–) を使用します。

発電機はありません。

ウェブフレームワーク

実行環境

単一の共有ファイル php.ini が PHP の機能のほとんどを制御し、何をいつ上書きするかについての複雑なルールを織り込んでいます。 PHP ソフトウェアは任意のマシンにデプロイできるため、環境を適切に動作させるには一部の設定をオーバーライドする必要がありますが、これは多くのプログラムで php.ini などのメカニズムの使用に違反します。

PHPは基本的にCGIとして動作します。ページをクリックするたびに、PHP は実行前に環境全体を再コンパイルします。 Python のおもちゃのフレームワークの開発環境ですら、このようなものではありません。

これにより、他の言語と同様に一度コンパイルするだけでPHPを高速化できる「PHPアクセラレータ」市場全体が形成されました。 PHP を開発した Zend 社は、これをビジネス モデルとして使用しています。

長い間、PHP エラーはデフォルトでクライアントに出力されていました。開発環境を助けるためだと思います。これが真実だとは思いませんが、それでも時折 mysql エラーがページの上部に表示されるのがわかります。

タグの外側の空白は、ライブラリ内であっても、PHP によってテキストとして扱われ、解析されて応答に組み込まれます (または、「headersalreadysent」エラーが発生します)。一般的な方法は、終了タグを無視することです。

展開

PHP の最も高度な部分としてデプロイ方法がよく引用されますが、ファイルを直接デプロイするだけです。はい、プロセス全体を開始する必要がある Python や Rury、Perl よりも簡単です。しかし、PHP にはまだ改善の余地がたくさんあります。

Webアプリケーションをアプリケーションサーバーとして実行し、リバースプロキシしてみたいと思っています。これには、コストが最も低く、多くの利点があります。サーバーとアプリケーションを個別に管理でき、複数の Web サーバーを必要とせずに、マシンの数に応じて複数または少数のアプリケーション プロセスを実行でき、それらを異なるプロセスとして実行できます。ユーザー アプリケーションでは、Web サーバーを選択でき、Web サーバーに影響を与えずにアプリケーションを削除でき、アプリケーションをシームレスにデプロイできます。アプリケーションを Web サーバーに直接接続するのはばかげており、そうする正当な理由はありません。

すべての PHP アプリケーションは php.ini を使用します。ただし、php.ini ファイルは 1 つだけであり、それはグローバルです。共有サーバー上でそれを変更する必要がある場合、または異なる設定が必要な 2 つのアプリケーションを実行している場合は、うまくいきません。組織に適用する必要がある 必要な設定はすべて、ini_set を使用するか、Apache 構成ファイルまたは .htaccess 設定のいずれかを使用して、アプリケーションに配置されます。できれば。おそらくすごいでしょう、設定された値を取得する方法を理解するためにチェックすべき場所がたくさんあります。

同様に、PHP アプリケーションを「分離」する方法は、システムの他の部分に依存しているため、簡単ではありません。 2 つのアプリケーションを実行したい場合、異なるライブラリ バージョンが必要な場合、または異なる PHP バージョン自体が必要な場合は、Apache の別のコピーの構築を開始します。

「ファイルの束」アプローチは、ルーティングを病気のロバのように見せるだけでなく、URL 階層がコード ツリーのレベルであるため、アクセス可能なものを制御するためにホワイトリストまたはブラックリストに注意する必要があることも意味します。構成ファイルやその他の「ローカル モジュール」は、直接ロードを避けるために C などで保護する必要があります。バージョン管理システム内のファイル (.svn など) は保護する必要があります。 mod_php では、ファイル システム内のすべてが潜在的なエントリになりますが、アプリケーション サーバーではエントリが 1 つだけあり、呼び出しは URL によってのみ制御されます。

ユーザーがアップグレードの間にサイトをクリックしたときにアプリケーションがクラッシュして未定義の動作を示したくない場合を除き、CGI スタイルで実行されている大量のファイルをシームレスにアップグレードすることはできません。

PHP を実行するように Apache を構成するのは「簡単」ですが、落とし穴がいくつかあります。 PHP ドキュメントでは、SetHandler を使用して .php ファイルを PHP モードで実行することを推奨しています。AddHandler はうまく動作するように見えますが、実際には問題が発生します。

AddHandler を使用すると、Apache に「php として実行」するように指示することになります。これは、.php ファイルを処理する可能な方法の 1 つです。しかし、Apache はファイル拡張子については考えていません。これは、index.html.en などのファイルをサポートするように設計されています。 Apache では、ファイルに同時に任意の数の拡張子を付けることができます。

パブリック ディレクトリにいくつかのファイルを保存するファイル アップロード フォームがあると思います。誰も PHP ファイルをアップロードできないようにするには、ファイルに .php 拡張子を付けることができないことを確認するだけです。攻撃に必要なのは、foo.php.txt という名前のファイルをアップロードすることだけです。アップロード ツールは問題を認識せず、Apache はそれが PHP であると認識し、問題なく実行します。

これは「元のファイル名を使用する」とか「より適切な検証がない」という問題ではなく、PHP を「簡単にデプロイできる」ようにするためのレガシー コードを実行するように Web サーバーを構成する必要があるということです。これは理論的な問題ではなく、同様の問題を抱えている現実のサイトをたくさん見つけました。

不足している機能

これらはすべて、Web アプリケーションの構築を中心にしていると思います。 PHP は合理的に見えますし、そのセールスポイントの 1 つが「Web の言語」であるため、これらを備えている必要があります。

モジュールシステムはありません。 PHPはテンプレートです。

XSSフィルターはありません。 htmlspecialchars は XSS フィルターではありません。

CSRF保護なし。自分でやらなければなりません。

普遍的な標準データベース API はありません。PDO のようなものは、それぞれの特定のデータベースの API をラップし、異なる部分を個別に抽象化する必要があります。

ルーティングシステムはありません。サイトの構造はファイル システムの構造です。

認証や認可はありません。

開発サーバーはありません。

インタラクティブなデバッグモードはありません。

一貫した展開メカニズムはなく、「すべてのファイルをサーバーにコピーする」だけです。

安全性

言語の境界

PHP の貧弱なセキュリティメカニズムは、ある言語からデータを取り出して別の言語にダンプするため、増幅される可能性があります。これは悪いメモです。 「

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/371411.html技術記事 phpは恥ずかしいです。とても壊れていましたが、訓練されたアマチュアはそれを賞賛しました。 PHP はいくつかの些細な改善策を行っていましたが、私はそれを忘れることにしました。 はじめに...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。