ホームページ バックエンド開発 PHPチュートリアル PHP の構築、破壊、カプセル化オブジェクト指向_PHP チュートリアル

PHP の構築、破壊、カプセル化オブジェクト指向_PHP チュートリアル

Jul 13, 2016 pm 05:13 PM
co php 同じ そして 関数 名前 声明 物体 カプセル化 操作する はい 破壊する のために

コンストラクターの宣言は、その名前が __construct() でなければならないことを除いて、他の操作の宣言と同じです。カプセル化とは、オブジェクトのプロパティとサービスを独立した同一のユニットに結合し、その内部の詳細を隠すことを意味します。可能な限りオブジェクト

構築メソッドとデストラクターメソッド
施工方法:
ほとんどのクラスには、コンストラクターと呼ばれる特別なメソッドがあります。オブジェクトが作成されると、自動的にコンストラクターが呼び出されます。つまり、 new キーワードを使用してオブジェクトをインスタンス化すると、コンストラクターが自動的に呼び出されます。

コンストラクターの宣言は、その名前が __construct() でなければならないことを除いて、他の操作の宣言と同じです。これは PHP5 での変更です。以前のバージョンでは、コンストラクターの名前はクラス名と同じである必要がありました。これは PHP5 でも引き続き使用できますが、この利点は、コンストラクターをクラス名と同じにすることができることです。クラス名に関係なく、クラス名が変更された場合でも、対応するコンストラクター名を変更する必要はありません。下位互換性のために、クラスに __construct() という名前のメソッドがない場合、PHP はクラス名と同じ名前で php4 で記述されたコンストラクター メソッドを検索します。

形式: function __construct ( [パラメータ] ) { ... ... }

クラス内で宣言できるコンストラクターは 1 つだけですが、コンストラクターはオブジェクトが作成されるたびに 1 回しか呼び出されないため、このメソッドはアクティブに呼び出すことができないため、通常はいくつかの便利な初期化タスクを実行するために使用されます。たとえば、オブジェクトの作成時に、対応するプロパティに初期値が割り当てられます。

コードは次のとおりです コードをコピー

//人間を作成する
クラスの人
{
//以下は人々のメンバー属性です
var $name //その人の名前
var $sex //人の性別
var $age //人の年齢

//コンストラクターのパラメーターを名前 $name、性別 $sex、年齢 $age として定義します
関数 __construct($name, $sex, $age)
{
//構築メソッドを通じて渡された $name には、メンバー属性 $this->name に初期値が割り当てられます
$this->name=$name; //構築メソッドを通じて渡された $sex には、メンバー属性 $this->sex に初期値が割り当てられます
$this->sex=$sex; //構築メソッドを通じて渡された $age には、メンバー プロパティ $this->age に初期値が割り当てられます
$this->age=$age; }

//この人の話し方
関数say()
{
echo "私の名前: ".$this->name." 性別: ".$this->性別" 私の年齢: ".$this->age."
}
}

//構築メソッドを通じて 3 つのオブジェクト $p1、p2、$p3 を作成し、3 つの異なる実際のパラメーター (名前、性別、年齢) を渡します
$p1=新しい人("張三","男性", 20); $p2=新しい人("李思","女", 30); $p3=新しい人("王五","男", 40);
// 以下は、$p1 オブジェクトの発話メソッドにアクセスします
$p1->say(); //以下は $p2 オブジェクトの発話メソッドにアクセスします
$p2->say(); //以下は $p3 オブジェクトの発話メソッドにアクセスします
$p3->say();
出力結果は次のようになります:
私の名前: Zhang San 性別: 男性 私の年齢: 20
私の名前は: Li Si 性別: 女性 私の年齢: 30
私の名前は: Wang Wu 性別: 男性 私の年齢: 40

//人間を作成する
クラス人
{
//人のメンバー属性は以下の通りです
var $name //その人の名前
var $sex //人の性別
var $age //その人の年齢

//コンストラクターのパラメーターを名前 $name、性別 $sex、年齢 $age として定義します
関数 __construct($name, $sex, $age)
{
//構築メソッドを通じて渡された $name には、メンバー属性 $this->name
に初期値が割り当てられます $this->name=$name;
//コンストラクターを通じて渡された $sex には、メンバー属性 $this->sex
の初期値が割り当てられます $this->sex=$sex;
//構築メソッドを通じて渡された $age は、メンバー属性 $this->age
に初期値を割り当てます $this->age=$age;
}

//この人の話し方
関数say()
{
echo "私の名前は: ".$this->name." 性別: ".$this->性別" 私の年齢: ".$this->age."";
}
}

//構築メソッドを通じて 3 つのオブジェクト $p1、p2、$p3 を作成し、3 つの異なる実際のパラメーター: 名前、性別、年齢を渡します
$p1=新しい人("張三","男性", 20);
$p2=新しい人("李思","女", 30);
$p3=新しい人("王五","男", 40);

//以下は$p1オブジェクトのspeakingメソッドにアクセスします
$p1->say();
//以下は $p2 オブジェクトの発話メソッドにアクセスします
$p2->say();
//以下は $p3 オブジェクトの発話メソッドにアクセスします
$p3->say();

出力結果は次のとおりです:
私の名前:張三 性別:男性 年齢:20歳
私の名前は: Li Si 性別: 女性 私の年齢: 30
私の名前:王呉 性別:男性 年齢:40歳

デストラクター:
コンストラクターの反対はデストラクターです。デストラクタは、PHP5 で新しく追加された内容です。PHP4 にはデストラクタはありません。デストラクターを使用すると、クラスを破棄する前に、ファイルを閉じる、結果セットを解放するなど、一部の操作を実行したり、一部の機能を完了したりできます。デストラクターは、オブジェクトへのすべての参照が削除されるか、オブジェクトが明示的に破棄されるときに削除されます。オブジェクトがメモリ内で破棄されるときに実行されます。つまり、デストラクタは、オブジェクトがメモリ内で破棄される前に呼び出されます。コンストラクターの名前と同様に、クラスのデストラクターの名前は __destruct() でなければなりません。デストラクターはパラメータを取ることができません。
形式: function __destruct ( ) { ... ... }

コードは次のとおりです コードをコピー
//人間を作成する
クラスの人
{
//以下は人々のメンバー属性です
var $name //その人の名前
var $sex //人の性別
var $age //人の年齢

//コンストラクターのパラメーターを名前 $name、性別 $sex、年齢 $age として定義します
関数 __construct($name, $sex, $age)
{
//構築メソッドを通じて渡された $name には、メンバー属性 $this->name に初期値が割り当てられます
$this->name=$name; //構築メソッドを通じて渡された $sex には、メンバー属性 $this->sex に初期値が割り当てられます
$this->sex=$sex; //構築メソッドを通じて渡された $age には、メンバー プロパティ $this->age に初期値が割り当てられます
$this->age=$age; }

//この人の話し方
関数say()
{
echo "私の名前: ".$this->name." 性別: ".$this->性別" 私の年齢: ".$this->age."
                                                                 
//これはデストラクターであり、オブジェクトが破棄される前に呼び出されます
関数 __destruct()
{
echo "さようなら".$this->name.""; }
}

//構築メソッドを通じて 3 つのオブジェクト $p1、p2、$p3 を作成し、3 つの異なる実際のパラメーター (名前、性別、年齢) を渡します
$p1=新しい人("張三","男性", 20); $p2=新しい人("李思","女", 30); $p3=新しい人("王五","男", 40);
// 以下は、$p1 オブジェクトの発話メソッドにアクセスします
$p1->say(); //以下は $p2 オブジェクトの発話メソッドにアクセスします
$p2->say(); //以下は $p3 オブジェクトの発話メソッドにアクセスします
$p3->say();
出力結果は次のようになります:

私の名前: Zhang San 性別: 男性 私の年齢: 20
私の名前は: Li Si 性別: 女性 私の年齢: 30
私の名前は: Wang Wu 性別: 男性 私の年齢: 40

さようなら、チャンサン
さようならリーシ
さようなら、王呉



カプセル化
カプセル化は、オブジェクト指向プログラミングの 3 つの主要な特徴の 1 つであり、オブジェクトのプロパティとサービスを独立した同一のユニットに結合することと、オブジェクトの内部の詳細を可能な限り隠すことです。意味: 1. オブジェクトのすべてのプロパティとすべてのサービスが結合されて、分割できない独立した単位 (オブジェクト) を形成します。 2. 情報の隠蔽、つまり物体の内部の詳細を可能な限り隠し、外界との境界を形成(または障壁を形成)し、外部と接続するための限られた外部インターフェースのみを保持する。

ソフトウェアにおけるカプセル化の原理の反映は、オブジェクト以外の部分がオブジェクトの内部データ (プロパティ) に自由にアクセスできないようにすることを必要とするため、外部エラーの「相互感染」を効果的に回避し、ソフトウェア エラーを可能にします。ローカライズされるため、エラー チェックとトラブルシューティングの難しさが大幅に軽減されます。

人のオブジェクトに年齢や給与などの属性があるとします。このような個人のプライバシー属性は、カプセル化を使用しない場合、他の人がそれを知ることができます。あなたはそれを取得できますが、それをカプセル化すると、自分がそれを伝えない限り、他の人はそのカプセル化された属性を取得することができなくなります。たとえば、パーソナル コンピュータにはパスワードがあり、他人が勝手にログインしたり、それをコピーして自分のコンピュータに貼り付けたりすることは望ましくありません。また、人間のような物体においては、身長や年齢といった属性は自分自身でのみ増加させることができ、他人等が恣意的に値を割り当てることはできない。

コードは次のとおりです コードをコピー

//private キーワードを使用してプロパティとメソッドをカプセル化します:
//オリジナルメンバー:
var $name //宣言者の名前
var $sex; //その人の性別を宣言します
var $age //宣言者の年齢
関数 run(){…….}

//カプセル化された形式に変更:
private $name //private キーワードを使用して人の名前をカプセル化します
private $sex; //private キーワードを使用して人の性別をカプセル化します
private $age //private キーワードを使用して人の年齢をカプセル化します
private function run(){……} //private キーワードを使用して人の歩行方法をカプセル化します

//private キーワードを使用してプロパティとメソッドをカプセル化します:
//オリジナルメンバー:
var $name; //宣言者の名前
var $sex //人の性別を宣言します
var $age //宣言者の年齢
関数 run(){…….}

//カプセル化された形式に変更:
private $name //private キーワードを使用して人の名前をカプセル化します
private $sex; //private キーワードを使用して人の性別をカプセル化します
private $age //private キーワードを使用して人の年齢をカプセル化します
private function run(){……} //private キーワードを使用して人の歩行メソッドをカプセル化します。 注: メンバー属性の前に他のキーワードがある限り、元のキーワード「var」を削除する必要があります。 use private 人間のメンバー (メンバー プロパティとメンバー メソッド) をカプセル化します。カプセル化内のメンバーにはクラスの外部から直接アクセスすることはできません。次のコードではエラーが生成されます。


クラスの人
{
//以下は人々のメンバー属性です
Private $name; //その人の名前は private
でカプセル化されます。 Private $sex; //人の性別は private
によってカプセル化されます。 Private $age; //人の年齢は private
によってカプセル化されます。
//この人はどうやって話せますか
関数say()
{
echo "私の名前: ".$this->name." 性別: ".$this->性別" 私の年齢: ".$this->age."
                                                               
//この人の歩き方はプライベートにカプセル化されています
プライベート関数 run()
{
エコー「この人は歩いています」 }
}
//人のインスタンスオブジェクトをインスタンス化します
$p1=新しい人
;
//プライベート属性に値を代入しようとするとエラーになります
$p1->name="張三"; $p1->性別="男性"; $p1-> 年齢 = 20;
//プライベート属性を出力しようとすると、エラーが発生します
echo $p1->name.""; エコー $p1->セックス。""; echo $p1->年齢。""

//プライベートメンバーメソッドを出力しようとすると、エラーが発生します
$p1->run();
出力結果は次のようになります:
致命的なエラー: プライベート プロパティ person::$name にアクセスできません
致命的なエラー: プライベート プロパティ person::$sex にアクセスできません
致命的なエラー: プライベート プロパティ person::$age にアクセスできません
致命的なエラー: プライベート プロパティ person::$name にアクセスできません
致命的なエラー: コンテキスト '' からプライベート メソッド Person::run() を呼び出します

クラスの人
{
//人のメンバー属性は以下の通りです
Private $name; //その人の名前は private
でカプセル化されます。 Private $sex; //人の性別は private
によってカプセル化されます Private $age; //人の年齢は private
によってカプセル化されます

//この人はどのように話すことができるのか

関数say()
{
echo "私の名前は: ".$this->name." 性別: ".$this->性別" 私の年齢: ".$this->age."";
}

//この人の歩き方はプライベートにカプセル化されています

プライベート関数 run()

{
echo "この人は歩いています";
}
}
//人のインスタンスオブジェクトをインスタンス化します

$p1=新しい人();


//プライベート属性に値を割り当てようとするとエラーが発生します
$p1->name="張三";
$p1->sex="男性";
$p1->年齢=20;

//プライベート属性を出力しようとするとエラーが発生します
echo $p1->name."";

echo $p1->sex."";

echo $p1->age.""

//プライベートメンバーメソッドを出力しようとするとエラーが発生します
$p1->run();

出力結果は次のとおりです:
致命的なエラー: プライベート プロパティ Person::$name にアクセスできません
致命的なエラー: プライベート プロパティ person::$sex にアクセスできません
致命的なエラー: プライベート プロパティ Person::$age にアクセスできません

致命的なエラー: プライベート プロパティ Person::$name にアクセスできません

致命的なエラー: コンテキスト ''
からプライベート メソッド Person::run() を呼び出します


上記の例からわかるように、プライベート メンバーはこのオブジェクト内でのみアクセスできるため、外部からアクセスすることはできません。たとえば、オブジェクト $p1 がそのプライベート属性を共有したい場合、say() でこのメソッドがアクセスします。私有地、それは問題ありません。 (アクセス制御は追加されていません。デフォルトはパブリックで、どこからでもアクセスできます)


//この人の話し方、自分のプライベート属性を話す方法、そしてここからプライベート メソッドにアクセスすることもできます

コードは次のとおりです コードをコピー

関数say()
{
echo "私の名前は: ".$this->name" 性別: ".$this->性別" 私の年齢: ".$this->age"
";
//ここからプライベート メソッドにもアクセスできます
//$this->run(); }

//この人が話すことができるメソッド、彼自身のプライベートな属性を話す、そしてプライベートなメソッドにもここからアクセスできます

関数say()
{
echo "私の名前は: ".$this->name" 性別: ".$this->性別" 私の年齢: ".$this->age"
";
//ここからプライベート メソッドにアクセスすることもできます
//$this->run();
}メンバーメソッドsay()はパブリックなので、クラスの外でsay()メソッドを呼び出しても問題ありません

クラスの人
{
//以下は人々のメンバー属性です
Private $name; //その人の名前は private
でカプセル化されます。 Private $sex; //人の性別は private
によってカプセル化されます。 Private $age; //人の年齢は private
によってカプセル化されます。
//プライベート属性の名前 $name、性別 $sex、年齢 $age に値を割り当てるコンストラクター パラメーターを定義します
関数 __construct($name, $sex, $age)
{
//コンストラクターを通じて渡された $name には、プライベート メンバー プロパティ $this->name の初期値が割り当てられます
$this->name=$name; //コンストラクターを通じて渡された $sex には、プライベート メンバー プロパティ $this->sex の初期値が割り当てられます
$this->sex=$sex; //コンストラクターを通じて渡された $age には、プライベート メンバー プロパティ $this->age の初期値が割り当てられます
$this->age=$age; }

//この人は、自分自身のプライベート属性を話す方法で話すことができます。プライベート メソッドにもここからアクセスできます
関数say()
{
echo "私の名前は: ".$this->name" 性別: ".$this->性別" 私の年齢: ".$this->age"
";
}
}

//構築メソッドを通じて 3 つのオブジェクト $p1、p2、$p3 を作成し、3 つの異なる実際のパラメーター (名前、性別、年齢) を渡します
$p1=新しい人("張三", "男性", 20); $p2=新しい人("李思","女", 30); $p3=新しい人("王五","男", 40);
// 以下は、$p1 オブジェクトの発話メソッドにアクセスします
$p1->say(); //以下は $p2 オブジェクトの発話メソッドにアクセスします
$p2->say(); //以下は $p3 オブジェクトの発話メソッドにアクセスします
$p3->say();
出力結果は次のようになります:
私の名前: Zhang San 性別: 男性 私の年齢: 20
私の名前は: Li Si 性別: 女性 私の年齢: 30
私の名前は: Wang Wu 性別: 男性 私の年齢: 40

クラスの人
{
//人のメンバー属性は以下の通りです
Private $name; //その人の名前は private
でカプセル化されます。 Private $sex; //人の性別は private
によってカプセル化されます Private $age; //人の年齢は private

によってカプセル化されます

//プライベート属性の名前 $name、性別 $sex、年齢 $age に値を割り当てるコンストラクター パラメーターを定義します
関数 __construct($name, $sex, $age)
{
//コンストラクターを通じて渡された $name には、プライベート メンバー プロパティ $this->name
の初期値が割り当てられます $this->name=$name;
//コンストラクターを通じて渡された $sex には、プライベート メンバー プロパティ $this->sex
に初期値が割り当てられます $this->sex=$sex;
//コンストラクターを通じて渡された $age には、プライベート メンバー プロパティ $this->age
の初期値が割り当てられます $this->age=$age;
}

//この人は、自分自身のプライベート属性を話す方法で話すことができます。プライベート メソッドにもここからアクセスできます
。 関数say()
{
echo "私の名前は: ".$this->name" 性別: ".$this->性別" 私の年齢: ".$this->age"
";
}
}

//構築メソッドを通じて 3 つのオブジェクト $p1、p2、$p3 を作成し、3 つの異なる実際のパラメーター: 名前、性別、年齢を渡します
$p1=新しい人("張三", "男性", 20);
$p2=新しい人("李思","女", 30);
$p3=新しい人("王五","男", 40);

//以下は$p1オブジェクトのspeakingメソッドにアクセスします
$p1->say();
//以下は $p2 オブジェクトの発話メソッドにアクセスします
$p2->say();
//以下は $p3 オブジェクトの発話メソッドにアクセスします
$p3->say();

出力結果は次のとおりです:
私の名前:張三 性別:男性 年齢:20歳
私の名前は: Li Si 性別: 女性 私の年齢: 30
私の名前:Wang Wu 性別:男性 私の年齢:40 コンストラクターはデフォルトのパブリック メソッドであるため (コンストラクターをプライベートに設定しないでください)、クラス外からアクセスできるため、コンストラクターを使用してオブジェクトを作成し、コンストラクターもクラス内の関数であるため、コンストラクターを使用してプライベート プロパティに初期値を割り当てることができます。 Say() メソッドはデフォルトでパブリックであるため、外部からアクセスして独自のプライベート プロパティを伝えることができます。

上記の例から、プライベート メンバーはクラス内でのみ使用でき、クラス外からは直接アクセスできないことがわかります。ただし、クラス内にアクセスする権限があるため、場合によってはプライベート プロパティの割り当てと読み取りが必要になります。外部とは、クラスの外部にアクセス可能なインターフェイスを提供することを意味します。上記の例では、コンストラクター メソッドは代入の形式ですが、コンストラクター メソッドは、オブジェクトを作成するときに値を代入するだけです。この既存のオブジェクトに値を割り当てる場合、コンストラクター メソッドも使用して値を渡すと、既存のオブジェクトではなく新しいオブジェクトが作成されます。したがって、外部からアクセスできるプライベート属性用のインターフェイスをいくつか作成する必要があります。目的は、オブジェクトが存在するときに属性の値を変更してアクセスすることです。ただし、これは必要な属性に対してのみ実行できることに注意してください。外部からアクセスされることを望まないプロパティにはそのようなインターフェイスがありません。そのため、カプセル化の目的はオブジェクト自体によって完了し、オブジェクトへの操作は最小限に抑えられます。外の世界。

クラスの外にインターフェイスを提供する場合、クラスの外にプライベート プロパティの設定メソッドと取得メソッドを提供して、プライベート プロパティを操作できます。例:

上記のメソッドはメンバー属性の値を設定および取得するものですが、同じメソッドを使用して各属性の値を割り当ておよび取得し、クラスの外でアクセス作業を完了することもできます。
コードは次のとおりです コードをコピー

//プライベート属性の年齢
プライベート $ 年齢

//年齢を外部から設定するためのパブリックメソッドを提供します
関数 setAge($age)
{
//属性に値を代入する際、属性に不正な値が設定されることを避けるため
If($年齢130)
戻る; $this->年齢=$年齢
}

//年齢を外部から取得するためのパブリックメソッドを提供します
関数 getAge()
{
戻る($this->年齢); }

//プライベート属性の年齢

プライベート $age;


//外部向けに年齢を設定するためのパブリックメソッドを提供します

関数 setAge($age)

{
//属性に値を代入する際、属性に不正な値が設定されることを避けるため
if($年齢130)
戻る;
$this->age=$age;
}

//外部関係者向けに年齢を取得するための公開メソッドを提供します

関数getAge()

{
return($this->年齢);
}アップ

http://www.bkjia.com/PHPjc/629193.html

tru​​ehttp://www.bkjia.com/PHPjc/629193.html技術記事コンストラクターの宣言は、その名前が __construct() である必要があることを除いて、他の操作の宣言と同じです。カプセル化とは、オブジェクトのプロパティとサービスを独立した同一のユニットに結合し、次のことを試みることです...
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

CakePHP プロジェクトの構成 CakePHP プロジェクトの構成 Sep 10, 2024 pm 05:25 PM

この章では、CakePHP の環境変数、一般設定、データベース設定、電子メール設定について理解します。

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

CakePHP の日付と時刻 CakePHP の日付と時刻 Sep 10, 2024 pm 05:27 PM

Cakephp4 で日付と時刻を操作するには、利用可能な FrozenTime クラスを利用します。

CakePHP ファイルのアップロード CakePHP ファイルのアップロード Sep 10, 2024 pm 05:27 PM

ファイルのアップロードを行うには、フォーム ヘルパーを使用します。ここではファイルアップロードの例を示します。

CakePHP ルーティング CakePHP ルーティング Sep 10, 2024 pm 05:25 PM

この章では、ルーティングに関連する次のトピックを学習します。

CakePHP データベースの操作 CakePHP データベースの操作 Sep 10, 2024 pm 05:25 PM

CakePHP でデータベースを操作するのは非常に簡単です。この章では、CRUD (作成、読み取り、更新、削除) 操作について理解します。

CakePHP について話し合う CakePHP について話し合う Sep 10, 2024 pm 05:28 PM

CakePHP は、PHP 用のオープンソース フレームワークです。これは、アプリケーションの開発、展開、保守をより簡単にすることを目的としています。 CakePHP は、強力かつ理解しやすい MVC のようなアーキテクチャに基づいています。モデル、ビュー、コントローラー

CakePHP バリデータの作成 CakePHP バリデータの作成 Sep 10, 2024 pm 05:26 PM

Validator は、コントローラーに次の 2 行を追加することで作成できます。

See all articles