Creating Anonymous Objects in PHP

Creating anonymous objects in php

It has been some years, but I think I need to keep the information up to date!

Since PHP 7 it has been possible to create anonymous classes, so you're able to do things like this:

<?php

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

var_dump($child instanceof Foo); // true

?>

You can read more about this in the manual

But I don't know how similar it is implemented to JavaScript, so there may be a few differences between anonymous classes in JavaScript and PHP.

How to call a method of anonymous object php?

You created a stdClass object, not an anonymous one:

$obj = new class () {
public function Greeting(string $d)
{
return "Hello $d";
}
};
echo $greetings = $obj->Greeting("world!");

output:

Hello world!


What's wrong?

Nothing, let's just ask, what's behind or happening here?

The stdClass is used for "empty" objects in PHP or when casting an array to an object ($obj = (object) ['hello' => 'world']).

By default it has no properties (like in $obj = new stdClass;) and also no methods. It is empty in terms of both of these.

Properties can be added dynamically to an stdClass object - but not functions as class methods have to be declared in PHP before instantiating the object.

So the function in your case is a property (PHP has two bags here: one for properties and one for functions) and not a new method dynamically added to it (class MyClass { function method() {...} }).

Let's compare with the original example and provoke the error again:

$obj = new stdClass();
$obj->Greeting = function (string $d) {
return "Hello $d";
};
$greetings = $obj->Greeting("world!");
PHP Fatal error:  Uncaught Error: Call to undefined method stdClass::Greeting()

However:

echo $greetings = ($obj->Greeting)("world!");
# #

works, the output:

Hello world!

because PHP is now guided to "call" the ($obj->Greeting) property indirectly, so not looking for the stdClass::Greeting method first.

Normally you don't want that indirection, therefore the suggestion to use the anonymous class instead.

Creating anonymous objects in php, which extends something

What you're trying to do is impossibru!. Can't be done, no way. Forget about it. End of.

An anonymous object is indeed an instance of the stdClass, but you can't in-line-extend it. What you can do, however, is to create an instance of the base class you want the stdClass to extend from, and overload it (which is a bad idea IMO, but it's poissible):

$anonObj = new BaseClass();//create "parent" instance
$anonObj->foo = function()
{
echo 'foo';
};
$anonObj->bar = function($bar)
{
echo $bar;
};

The reason why I consider this "overloading" to be a bad idea is because of:

  • Overloading is just a silly term, most of the time overloading, in OOP, means something else entirely
  • Predeclared properties are quick to find, properties added to an instance are not. details here
  • Typo's make your code extremely vulnerable to errors, and neigh on impossible to debug
  • You can type-hint for a class, which tells you certain pre-defined methods and properties will be available. If you add properties/methods as you go, you loose this edge

Bottom line: if you want an object to extend your BaseClass, and have 2 extra methods: just write the bloody class, don't try to extend generic objects from custom made ones.

Create and use anonymous object in PHP

You can't do what you want exactly, but there are workarounds without making things static.

You can make a function that returns the new object

function tst( $s ) {
return new tst( $s );
}

echo tst( "again" )->show();

create anonymous object in php

You are trying to access a property as an array element. You need to extend ArrayObject. http://php.net/manual/en/class.arrayobject.php to do this. Otherwise dont mix objects and arrays.

php create object without class

you can always use new stdClass(). Example code:

   $object = new stdClass();
$object->property = 'Here we go';

var_dump($object);
/*
outputs:

object(stdClass)#2 (1) {
["property"]=>
string(10) "Here we go"
}
*/

Also as of PHP 5.4 you can get same output with:

$object = (object) ['property' => 'Here we go'];

Std class vs Anonymous class in PHP7+

It seems even in PHP 8 if you cast an array to object you still get stdClass:

$test = (object) [];
var_dump($test); //output: object(stdClass)#1 (0) {}

$test = new class{};
var_dump($test); //output: object(class@anonymous)#1 (0) {}

So it is safe to assume it is still the generic class in php 7 and 8.

One difference is when you want to declare some method or even the __construct method for the object:

$object = new class('value') {

private $val;

public function __construct($val){
$this->val = $val;
}

public function getVal(){
return $this->val;
}
};

Above code is obviously more readable regards to object orianted concepts like encapsulation.

But if you need to create an empty object I would suggest to use stdClass ( or (object)[] to type less) over anonymous class since it was intended to derive fully modelled objects.

If you want to have some public properties in the object, still (object)[] would be a more readable way to go:

$object = (object) [
"firstName" => "John",
"lastName" => "Doe"
];

$object = new class{};
$object->firstName = "John";
$object->lastName = "Doe";

If you need some methods for the object, anonymous class would be a better option.

If you want to have private properties, again anonymous class is the way to go.

If you want your object to implement some interface then definitely go with anonymous class:

interface Logger {
public function log(string $msg);
}

class Application {
private $logger;

public function getLogger(): Logger {
return $this->logger;
}

public function setLogger(Logger $logger) {
$this->logger = $logger;
}
}

$app = new Application;
$app->setLogger(new class implements Logger {
public function log(string $msg) {
echo $msg;
}
});

If you want your object to extend some class then again anonymous class is the way to go:

$object = new class extends Thread {
public function run() {
/** ... **/
}
};

$object->start();

Why PHP asks to pass arguments to the anonymous class?

At the very end, you are instantiating a class, so, the constructor is been fired. Anonymous classes, as it's mentioned in the documentation, are useful for creating single and uniques objects, not for creating a template.

The syntax for passing params through is:

$trainerEngineClass = new class($user, $trainer) extends \App\MemoryBoost\TrainerEngine {
public function __construct($user, $trainer) {
parent::__construct($user, $trainer);
}

// Overriden abstract methods
};

Accessing outer variable in PHP 7 anonymous class

another solution could be

$outer = 'something';

$instance = new class($outer) {

private $outer;

public function __construct($outer) {
$this->outer = $outer
}

public function testing() {
var_dump($this->outer);
}
};


Related Topics



Leave a reply



Submit