I dont know how to explain this question so maybe the tile is not matched.
Class a {
function b{
return $this;
}
function c{
return $this;
}
}
If I have class structure like this I can do
$a = new a();
$a->b()->c();
I want to know how can I know the function is not continued like $a->b();, then I return $retuslt instead of $this.
Class a {
function b{
//if not continued
return $result;
//if continued
return $this;
}
function c{
return $this;
}
}
Is this possible? thank you very much!!
It is not possible. You will not know inside the method what is being done with the return. You could however pass a return value in, for example:
Class a {
function b(&$return){
// do something
$return = 'some value';
return $this;
}
function c(){
return $this;
}
}
$a = new a();
$a->b($returnFromB)->c();
echo $returnFromB; // 'some value'
Related
I try to make an function like this below how can do that, any example?
$myClass->first()->callSecond();
You just need to return object all the time. It's called fluent interface. It can be self or other object.
<php
class A
{
public function first()
{
// Do something
return $this;
}
public function callSecond()
{
// Do somewthing else
return $this;
}
}
$a = (new A())->first()->callSecond();
<?php
class OtherClass{
public function callSecond(){
echo 'Second Called';
}
}
class MyClass{
public function first(){
return new OtherClass();
}
}
$myClass = new MyClass();
$myClass->first()->callSecond();
?>
Maybe I'm wrong to expressed it in the title, but I just do not understand how in the class like this.
<?php
class sample{
public $data = [];
public function pushIndex($index){
array_push($this->data, $index);
}
public function pushValue($value){
array_push($this->data["index"], $value);
// Some magic
}
public function forIndex($index){
return $this->data[$index];
// Some magic
}
}
To realize scheme like in Symfony, where will be spaghetti like this
<?php
$a = new sample;
$a->pushIndex("index")->pushValue("value");
$a->forIndex("index2")->pushValue("value2");
Maybe someone knows how to do it?
What you're talking about is called Fluent interface.
Returns the current object by using $this.
public function pushIndex($index){
array_push($this->a,$index);
return $this;
}
But what you want is to do something like this:
class sample
{
protected $a = [];
protected $currentIndex = null;
public function pushIndex($index)
{
$this->currentIndex = $index;
return $this;
}
public function pushValue($value)
{
if ($this->currentIndex === null) {
throw new LogicException('You need to call "pushIndex" or "forIndex" first.');
}
$this->a[$this->currentIndex] = $value;
return $this;
}
public function forIndex($index)
{
if (!isset($this->a[$index])) {
throw new RuntimeException(sprintf('Index "%s" doesn\'t exists', $index));
}
$this->currentIndex = $index;
return $this;
}
public function getArray()
{
return $this->a;
}
}
$a = new sample;
$a->pushIndex("index")->pushValue("value");
$a->forIndex("index2")->pushValue("value2"); // exception?
var_dump($a->getArray());
But what you want is pretty unclear.
I think what you're trying to achieve is something like this:
class sample{
public $a = [];
public $index = null;
public function pushIndex($index){
$this->index = $index;
$this->a[$index] = null;
return $this;
}
public function pushValue($value){
$this->a[$this->index] = $value;
return $this;
}
public function forIndex($index){
$this->index = $index;
return $this;
}
}
$a = new sample;
$a->pushIndex("index")->pushValue("value");
$a->forIndex("index2")->pushValue("value2");
echo "<pre>";
var_dump($a);
echo "</pre>";
This is called "method chaining". By returning a reference to the called object, you're able to perform further methods on the object, essentially "chaining" the methods.
I've had to adjust your code a little to get it the work I believe the way you want it to. It should provide a working example to help you understand method chaining.
I have two classes, ClassA, ClassB. In ClassA I have Method which call method from ClassB.
For Example:
function functionInClassB($state)
{
if ($state) {
return true;
} else {
return false;
}
}
function functionInClassA ()
{
if (functionInClassB(1)) {
return "Anything";
}
}
Now, I want test functionInClassB with PhpUnit and I dont want functionInClassB ran. I want return value which I want.
Sorry for my English, please help!!!
Old question, but I think you're referring to stubbing / mocking.
How easy /sensible it is depends. If you want to call functionInClassB statically then you're out of luck; static stuff doesn't work well with testing. But if you're calling the method on an instance then the following should work:
class A {
protected $instanceOfB;
public function functionInClassA(B $injectedInstanceOfB) {
if ($injectedInstanceOfB->functionInClassB(1)) return 'anything';
}
}
class B {
public function functionInClassB($state) {
if ($state) {
return true;
} else {
return false;
}
}
}
class yourPHPUnitTest extends \PHPUnit\Framework\TestCase {
public function testA() {
$stubOfB = $this->createStub(\B::class);
// Optionally...
$stubOfB->method('functionInClassB')->willReturn('something');
// Thing you want to test
$a = new A();
$result = $a->functionInClassA($stubOfB);
$this->assertEqual('something', $result);
}
}
I'm trying to use call_user_func to call a method from another method of the same object, e.g.
class MyClass
{
public function __construct()
{
$this->foo('bar');
}
public function foo($method)
{
return call_user_func(array($this, $method), 'Hello World');
}
public function bar($message)
{
echo $message;
}
}
new MyClass; Should return 'Hello World'...
Does anyone know the correct way to achieve this?
Many thanks!
The code you posted should work just fine. An alternative would be to use "variable functions" like this:
public function foo($method)
{
//safety first - you might not need this if the $method
//parameter is tightly controlled....
if (method_exists($this, $method))
{
return $this->$method('Hello World');
}
else
{
//oh dear - handle this situation in whatever way
//is appropriate
return null;
}
}
This works for me:
<?php
class MyClass
{
public function __construct()
{
$this->foo('bar');
}
public function foo($method)
{
return call_user_func(array($this, $method), 'Hello World');
}
public function bar($message)
{
echo $message;
}
}
$mc = new MyClass();
?>
This gets printed out:
wraith:Downloads mwilliamson$ php userfunc_test.php
Hello World
new MyClass; Should return 'Hello World'...
A constructor does not return anything.
I have been browsing some php source code and need to know how the following class and sub methods use works:
<?php
$me = new Person;
$me->name("Franky")->surname("Chanyau")->phone("+22", "456 789");
?>
I have pretty solid knowledge of OOP so I don't want a 101. I just need to know how to make the above code possible.
Method chaining is possible, by
return $this;
at the end of the method.
Explained here:
phpandstuff: Method Chaining Plus Magic Setters
These methods usually set an instance variable and then just return $this.
public function phone($param) {
$this->phone = $param;
return $this;
}
methods name() surname() and phone() return an instance of Person. you can accomplish this by
return $this;
most probably these methods look like this:
public function name($name) {
$this->name = $name;
return $this;
}
like some others said, its a fluid interface http://en.wikipedia.org/wiki/Fluent_interface#PHP the Basic Idea is that a methof of a class always returns the object itself
class Car {
private $speed;
private $color;
private $doors;
public function setSpeed($speed){
$this->speed = $speed;
return $this;
}
public function setColor($color) {
$this->color = $color;
return $this;
}
public function setDoors($doors) {
$this->doors = $doors;
return $this;
}
}
// Fluent interface
$myCar = new Car();
$myCar->setSpeed(100)->setColor('blue')->setDoors(5);
(via wiki)
It's called method chaining. Basically each class function returns the object itself ($this) so that the user can call more functions on the returned object.
public function name() {
//other stuff...
return $this;
}
http://www.talkphp.com/advanced-php-programming/1163-php5-method-chaining.html
http://www.electrictoolbox.com/php-method-chaining
The idea is if we return $this then we can chain the object method calls together. Here's the solution:
<?php
class Person
{
private $strName;
private $strSurname;
private $ArrPhone = array();
public function name($strName)
{
$this->strName = $strName;
return $this; // returns $this i.e Person
}
public function surname($strSurname)
{
$this->strSurname = $strSurname;
return $this; // returns $this i.e Person
}
public function phone()
{ $this->ArrPhone = func_get_args(); //get arguments as array
return $this; // returns $this i.e Person
}
public function __toString()
{
return $this->strName." ".$this->strSurname.", ".implode(" ",$this->ArrPhone);
}
}
$me = new Person;
echo $me->name("Franky")->surname("Chanyau")->phone("+22", "456 789");
?>
Correct answers, but to make the code work you should write:
$me = new Person();
instead of
$me = new Person;