PHPでの匿名オブジェクトの作成


141

ご存知のように、JavaScriptで匿名オブジェクトを作成するのは、次のコードのように簡単です。

var object = { 
    p : "value", 
    p1 : [ "john", "johnny" ]
};

alert(object.p1[1]);

出力:

an alert is raised with value "johnny"

これと同じ手法をPHPに適用できますか?PHPで匿名オブジェクトを作成できますか?


1
注:これは古い質問なので、受け入れられた回答は古くなっています。要求されているこの機能は、PHP 7に追加されました。@ Rizier123による以下の回答を参照してください。
Simba

@Simba-指摘してくれてありがとう。StackOverflowのこのページの回答を投稿して、今後の訪問者を支援しますか?
Sujit Agarwal

1
私はする必要はありません。この情報には既に回答があります(下記の@ Rizier123を参照)。
Simba

回答:


40

もう何年か経ちますが、情報を最新の状態に保つ必要があると思います。

PHP 7以降、匿名クラスを作成できるようになったため、次のようなことができます。

<?php

    class Foo {}
    $child = new class extends Foo {};

    var_dump($child instanceof Foo); // true

?>

これについてはマニュアルでもっと読むことができます

しかし、JavaScriptにどのように実装されるかはわかりません。そのため、JavaScriptとPHPの匿名クラスにはいくつかの違いがあるかもしれません。


@risyasinありがとう、回答を更新し、それに手動リンクを入れました。
Rizier123 2015

php7の最新の変更に対応するために、回答に正しいマークを付けます。ありがとう@ Rizier123
Sujit Agarwal

3
これは興味深いですが、OPがクラスを作成せずにさまざまなメンバーでオブジェクトを初期化する便利な方法を求めていたため、実際には問題には対処していません。PHPの匿名クラスを使用してそれを行うことができるかどうかはわかりませんが、できる場合はその方法を説明していません。
amh15、18年

228

オブジェクトについて話すとき、「匿名」は正しい用語ではありません。「匿名型のオブジェクト、これはPHPには当てはまりません。

PHPのすべてのオブジェクトにはクラスがあります。「デフォルト」クラスはstdClassであり、この方法でオブジェクトを作成できます。

$obj = new stdClass;
$obj->aProperty = 'value';

さらに便利な構文として、配列をオブジェクトキャストすることもできます。

$obj = (object)array('aProperty' => 'value');
print_r($obj);

ただし、配列をオブジェクトにキャストすると、有効なPHP変数名ではない配列キーに対して「興味深い」結果が得られる可能性があることに注意してください。たとえば、ここでは、キーが数字で始まる場合にどうなるかを示す私の答えを示します。


1
複数の値の配列もプッシュできますか?
Sujit Agarwal

2
@CodingFreak:あなたは、することができますが:アレイがサブアレイが含まれており、同様にオブジェクトとしてそれらをしたい場合は、明示的にオブジェクトに一人一人をキャストする必要があります。
Jon

21

はい、可能です!この単純なPHP匿名オブジェクトクラスを使用します。使い方:

// define by passing in constructor
$anonim_obj = new AnObj(array(
    "foo" => function() { echo "foo"; }, 
    "bar" => function($bar) { echo $bar; } 
));

$anonim_obj->foo(); // prints "foo"
$anonim_obj->bar("hello, world"); // prints "hello, world"

// define at runtime
$anonim_obj->zoo = function() { echo "zoo"; };
$anonim_obj->zoo(); // prints "zoo"

// mimic self 
$anonim_obj->prop = "abc";
$anonim_obj->propMethod = function() use($anonim_obj) {
    echo $anonim_obj->prop; 
};
$anonim_obj->propMethod(); // prints "abc"

もちろん、このオブジェクトはAnObjクラスのインスタンスであるため、実際には匿名ではありませんが、JavaScriptのように、その場でメソッドを定義できます。


create_functionを使用して、無名関数をエミュレートできます。
Mihailoff 2013

私は彼がstdClassオブジェクトをいくつかの値で初期化するきちんとした方法を望んでいたと思います。あなたのアプローチでそれを行うことができますか?
amh15

18

最近まで、これはオブジェクトをその場で作成する方法でした。

$someObj = json_decode("{}");

次に:

$someObj->someProperty = someValue;

しかし、今私は行きます:

$someObj = (object)[];

次に、以前のように:

$someObj->someProperty = someValue;

もちろん、すでにプロパティと値がわかっている場合は、前述のように内部に設定できます。

$someObj = (object)['prop1' => 'value1','prop2' => 'value2'];

注意:これが動作するPHPのバージョンがわからないので、注意する必要があります。しかし、私は最初のアプローチ(構築時に設定するプロパティがない場合も短い)はjson_encode / json_decodeを持つすべてのバージョンで機能するはずだと思います


1
$ someObj = new \ stdClass()とはどう違うのですか?
JamesNZ 2018年

9

配列をオブジェクトに変換します(ただし、これはサブ子に対して再帰的ではありません)。

$obj = (object)  ['myProp' => 'myVal'];

7

JavaScriptを模倣したい場合は、クラスを作成してObject、同じ動作を得ることができます。もちろん、これはもはや匿名ではありませんが、機能します。

<?php 
class Object { 
    function __construct( ) { 
        $n = func_num_args( ) ; 
        for ( $i = 0 ; $i < $n ; $i += 2 ) { 
            $this->{func_get_arg($i)} = func_get_arg($i + 1) ; 
        } 
    } 
} 

$o = new Object( 
    'aProperty', 'value', 
    'anotherProperty', array('element 1', 'element 2')) ; 
echo $o->anotherProperty[1];
?>

要素2が出力されます。これは、PHP:Classes and Objectsに関するコメントから盗まれまし


3

匿名クラスのサポートはPHP 7.0以降で利用可能であり、質問で提供されているJavaScriptの例に最も近いものです。

<?php
$object = new class {
    var $p = "value";
    var $p1 = ["john", "johnny"];
};

echo $object->p1[1];

プロパティの可視性宣言は省略できません(私はvarそれがpublic。より短いので使用しただけです)。

JavaScriptと同様に、クラスのメソッドも定義できます。

<?php
$object = new class {
    var $p = "value";
    var $p1 = ["john", "johnny"];
    function foo() {return $this->p;}
};

echo $object->foo();

1

PHPドキュメントから、さらにいくつかの例:

<?php

$obj1 = new \stdClass; // Instantiate stdClass object
$obj2 = new class{}; // Instantiate anonymous class
$obj3 = (object)[]; // Cast empty array to object

var_dump($obj1); // object(stdClass)#1 (0) {}
var_dump($obj2); // object(class@anonymous)#2 (0) {}
var_dump($obj3); // object(stdClass)#3 (0) {}

?>

$ obj1と$ obj3は同じタイプですが、$ obj1!== $ obj3です。また、3つすべてがjson_encode()を単純なJSオブジェクト{}に変換します。

<?php

echo json_encode([
    new \stdClass,
    new class{},
    (object)[],
]);

?>

出力:

[{},{},{}]

https://www.php.net/manual/en/language.types.object.php


0

プロパティに値を設定していないときに、未定義のプロパティの警告を受け取らずに、動的プロパティを持つオブジェクト(JavaScriptなど)を作成する場合

class stdClass {

public function __construct(array $arguments = array()) {
    if (!empty($arguments)) {
        foreach ($arguments as $property => $argument) {
            if(is_numeric($property)):
                $this->{$argument} = null;
            else:
                $this->{$property} = $argument;
            endif;
        }
    }
}

public function __call($method, $arguments) {
    $arguments = array_merge(array("stdObject" => $this), $arguments); // Note: method argument 0 will always referred to the main class ($this).
    if (isset($this->{$method}) && is_callable($this->{$method})) {
        return call_user_func_array($this->{$method}, $arguments);
    } else {
        throw new Exception("Fatal error: Call to undefined method stdObject::{$method}()");
    }
}

public function __get($name){
    if(property_exists($this, $name)):
        return $this->{$name};
    else:
        return $this->{$name} = null;
    endif;
}

public function __set($name, $value) {
    $this->{$name} = $value;
}

}

$obj1 = new stdClass(['property1','property2'=>'value']); //assign default property
echo $obj1->property1;//null
echo $obj1->property2;//value

$obj2 = new stdClass();//without properties set
echo $obj2->property1;//null

0

これと同じテクニックをPHPの場合にも適用できますか?

いいえ-JavaScriptはプロトタイプ/オブジェクトの直接宣言を使用するため-PHP(および他の多くのオブジェクト指向言語)では、オブジェクトはクラスからのみ作成できます。

だから問題は-匿名クラスを作成できますか?

もう一度答えはノーです-それを参照することができずにクラスをどのようにインスタンス化しますか?


匿名クラスのインスタンスを作成するのに名前は必要ありません。Java:Object var = new Object() { ... };-C ++:class { ... } var;
TheOperator 2017年

1
PHPで匿名クラスを作成できるようになりました。
ビクター


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.