We have the following chaining:
$obj = new obj();
$obj->setname($params1)->setcolor($params2);
Is there a way to do the same chaining on one line, without creating a dummy function?
P.S: I want to skip the part where the constructor itself is on a new line. I want to construct the object and start the chaining on the same line. Something like this:
$obj = new obj()->setname($params1)->setcolor($params2);
Since PHP 5.4, class member access on instantiation has been added so you can do it like this:
$obj = (new obj())->setname($params1)->setcolor($params2);
In previous versions, like you I hate that you have to instantiate the object on one line and then start using it on another, so I have a global function _i() which looks like this:
function _i($i) { return $i; }
I use it like this:
_i(new Obj)->doThis($param)->doThat($param2);
Some people will find it ugly but PHP lacks language expression power, so it works for me :)
I use static functions of class for it.
class a{
static public function gets($args){
return new self($args);
}
public function do_other(){
}
}
a::gets()->do_other();
Usually there are more then I static method to different usages
Should be possible if you allways return the object itself in the function.
function setname($param) {
// set the name etc..
return $this;
}
You can also use PHP type hinting to make sure only the correct object is used as an argument
function instance(sdtClass $instance) { return $instance }
or as the static method using the class name
class CustomClass{
static public function gets(CustomClass $obj){
return $obj;
}
}
You can also use this technique from Singleton pattern (without using singleton pattern):
<?php
class test
{
public function __construct() {
}
public static function getInstance() {
return new test();
}
public function chain() {
echo 'ok';
}
}
// outputs 'ok'
$test = test::getInstance()->chain();
Sure is. Simplt return this at the end of each function, to return the object so your next chained function can use it.
<?php
class A
{
public __constructor()
{ .... }
public function B($params)
{
//Processing
return this;
}
public function C($params)
{
//Processing
return this;
}
public function D($params)
{
//Processing
}
}
$O = new A();
$O->B($params)->C($params)->D($params); //Will work because B and C return this
$O->B($params)->D($params)->C($params); //WILL NOT work because D doesn't return this
?>
Related
Say I have the following class:
class Test
{
private static $instance = false;
public static function test()
{
if(!self::$instance)
{
self::$instance = new self();
}
return self::$instance;
}
public function test1()
{
//...
}
public function test2()
{
//...
}
}
And I go about calling functions by chaining them like so:
$data = Test::test(...)->test1(...)->test2(...);
At the moment for the above method chain to work I have to keep returning $instance and I really would like it if I could return something from test2() to then be assigned to $data but I am not sure how to do this as I have to keep returning $instance in order for mt method chain to work?
If you want to chain methods, you need to return the current instance from any method which has another call chained on after it. However, it's not necessary for the last call in the chain to do so. In this case that means you're free to return whatever you like from test2()
Just bear in mind, if you return something different from test2() you'll never be able to chain anything onto it in future. For example, $data = Test::test(...)->test2(...)->test1(...); wouldn't work.
Protip: it's worth documenting your code with some comments explaining which ones are and aren't chainable so you don't forget in future.
Generally speaking if you are doing method chaining, and I'm assuming each of the tests above return your data model in a different state, and I assume that you want some data from the model itself. I would do the following:
class Test
{
private static $model;
public function test1() {
//do something to model
return $this;
}
public function test1() {
//do something to model
return $this;
}
public function finish_process() {
//process results
return $this.model;
}
}
so essentially i can do the following now:
$results = Test::test1()->finish_process();
and
$results = Test::test1()->test2()->finish_process();
You can pass the $data by its reference and you can change it or assign any data into it.
// inside class
public function test2( &$data ) {
$data = 'it will work';
}
// outside class
$data = '';
Test::test(...)->test1(...)->test2($data);
check this http://php.net/manual/en/language.references.pass.php
return $this inside test1() and test2() methods.
The output returned by the function when called from constructor is an object and not the array which its supposed to display. Below is an idea of my code. Please note that this is not my actual code. I'm just trying to give a basic idea of the functionality.
class Foo(){
public function __construct($arg)
{
$this->A($arg);
}
public function A($arg)
{
$data = 2*$arg;
return $data
}
}
$obj = new Foo(10);
echo $obj;
I have been researching and found that constructor will return the instance of the object and not a value. If this is true, is there any workaround? I know I can use init() of Zend but I'm not too familiar with it. Any suggestions? Thank you for all your help in advance.
create a property of the class
class Foo(){
public var $myvar;
public function __construct($arg)
{
$this->A($arg);
}
public function A($arg)
{
$this->myvar = 2*$arg;
}
}
$obj = new Foo(10);
echo $this->myvar;
the problem you are having is $obj is the object created by your class. when you return from the constructor it does nothing. And echo'ing your class object isn't gong to do anything either. You can also use ..
public function A($arg)
{
$data = 2*$arg;
echo $data;
}
if you want to just display it right there. Then using
$obj = new Foo(10)
will be all you need to use to display the value.
Have a look here for more info on constructors. Again, constructors do not return anything, they are for instancing the object only.
http://php.net/manual/en/language.oop5.decon.php
While reading this: http://propelorm.org/ I noticed that they are using -> sign on a static object and using several different methods of it as a "one-liner".
Or does the static object return an instance which from the methods are being called from?
What ever is the case I would like to read more about this. What is this called and does it really work with static objects?
I noticed that they are using -> sign on a static object
By static object you mean to say static method and that the code you are referring to is this:
classBookQuery::create()->findPK(123);
They are not using -> on a static method. They are using -> on the object returned by the static method.
You can try it yourself:
class AClass
{
public static function aMethod()
{
return new BClass();
}
}
class BClass
{
public function bMethod($int)
{
echo $int;
}
}
AClass::aMethod()->bMethod(123); // output: 123
As others have mentioned in the comments, the static function BookQuery::create() just returns another object.
The "arrow" operates on the returned object.
Example:
class Car {
public function beep() {
echo 'BEEP';
}
}
class CarProvider {
public static function get() {
return new Car();
}
}
// outputs 'BEEP';
CarProvider::get()->beep();
// the same as this
$car = CarProvider::get();
$car->beep();
This is oftentimes know as method chaining. The static method call is returning an instantiated object against which another method is called. This sort of construct is often achieve like this:
class myobject_factory {
public static function get_object () {
return new myobject;
}
}
class myobject {
protected $some_property;
public function set_some_property($value) {
$this->some_property = $value;
return $this;
}
public function get_some_propert() {
return $this->some_property;
}
}
$property = myobject_factory::get_object()->set_some_property('foobar')->get_some_property();
This is obviously a trivial example, but you can see how chaining is enabled because the setter on myobject returns $this.
How this stuff works?
$object->foo1()->foo2()->foo3();
I'm working in Magento php framework. In Magento functions are called as sequence.But, I don't understand how it works.Can anyone explain.
$object->foo1()->foo2()->foo3();
First, PHP will get a pointer to the foo1 method from the $object variable. It calls this method, which then returns another object. This second object (we shall call it $object2) has a method foo2(), which is also called. foo2() returns another object ($object3), which has a method foo3(), which returns whatever it likes.
In some cases, $object, $object2 and $object3 are just pointers to the same object. This means that you can keep calling methods on the same class in a nice sequence.
You can achieve this quite easily:
class Foo
{
public function nicely()
{
return $this;
}
public function formatted()
{
return $this;
}
public function chained()
{
return $this;
}
public function calls()
{
return $this;
}
}
$foo = new Foo();
$foo->nicely()->formatted()->chained()->calls();
When the methods in the class are returning values, they are returning objects of themselves. This allows you to keep calling other methods in that class in a sequence like you posted.
class myClassA {
public $str = NULL;
public function setStr( $value ){
$this->str .= $value;
return $this; // This is the key to sequencing
}
}
$myclass = new MyClassA();
$myclass->setStr("H")->setStr("E");
// If you echoed the $str variable in myClassA, you would get
// "HE"
How to call function of just created object without temporary variable?
Code
(new \Foo())->woof();
is not valid in php.
What is right?
$obj = new Foo();
$obj->woof();
If you have got PHP 5.4 or later, you can make use of a new feature:
Class member access on instantiation has been added, e.g. (new Foo)->bar().
You can do it like this, but it's not very clean:
<?php
class Foo
{
public function __construct()
{
}
public function bar()
{
echo 'hello!';
}
}
function Foo()
{
return new Foo();
}
Foo()->bar();
You could also change it to something like
function newClass($className)
{
return new $className();
}
newClass('Foo')->bar();
But the static method way is preferred.
It can work if the object has singleton
Foo::getInstance()->woof();
BTW: it doesn't have to be even singleton but also static method which returns the instance
class Foo {
public static function & getInstance()
{
return new self();
}
}