147

What I would like to do is something like this:

$method_result = new Obj()->method();

Instead of having to do:

$obj = new Obj();
$method_result = $obj->method();

The result doesn't actually matter to me in my specific case. But, is there a way to do this?

weotch
  • 5,788
  • 6
  • 35
  • 42
  • 4
    btw, if you are not using 5.4 (which you probably aren't), you can define a helper function which just returns an object to chain stuff ... function with($obj) { return $obj; } (picked the trick up from laravel :P) .. then you can do with(new Obj)->method() – kapv89 May 27 '12 at 15:28
  • BTW, if you find yourself doing this often, its worth considering whether `my_method` should instead be declared `static`. – ToolmakerSteve Mar 10 '20 at 02:31

10 Answers10

195

The feature you have asked for is available from PHP 5.4. Here is the list of new features in PHP 5.4:

https://php-legacy-docs.zend.com/manual/php5/en/migration54.new-features

And the relevant part from the new features list:

Class member access on instantiation has been added, e.g. (new Foo)->bar().

Don't Panic
  • 41,125
  • 10
  • 61
  • 80
Delian Krustev
  • 2,826
  • 1
  • 19
  • 15
  • 12
    Note that this also means you can do `(new Foo)->property` if you wanted to. – dave1010 Jun 07 '12 at 13:14
  • 2
    Note that you cannot assign properties in this way yet. (new Foo)->property = 'property'; – CMCDragonkai Mar 29 '14 at 07:01
  • 7
    @CMCDragonkai logically that makes sense; the object only exists for the duration of the statement `(new Foo)->property` - the value you are storing has nowhere to go because the object will no longer exist after that as it's not stored anywhere. – thomasrutter Aug 03 '15 at 01:14
  • 1
    @CMCDragonkai You can assign properties this way by calling the corresponding **setters**, all you need to do is to add `return $this` to your setters. This will also allow you to chain setters. – iloo Jul 05 '17 at 15:47
  • I have a question. Is there any benefit to declaring the object on a separate line and saving it to a variable, other than being able to reuse the object? – Tyler Swartzenburg Jul 11 '17 at 16:19
  • @TylerSwartzenburg If you want to use your object, then yes, you'll need an actual reference to it. Why even instantiate a class if you don't want to use it? – Félix Adriyel Gagnon-Grenier Aug 16 '18 at 18:26
  • Thank you for this. New to OOP in PHP and this helps clean up my code a lot. – Matt. Dec 22 '18 at 15:45
  • @Matt: If you find yourself doing this often, its worth considering whether `my_method` should instead be declared `static`. – ToolmakerSteve Mar 10 '20 at 02:31
40

You cannot do what you are asking ; but you can "cheat", using the fact that, in PHP, you can have a function that has the same name as a class ; those names won't conflict.

So, if you declared a class like this :

class Test {
    public function __construct($param) {
        $this->_var = $param;
    }
    public function myMethod() {
        return $this->_var * 2;
    }
    protected $_var;
}

You can then declare a function that returns an instance of that class -- and has exactly the same name as the class :

function Test($param) {
    return new Test($param);
}

And now, it becomes possible to use a one-liner, like you asked -- only thing is you are calling the function, thus not using new :

$a = Test(10)->myMethod();
var_dump($a);

And it works : here, I'm getting :

int 20

as output.


And, better, you can put some phpdoc on your function :

/**
 * @return Test
 */
function Test($param) {
    return new Test($param);
}

This way, you'll even have hints in your IDE -- at least, with Eclipse PDT 2.x ; see the screeshot :



Edit 2010-11-30 : Just for information, a new RFC has been submitted, a few days ago, that proposes to add this feature to one of the future versions of PHP.

See : Request for Comments: Instance and method call/property access

So, maybe doing things like these will be possible in PHP 5.4 or another future version :

(new foo())->bar()
(new $foo())->bar
(new $bar->y)->x
(new foo)[0]
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Pascal MARTIN
  • 395,085
  • 80
  • 655
  • 663
19

How about:

$obj = new Obj(); $method_result = $obj->method(); // ?

:P

Madhawa Priyashantha
  • 9,633
  • 7
  • 33
  • 60
Jeff
  • 742
  • 10
  • 16
19

You can do it more universally by defining an identity function:

function identity($x) {
    return $x;
}

identity(new Obj)->method();

That way you don't need to define a function for each class.

Tom Pažourek
  • 9,582
  • 8
  • 66
  • 107
16

No, this is not possible.
You need to assign the instance to a variable before you can call any of it's methods.

If you really wan't to do this you could use a factory as ropstah suggests:

class ObjFactory{
  public static function newObj(){
      return new Obj();
  }
}
ObjFactory::newObj()->method();
Richard de Wit
  • 7,102
  • 7
  • 44
  • 54
Pim Jager
  • 31,965
  • 17
  • 72
  • 98
  • 4
    Pim's answer is correct. Alternatively you could use static functions if you do not wish to create an instance of the object – Mark Sep 09 '09 at 22:42
  • using this, we are force to use `public static function` instead of `public function`. Is recommended to use static? – KD.S.T. Jun 06 '18 at 09:04
8

Simply we can do this

$method_result = (new Obj())->method();
vimuth
  • 5,064
  • 33
  • 79
  • 116
6

You could use a static factory method to produce the object:

ObjectFactory::NewObj()->method();
Ropstah
  • 17,538
  • 24
  • 120
  • 194
3

I, too, was looking for a one-liner to accomplish this as part of a single expression for converting dates from one format to another. I like doing this in a single line of code because it is a single logical operation. So, this is a little cryptic, but it lets you instantiate and use a date object within a single line:

$newDateString = ($d = new DateTime('2011-08-30') ? $d->format('F d, Y') : '');

Another way to one-line the conversion of date strings from one format to another is to use a helper function to manage the OO parts of the code:

function convertDate($oldDateString,$newDateFormatString) {
    $d = new DateTime($oldDateString);
    return $d->format($newDateFormatString);
}

$myNewDate = convertDate($myOldDate,'F d, Y');

I think the object oriented approach is cool and necessary, but it can sometimes be tedious, requiring too many steps to accomplish simple operations.

1

I see this is quite old as questions go but here is something I think should be mentioned:

The special class method called "__call()" can be used to create new items inside of a class. You use it like this:

<?php
class test
{

function __call($func,$args)
{
    echo "I am here - $func\n";
}

}

    $a = new test();
    $a->new( "My new class" );
?>

Output should be:

I am here - new

Thus, you can fool PHP into making a "new" command inside of your top level class (or any class really) and put your include command in to the __call() function to include the class that you have asked for. Of course, you would probably want to test $func to make sure it is a "new" command that was sent to the __call() command and (of course) you could have other commands also because of how __call() works.

Mark Manning
  • 1,427
  • 12
  • 14
0

Additionally, you can also clone an object and call a method on the same line too:

(clone $image)->save('thumbnail.jpg');

I actually struggled find it out. I thought it could help some people.

Imtiaz
  • 2,484
  • 2
  • 26
  • 32