PHP 8.4.2 Released!

クラスの基礎

class

各クラスの定義は、classキーワードで始まり、クラス名が続きます。 そしてその後に波括弧のペアが続き、 その中にはクラスのプロパティとメソッドの定義を記述します。

クラス名には、PHP の予約語 以外でラベルとして有効なあらゆる名前を使用することができます。 PHP 8.4.0 以降では、アンダースコア (_) 1文字のみのクラス名は非推奨となりました。 有効なクラス名は、先頭が文字あるいはアンダースコアで始まり、 その後に任意の数の文字/数字/アンダースコアが続くものです。 正規表現で表すと、 ^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$ のようになります。

クラスの中には、 定数変数 ("プロパティ" といいます) そして関数 ("メソッド" といいます) を含めることができます。

例1 簡単なクラス定義

<?php
class SimpleClass
{
// プロパティの宣言
public $var = 'a default value';

// メソッドの宣言
public function displayVar() {
echo
$this->var;
}
}
?>

メソッドがオブジェクトのコンテキストからコールされる場合は、 疑似変数 $this が利用可能です。 $this は、呼び出し元オブジェクトの値です。

警告

static でないメソッドを static メソッドとしてコールすると、 Error がスローされます。 PHP 8.0.0 より前のバージョンでは、推奨されない警告が発生し、 $this が未定義になっていました。

例2 $this 疑似変数の例

<?php
class A
{
function
foo()
{
if (isset(
$this)) {
echo
'$this is defined (';
echo
get_class($this);
echo
")\n";
} else {
echo
"\$this is not defined.\n";
}
}
}

class
B
{
function
bar()
{
A::foo();
}
}

$a = new A();
$a->foo();

A::foo();

$b = new B();
$b->bar();

B::bar();
?>

上の例の PHP 7 での出力は、このようになります。

$this is defined (A)

Deprecated: Non-static method A::foo() should not be called statically in %s  on line 27
$this is not defined.

Deprecated: Non-static method A::foo() should not be called statically in %s  on line 20
$this is not defined.

Deprecated: Non-static method B::bar() should not be called statically in %s  on line 32

Deprecated: Non-static method A::foo() should not be called statically in %s  on line 20
$this is not defined.

上の例の PHP 8 での出力は、このようになります。:

$this is defined (A)

Fatal error: Uncaught Error: Non-static method A::foo() cannot be called statically in %s :27
Stack trace:
#0 {main}
  thrown in %s  on line 27

読み取り専用クラス

PHP 8.2.0 以降では、 クラスに対して readonly を指定することができます。 クラスに対して readonly を指定すると、 宣言されている全ての プロパティに対して readonly を指定した ことになり、 かつ 動的なプロパティ の作成を禁止したことになります。 さらに、AllowDynamicProperties アトリビュートを指定しても動的なプロパティを作成できなくなります。 動的なプロパティを作成しようとすると、コンパイル時にエラーが発生します。

<?php
#[\AllowDynamicProperties]
readonly class
Foo {
}

// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo
?>

型を指定していないプロパティや、 static プロパティ に対しては readonly を指定できません。 readonly クラスには、それらをいずれも指定できません:

<?php
readonly class Foo
{
public
$bar;
}

// Fatal error: Readonly property Foo::$bar must have type
?>
<?php
readonly class Foo
{
public static
int $bar;
}

// Fatal error: Readonly class Foo cannot declare static properties
?>

readonly を指定したクラスは、 子クラスでも readonly を指定した場合にのみ 継承 できます。

new

あるクラスのインスタンスを生成するには、new キーワードを使わなければなりません。エラー時に 例外をスローするような コンストラクタを定義していない限り、 オブジェクトが常に生成されます。 クラスは、そのインスタンスを作成する前に定義すべきです (これが必須となる場合もあります)。

クラス名を含む文字列を new で指定すると、 そのクラスのインスタンスを作成します。クラスが名前空間に属している場合は、 完全修飾名を指定しなければなりません。

注意:

クラスのコンストラクタに引数を渡さなかった場合、 クラス名の後の括弧は省略しても構いません。

例3 インスタンスを作成する

<?php
$instance
= new SimpleClass();

// 変数を使うこともできます
$className = 'SimpleClass';
$instance = new $className(); // new SimpleClass()
?>

クラスのコンテキストにおいては、 new selfnew parent のようにして新しいオブジェクトを作成することができます。

作成済みのクラスのインスタンスを新たな変数に代入する場合、新しい変数は、 代入されたオブジェクトと同じインスタンスにアクセスします。 この動作は、インスタンスを関数に渡す場合も同様です。 作成済みのオブジェクトのコピーは、その クローンを作成 することにより作成可能です。

例4 オブジェクトの代入

<?php

$instance
= new SimpleClass();

$assigned = $instance;
$reference =& $instance;

$instance->var = '$assigned will have this value';

$instance = null; // $instance と $reference は null になります

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

上の例の出力は以下となります。

NULL
NULL
object(SimpleClass)#1 (1) {
   ["var"]=>
     string(30) "$assigned will have this value"
}

PHP 8.0.0 以降では、 new を任意の式と一緒に使う機能がサポートされました。 これによって、式が文字列を生成する場合に、 より複雑なインスタンス化を行えるようになります。 式は括弧で囲まなければいけません。

例5 任意の式を使ってインスタンスを生成する

以下の例では、 クラス名を生成する有効な任意の式を複数示します。 関数呼び出し、文字列連結、そして ::class 定数です。

<?php

class ClassA extends \stdClass {}
class
ClassB extends \stdClass {}
class
ClassC extends ClassB {}
class
ClassD extends ClassA {}

function
getSomeClass(): string
{
return
'ClassA';
}

var_dump(new (getSomeClass()));
var_dump(new ('Class' . 'B'));
var_dump(new ('Class' . 'C'));
var_dump(new (ClassD::class));
?>

上の例の PHP 8 での出力は、このようになります。:

object(ClassA)#1 (0) {
}
object(ClassB)#1 (0) {
}
object(ClassC)#1 (0) {
}
object(ClassD)#1 (0) {
}

複数のやり方で、オブジェクトのインスタンスを作ることが出来ます:

例6 新しいオブジェクトの作成

<?php
class Test
{
static public function
getNew()
{
return new static;
}
}

class
Child extends Test
{}

$obj1 = new Test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);

$obj3 = Test::getNew();
var_dump($obj3 instanceof Test);

$obj4 = Child::getNew();
var_dump($obj4 instanceof Child);
?>

上の例の出力は以下となります。

bool(true)
bool(true)
bool(true)

新しく作成したオブジェクトのメンバーに、作成したその式の中でもアクセスすることができます。

例7 新しく作成したオブジェクトのメンバーへのアクセス

<?php
echo (new DateTime())->format('Y');
// PHP 8.4.0 以降、囲む括弧は省略可能です。
echo new DateTime()->format('Y');
?>

上の例の出力は、 たとえば以下のようになります。

2016

注意: PHP 7.1 より前のバージョンでは、コンストラクタが定義されない場合、それへの引数が評価されていませんでした。

プロパティとメソッド

クラスのプロパティとメソッドは、それぞれ別の "名前空間" に存在するので、 同じ名前のプロパティとメソッドを共存させることもできます。 プロパティを参照する場合もメソッドを参照する場合も書きかたは同じです。 それがプロパティへのアクセスなのかメソッドの呼び出しなのかは、そのコンテキストによって決まります。 つまり、変数にアクセスしようとしているのか関数を呼び出そうとしているのかの違いです。

例8 プロパティへのアクセスとメソッドの呼び出し

<?php
class Foo
{
public
$bar = 'property';

public function
bar() {
return
'method';
}
}

$obj = new Foo();
echo
$obj->bar, PHP_EOL, $obj->bar(), PHP_EOL;

上の例の出力は以下となります。

property
method

これはつまり、プロパティに 無名関数 を代入した場合に、その関数は直接呼び出せないということです。 その場合は、たとえば事前にプロパティを変数に代入しておく必要があります。 括弧で囲むと、プロパティを直接呼び出すこともできます。

例9 プロパティに格納した無名関数の呼び出し

<?php
class Foo
{
public
$bar;

public function
__construct() {
$this->bar = function() {
return
42;
};
}
}

$obj = new Foo();

echo (
$obj->bar)(), PHP_EOL;

上の例の出力は以下となります。

42

extends

クラスは、宣言部に extends キーワードを含めることで、 他のクラスの定数や、メソッド、 およびプロパティを継承することができます。多重継承を行うことはできず、クラスが継承できるベース クラスは一つだけです。

継承された定数やメソッド、プロパティをオーバーライド(上書き)するには、 親クラスで定義されているのと同じ名前でそれを再宣言します。 しかし、親クラスでそのメソッドや定数が final として定義されている場合はオーバーライドできません。 オーバーライドされた元のメソッドやstaticプロパティにアクセスするには、 parent:: で参照します。

注意: PHP 8.1.0 以降では、定数も final として宣言できます。

例10 簡単なクラスの継承

<?php
class ExtendClass extends SimpleClass
{
// 親クラスのメソッドを再定義
function displayVar()
{
echo
"Extending class\n";
parent::displayVar();
}
}

$extended = new ExtendClass();
$extended->displayVar();
?>

上の例の出力は以下となります。

Extending class
a default value

シグネチャの互換性に関するルール

メソッドをオーバーライドするときは、 子クラスのシグネチャが親クラスのそれと互換性がなければいけません。 互換性が壊れた場合、致命的なエラーが発生します。 PHP 8.0.0 より前のバージョンでは、 互換性が壊れた場合に、E_WARNING レベルの警告が発生していました。 共変性と反変性 の規則を守っている場合は、シグネチャに互換性があります。 必須の引数をオプションにした場合も、互換性があります。 新しいオプションの引数を追加しただけで、アクセス権を厳しくせず、 緩めただけの場合も互換性があります。 これは、リスコフの置換原則(Liskov Substitution Principle)、 略して LSP として知られています。 但し、コンストラクタprivate メソッドについては、 この規則の例外で、 オーバライドしたシグネチャにミスマッチがあっても致命的なエラーにはなりません。

例11 互換性がある子クラスのメソッド

<?php
class Base
{
public function
foo(int $a) {
echo
"Valid\n";
}
}
class
Extend1 extends Base
{
function
foo(int $a = 5)
{
parent::foo($a);
}
}
class
Extend2 extends Base
{
function
foo(int $a, $b = 5)
{
parent::foo($a);
}
}
$extended1 = new Extend1();
$extended1->foo();
$extended2 = new Extend2();
$extended2->foo(1);

上の例の出力は以下となります。

Valid
Valid

次の例は、引数を削除した子クラスのメソッドや、 オプションの引数を必須にしたりすることが、親クラスのメソッドと互換性がなくなることを示しています。

例12 子クラスのメソッドで引数を削除すると致命的なエラーになる

<?php
class Base
{
public function
foo(int $a = 5) {
echo
"Valid\n";
}
}
class
Extend extends Base
{
function
foo()
{
parent::foo(1);
}
}

上の例の PHP 8 での出力は、たとえば以下のようになります。:

Fatal error: Declaration of Extend::foo() must be compatible with Base::foo(int $a = 5) in /in/evtlq on line 13

例13 子クラスのメソッドで、オプションの引数を必須にすると致命的なエラーになる

<?php
class Base
{
public function
foo(int $a = 5) {
echo
"Valid\n";
}
}
class
Extend extends Base
{
function
foo(int $a)
{
parent::foo($a);
}
}

上の例の PHP 8 での出力は、たとえば以下のようになります。:

Fatal error: Declaration of Extend::foo(int $a) must be compatible with Base::foo(int $a = 5) in /in/qJXVC on line 13
警告

メソッドの引数の名前を子クラスで変更しても、 シグネチャ上は非互換になりません。 しかし、こうしてしまうと 名前付き引数 を使った時に実行時エラーになるので、おすすめできません。

例14 子クラスで引数の名前を変更し、かつ名前付き引数を使うとエラーになる

<?php
class A {
public function
test($foo, $bar) {}
}
class
B extends A {
public function
test($a, $b) {}
}
$obj = new B;
// A::test() の規約に従って引数を渡す
$obj->test(foo: "foo", bar: "bar"); // エラー発生!

上の例の出力は、 たとえば以下のようになります。

Fatal error: Uncaught Error: Unknown named parameter $foo in /in/XaaeN:14
Stack trace:
#0 {main}
  thrown in /in/XaaeN on line 14

::class

class キーワードでもクラス名の解決を行うことが出来ます。 クラスの名前が ClassName になっているクラスの完全修飾名を取得するには、 ClassName::class を使います。 これは、名前空間付きのクラスに使うと特に便利です。

例15 クラス名の解決

<?php
namespace NS {
class
ClassName {
}

echo
ClassName::class;
}
?>

上の例の出力は以下となります。

NS\ClassName

注意:

::class によるクラス名の解決は、コンパイル時の変換です。 つまり、クラス名を作るタイミングでは、まだオートロードが行われていないということです。 結果的に、クラスがまだ存在しない時点でクラス名が展開されることになります。 この場合にはエラーは発生しません。

例16 クラス名が存在しない場合の名前解決

<?php
print Does\Not\Exist::class;
?>

上の例の出力は以下となります。

Does\Not\Exist

PHP 8.0.0 以降では、 ::class はオブジェクトに対しても使えるようになりました。 この名前解決はコンパイル時ではなく、実行時に行われます。 この場合、get_class() をオブジェクトに対して使った時と同じ動きをします。

例17 オブジェクトの名前解決

<?php
namespace NS {
class
ClassName {
}
}
$c = new ClassName();
print
$c::class;
?>

上の例の出力は以下となります。

NS\ClassName

nullsafe メソッドとプロパティ

PHP 8.0.0 以降では、プロパティやメソッドは "nullsafe" 演算子 ?-> を使ってアクセスすることもできます。 nullsafe 演算子は既に述べたメソッドやプロパティと同じように振る舞いますが、 オブジェクトが null と評価された場合に、例外はスローされず、 null が返される点だけが異なります。 オブジェクトの評価がチェインの一部だった場合は、 残りのチェインはスキップされます。

この演算子の働きは、 オブジェクトにアクセスするたびに is_null() でラップするコードに似ています。 しかし、よりコンパクトです。

例18 nullsafe 演算子

<?php

// PHP 8.0.0 以降は、このように書けます:
$result = $repository?->getUser(5)?->name;

// これは、以下のコードチェックと同等です:
if (is_null($repository)) {
$result = null;
} else {
$user = $repository->getUser(5);
if (
is_null($user)) {
$result = null;
} else {
$result = $user->name;
}
}
?>

注意:

nullsafe 演算子は、プロパティやメソッドが値を返す際、 null が正しく、期待されうる値とみなせる場合に一番よく使います。 エラーを示すためなら、例外をスローするほうが好ましいです。

add a note

User Contributed Notes 11 notes

up
641
aaron at thatone dot com
17 years ago
I was confused at first about object assignment, because it's not quite the same as normal assignment or assignment by reference. But I think I've figured out what's going on.

First, think of variables in PHP as data slots. Each one is a name that points to a data slot that can hold a value that is one of the basic data types: a number, a string, a boolean, etc. When you create a reference, you are making a second name that points at the same data slot. When you assign one variable to another, you are copying the contents of one data slot to another data slot.

Now, the trick is that object instances are not like the basic data types. They cannot be held in the data slots directly. Instead, an object's "handle" goes in the data slot. This is an identifier that points at one particular instance of an obect. So, the object handle, although not directly visible to the programmer, is one of the basic datatypes.

What makes this tricky is that when you take a variable which holds an object handle, and you assign it to another variable, that other variable gets a copy of the same object handle. This means that both variables can change the state of the same object instance. But they are not references, so if one of the variables is assigned a new value, it does not affect the other variable.

<?php
// Assignment of an object
Class Object{
public
$foo="bar";
};

$objectVar = new Object();
$reference =& $objectVar;
$assignment = $objectVar

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="bar"
//
?>

$assignment has a different data slot from $objectVar, but its data slot holds a handle to the same object. This makes it behave in some ways like a reference. If you use the variable $objectVar to change the state of the Object instance, those changes also show up under $assignment, because it is pointing at that same Object instance.

<?php
$objectVar
->foo = "qux";
print_r( $objectVar );
print_r( $reference );
print_r( $assignment );

//
// $objectVar --->+---------+
// |(handle1)----+
// $reference --->+---------+ |
// |
// +---------+ |
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
//
?>

But it is not exactly the same as a reference. If you null out $objectVar, you replace the handle in its data slot with NULL. This means that $reference, which points at the same data slot, will also be NULL. But $assignment, which is a different data slot, will still hold its copy of the handle to the Object instance, so it will not be NULL.

<?php
$objectVar
= null;
print_r($objectVar);
print_r($reference);
print_r($assignment);

//
// $objectVar --->+---------+
// | NULL |
// $reference --->+---------+
//
// +---------+
// $assignment -->|(handle1)----+
// +---------+ |
// |
// v
// Object(1):foo="qux"
?>
up
88
kStarbe at gmail point com
7 years ago
You start using :: in second example although the static concept has not been explained. This is not easy to discover when you are starting from the basics.
up
129
Doug
14 years ago
What is the difference between $this and self ?

Inside a class definition, $this refers to the current object, while self refers to the current class.

It is necessary to refer to a class element using self ,
and refer to an object element using $this .
Note also how an object variable must be preceded by a keyword in its definition.

The following example illustrates a few cases:

<?php
class Classy {

const
STAT = 'S' ; // no dollar sign for constants (they are always static)
static $stat = 'Static' ;
public
$publ = 'Public' ;
private
$priv = 'Private' ;
protected
$prot = 'Protected' ;

function
__construct( ){ }

public function
showMe( ){
print
'<br> self::STAT: ' . self::STAT ; // refer to a (static) constant like this
print '<br> self::$stat: ' . self::$stat ; // static variable
print '<br>$this->stat: ' . $this->stat ; // legal, but not what you might think: empty result
print '<br>$this->publ: ' . $this->publ ; // refer to an object variable like this
print '<br>' ;
}
}
$me = new Classy( ) ;
$me->showMe( ) ;

/* Produces this output:
self::STAT: S
self::$stat: Static
$this->stat:
$this->publ: Public
*/
?>
up
25
Hayley Watson
6 years ago
Class names are case-insensitive:
<?php
class Foo{}
class
foo{} //Fatal error.
?>

Any casing can be used to refer to the class
<?php
class bAr{}
$t = new Bar();
$u = new bar();
echo (
$t instanceof $u) ? "true" : "false"; // "true"
echo ($t instanceof BAR) ? "true" : "false"; // "true"
echo is_a($u, 'baR') ? "true" : "false"; // "true"
?>

But the case used when the class was defined is preserved as "canonical":
<?php
echo get_class($t); // "bAr"
?>

And, as always, "case-insensitivity" only applies to ASCII.
<?php
class пасха{}
class
Пасха{} // valid
$p = new ПАСХА(); // Uncaught warning.
?>
up
70
wbcarts at juno dot com
16 years ago
CLASSES and OBJECTS that represent the "Ideal World"

Wouldn't it be great to get the lawn mowed by saying $son->mowLawn()? Assuming the function mowLawn() is defined, and you have a son that doesn't throw errors, the lawn will be mowed.

In the following example; let objects of type Line3D measure their own length in 3-dimensional space. Why should I or PHP have to provide another method from outside this class to calculate length, when the class itself holds all the neccessary data and has the education to make the calculation for itself?

<?php

/*
* Point3D.php
*
* Represents one locaton or position in 3-dimensional space
* using an (x, y, z) coordinate system.
*/
class Point3D
{
public
$x;
public
$y;
public
$z; // the x coordinate of this Point.

/*
* use the x and y variables inherited from Point.php.
*/
public function __construct($xCoord=0, $yCoord=0, $zCoord=0)
{
$this->x = $xCoord;
$this->y = $yCoord;
$this->z = $zCoord;
}

/*
* the (String) representation of this Point as "Point3D(x, y, z)".
*/
public function __toString()
{
return
'Point3D(x=' . $this->x . ', y=' . $this->y . ', z=' . $this->z . ')';
}
}

/*
* Line3D.php
*
* Represents one Line in 3-dimensional space using two Point3D objects.
*/
class Line3D
{
$start;
$end;

public function
__construct($xCoord1=0, $yCoord1=0, $zCoord1=0, $xCoord2=1, $yCoord2=1, $zCoord2=1)
{
$this->start = new Point3D($xCoord1, $yCoord1, $zCoord1);
$this->end = new Point3D($xCoord2, $yCoord2, $zCoord2);
}

/*
* calculate the length of this Line in 3-dimensional space.
*/
public function getLength()
{
return
sqrt(
pow($this->start->x - $this->end->x, 2) +
pow($this->start->y - $this->end->y, 2) +
pow($this->start->z - $this->end->z, 2)
);
}

/*
* The (String) representation of this Line as "Line3D[start, end, length]".
*/
public function __toString()
{
return
'Line3D[start=' . $this->start .
', end=' . $this->end .
', length=' . $this->getLength() . ']';
}
}

/*
* create and display objects of type Line3D.
*/
echo '<p>' . (new Line3D()) . "</p>\n";
echo
'<p>' . (new Line3D(0, 0, 0, 100, 100, 0)) . "</p>\n";
echo
'<p>' . (new Line3D(0, 0, 0, 100, 100, 100)) . "</p>\n";

?>

<-- The results look like this -->

Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=1, y=1, z=1), length=1.73205080757]

Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=0), length=141.421356237]

Line3D[start=Point3D(x=0, y=0, z=0), end=Point3D(x=100, y=100, z=100), length=173.205080757]

My absolute favorite thing about OOP is that "good" objects keep themselves in check. I mean really, it's the exact same thing in reality... like, if you hire a plumber to fix your kitchen sink, wouldn't you expect him to figure out the best plan of attack? Wouldn't he dislike the fact that you want to control the whole job? Wouldn't you expect him to not give you additional problems? And for god's sake, it is too much to ask that he cleans up before he leaves?

I say, design your classes well, so they can do their jobs uninterrupted... who like bad news? And, if your classes and objects are well defined, educated, and have all the necessary data to work on (like the examples above do), you won't have to micro-manage the whole program from outside of the class. In other words... create an object, and LET IT RIP!
up
30
moty66 at gmail dot com
15 years ago
I hope that this will help to understand how to work with static variables inside a class

<?php

class a {

public static
$foo = 'I am foo';
public
$bar = 'I am bar';

public static function
getFoo() { echo self::$foo; }
public static function
setFoo() { self::$foo = 'I am a new foo'; }
public function
getBar() { echo $this->bar; }
}

$ob = new a();
a::getFoo(); // output: I am foo
$ob->getFoo(); // output: I am foo
//a::getBar(); // fatal error: using $this not in object context
$ob->getBar(); // output: I am bar
// If you keep $bar non static this will work
// but if bar was static, then var_dump($this->bar) will output null

// unset($ob);
a::setFoo(); // The same effect as if you called $ob->setFoo(); because $foo is static
$ob = new a(); // This will have no effects on $foo
$ob->getFoo(); // output: I am a new foo

?>

Regards
Motaz Abuthiab
up
5
pawel dot zimnowodzki at gmail dot com
2 years ago
Although there is no null-safe operator for not existed array keys I found workaround for it: ($array['not_existed_key'] ?? null)?->methodName()
up
38
Notes on stdClass
15 years ago
stdClass is the default PHP object. stdClass has no properties, methods or parent. It does not support magic methods, and implements no interfaces.

When you cast a scalar or array as Object, you get an instance of stdClass. You can use stdClass whenever you need a generic object instance.
<?php
// ways of creating stdClass instances
$x = new stdClass;
$y = (object) null; // same as above
$z = (object) 'a'; // creates property 'scalar' = 'a'
$a = (object) array('property1' => 1, 'property2' => 'b');
?>

stdClass is NOT a base class! PHP classes do not automatically inherit from any class. All classes are standalone, unless they explicitly extend another class. PHP differs from many object-oriented languages in this respect.
<?php
// CTest does not derive from stdClass
class CTest {
public
$property1;
}
$t = new CTest;
var_dump($t instanceof stdClass); // false
var_dump(is_subclass_of($t, 'stdClass')); // false
echo get_class($t) . "\n"; // 'CTest'
echo get_parent_class($t) . "\n"; // false (no parent)
?>

You cannot define a class named 'stdClass' in your code. That name is already used by the system. You can define a class named 'Object'.

You could define a class that extends stdClass, but you would get no benefit, as stdClass does nothing.

(tested on PHP 5.2.8)
up
3
johannes dot kingma at gmail dot com
3 years ago
BEWARE!

Like Hayley Watson pointed out class names are not case sensitive.

<?php
class Foo{}
class
foo{} // Fatal error: Cannot declare class foo, because the name is already in use
?>
As well as
<?php
class BAR{}
$bar = new Bar();
echo
get_class($bar);
?>

Is perfectly fine and will return 'BAR'.

This has implications on autoloading classes though. The standard spl_autoload function will strtolower the class name to cope with case in-sensitiveness and thus the class BAR can only be found if the file name is bar.php (or another variety if an extension was registered with spl_autoload_extensions(); ) not BAR.php for a case sensitive file and operating system like linux. Windows file system is case sensitive but the OS is not and there for autoloading BAR.php will work.
up
15
Jeffrey
16 years ago
A PHP Class can be used for several things, but at the most basic level, you'll use classes to "organize and deal with like-minded data". Here's what I mean by "organizing like-minded data". First, start with unorganized data.

<?php
$customer_name
;
$item_name;
$item_price;
$customer_address;
$item_qty;
$item_total;
?>

Now to organize the data into PHP classes:

<?php
class Customer {
$name; // same as $customer_name
$address; // same as $customer_address
}

class
Item {
$name; // same as $item_name
$price; // same as $item_price
$qty; // same as $item_qty
$total; // same as $item_total
}
?>

Now here's what I mean by "dealing" with the data. Note: The data is already organized, so that in itself makes writing new functions extremely easy.

<?php
class Customer {
public
$name, $address; // the data for this class...

// function to deal with user-input / validation
// function to build string for output
// function to write -> database
// function to read <- database
// etc, etc
}

class
Item {
public
$name, $price, $qty, $total; // the data for this class...

// function to calculate total
// function to format numbers
// function to deal with user-input / validation
// function to build string for output
// function to write -> database
// function to read <- database
// etc, etc
}
?>

Imagination that each function you write only calls the bits of data in that class. Some functions may access all the data, while other functions may only access one piece of data. If each function revolves around the data inside, then you have created a good class.
up
3
Anonymous
6 years ago
At first I was also confused by the assignment vs referencing but here's how I was finally able to get my head around it. This is another example which is somewhat similar to one of the comments but can be helpful to those who did not understand the first example. Imagine object instances as rooms where you can store and manipulate your properties and functions. The variable that contains the object simply holds 'a key' to this room and thus access to the object. When you assign this variable to another new variable, what you are doing is you're making a copy of the key and giving it to this new variable. That means these two variable now have access to the same 'room' (object) and can thus get in and manipulate the values. However, when you create a reference, what you doing is you're making the variables SHARE the same key. They both have access to the room. If one of the variable is given a new key, then the key that they are sharing is replaced and they now share a new different key. This does not affect the other variable with a copy of the old key...that variable still has access to the first room
To Top