How can I do multiple levels of de-referencing? For instance, in C#, we can keep appending a '.' to access the next objects properties: string s, s.ToString(), s.ToString().ToUpper(). With PHP, I get to around $this->someobject, but $this->someobject->somethingelse does not appear to work.
Any ideas?
Assuming you're using PHP5+, and $this->someobject returns an object with a property called somethingelse; it should work.
Similarly, this also works
class Example
{
public function foo()
{
echo 'Hello';
return $this; // returning an object (self)
}
public function bar()
{
echo ' World';
return $this;
}
}
$example = new Example;
$example->foo()->bar(); // Hello World
$example->foo()->foo()->foo()->bar()->foo(); // HelloHelloHello WorldHello
Edit:
Just as a further note, you don't have to return self. Any object will suffice.
class Example1
{
public function __construct(Example2 $example2)
{
$this->example2 = $example2;
$this->example2->setExample1($this);
}
public function foo()
{
echo 'Hello';
return $this->example2;
}
}
class Example2
{
public function setExample1(Example1 $example1)
{
$this->example1 = $example1;
}
public function bar()
{
echo ' World';
return $this->example1;
}
}
$example = new Example1(new Example2());
$example->foo()->bar(); // Hello World
$example->foo()->bar()->foo()->bar(); // Hello WorldHello World
PHP's dereference operator only works on Objects; and, unlike some other languages, only Objects are objects ;) Primitives don't have an implicit wrapper. So, if $this->someobject resolves to a non object, (like a string, float, int or array), you cannot chain the dereference operator any further.
You have the syntax correct, but only for nested objects. Frequently, an object property might be of the array type, so you would need to access it accordingly: $this->somearray['somekey'];
If you're looking to create a fluent interface to allow for chaining, the object methods would need to return $this; in order to facilitate that.
Classes can also be accessed with the :: (scope resolution operator) without being instantiated, but that's a little outside of the scope of the question.
Hope that helps!
Related
I don't truly understand how chaining functions work on the values that are returned.
Let's say I have a function that returns a string or array
public static $query;
public static function getArray($arr) {
Database::$query = $arr;
return Database::$query;
}
public function single() {
return Database::$query[0];
}
Why, when I call it can I then not chain a function onto this to affect the string (In this example I was to append ' test' and how would I go about doing this?
Why can I simply not call
Database::getArray(array("test","test2"))->single();
Without getting a Call to a member function single() on array error. But instead, make it return only the first value of the array.
How would I go append doing what I'm trying to achieve here? Why is my logic wrong?
When you call a method, the return value is whatever that method decides to return; the return value doesn't have any automatic relationship with the object you called the method on. For instance:
class A {
public function foo() {
return 'Hello, World!';
}
}
$a = new A;
echo $a->foo();
The value returned is just an ordinary string, just as if foo was a global function not attached to any object.
In PHP, strings (and other "basic types" like arrays) are not objects, so you can't call any methods on them. Even if you could, those methods would be built into the language, and you couldn't just decide that ->single() could be called on any array.
What may be confusing is that some people write methods with the convention that they return an object, known as a "fluent interface", or more generally "chained methods". This is not a feature of the language, just a natural consequence of returning an object from a method:
class A {
public function foo() {
return new B;
}
}
class B {
public function bar() {
return 'Hello, World!';
}
}
$a = new A;
$b = $a->foo(); // $b is a B object
echo $b->bar();
// We can combine this into one line:
echo (new A)->foo()->bar();
There is nothing special about this chaining; it's just that wherever you have an object, you can call appropriate methods on it, just as wherever you have a number, you can do maths with it. Compare with a simple addition:
function foo() {
return 1;
}
$a = foo();
$a = $a + 2;
echo $a;
// We can combine this into one line:
echo foo() + 2;
// Or keep the assignment:
$a = foo() + 2;
echo $a;
The object doesn't know it's being chained - in fact, it shouldn't need to know anything about the code around it, and that's an important part of structured programming.
A common pattern is then to have modifying methods which return the object they just modified, so you can make a series of modifications in one go:
class A {
private $words = [];
public function addWord($word) {
$this->words[] = $word;
// $this is the current object, which is an instance of class A
return $this;
}
public function getString() {
return implode(' ', $this->words);
}
}
$a = new A;
// Calling $a->addWord(...) gives us back the same object
$a = $a->addWord('Hello');
$a = $a->addWord('World');
// Calling $a->getString() gives us back a string
echo $a->getString();
// We can combine this into one line:
echo (new A)->addWord('Hello')->addWord('World')->getString();
Note that you can only refer to $this if you have created an instance of the object (with the new keyword), not in a method declared as static. A static method can still have this kind of pattern, but it will need to return some other object, like new self (a new instance of the current class) or self::$foo (an object created earlier).
it's called fluent interface, if you want to chain methods from same class you have to return this from each of them which you want to call fluently, so your code should look like:
public static $query;
public function getArray($arr) {
Database::$query = $arr;
return $this;
}
public function single() {
return Database::$query[0];
}
after applying changes, the construct Database::getArray(array("test","test2"))->single(); will work, however you may consider renaming method getArray, because as its name suggests, it shouldn't be returning $this, but array
#EDIT
you should change the type of function getArray from public static function to public function to make it work, also your final statement will change to something like:
(new Database())->getArray(array("test","test2"))->single();
however, in this case, I would consider redesigning your class and creating some kind of singleton so that you instantiate Database class only once and store the object somewhere
There are two distinct ways to access methods in PHP, but what's the difference?
$response->setParameter('foo', 'bar');
and
sfConfig::set('foo', 'bar');
I'm assuming -> (dash with greater than sign or chevron) is used for functions for variables, and :: (double colons) is used for functions for classes. Correct?
Is the => assignment operator only used to assign data within an array? Is this in contrast to the = assignment operator which is used to instantiate or modify a variable?
When the left part is an object instance, you use ->. Otherwise, you use ::.
This means that -> is mostly used to access instance members (though it can also be used to access static members, such usage is discouraged), while :: is usually used to access static members (though in a few special cases, it's used to access instance members).
In general, :: is used for scope resolution, and it may have either a class name, parent, self, or (in PHP 5.3) static to its left. parent refers to the scope of the superclass of the class where it's used; self refers to the scope of the class where it's used; static refers to the "called scope" (see late static bindings).
The rule is that a call with :: is an instance call if and only if:
the target method is not declared as static and
there is a compatible object context at the time of the call, meaning these must be true:
the call is made from a context where $this exists and
the class of $this is either the class of the method being called or a subclass of it.
Example:
class A {
public function func_instance() {
echo "in ", __METHOD__, "\n";
}
public function callDynamic() {
echo "in ", __METHOD__, "\n";
B::dyn();
}
}
class B extends A {
public static $prop_static = 'B::$prop_static value';
public $prop_instance = 'B::$prop_instance value';
public function func_instance() {
echo "in ", __METHOD__, "\n";
/* this is one exception where :: is required to access an
* instance member.
* The super implementation of func_instance is being
* accessed here */
parent::func_instance();
A::func_instance(); //same as the statement above
}
public static function func_static() {
echo "in ", __METHOD__, "\n";
}
public function __call($name, $arguments) {
echo "in dynamic $name (__call)", "\n";
}
public static function __callStatic($name, $arguments) {
echo "in dynamic $name (__callStatic)", "\n";
}
}
echo 'B::$prop_static: ', B::$prop_static, "\n";
echo 'B::func_static(): ', B::func_static(), "\n";
$a = new A;
$b = new B;
echo '$b->prop_instance: ', $b->prop_instance, "\n";
//not recommended (static method called as instance method):
echo '$b->func_static(): ', $b->func_static(), "\n";
echo '$b->func_instance():', "\n", $b->func_instance(), "\n";
/* This is more tricky
* in the first case, a static call is made because $this is an
* instance of A, so B::dyn() is a method of an incompatible class
*/
echo '$a->dyn():', "\n", $a->callDynamic(), "\n";
/* in this case, an instance call is made because $this is an
* instance of B (despite the fact we are in a method of A), so
* B::dyn() is a method of a compatible class (namely, it's the
* same class as the object's)
*/
echo '$b->dyn():', "\n", $b->callDynamic(), "\n";
Output:
B::$prop_static: B::$prop_static value
B::func_static(): in B::func_static
$b->prop_instance: B::$prop_instance value
$b->func_static(): in B::func_static
$b->func_instance():
in B::func_instance
in A::func_instance
in A::func_instance
$a->dyn():
in A::callDynamic
in dynamic dyn (__callStatic)
$b->dyn():
in A::callDynamic
in dynamic dyn (__call)
:: is used in static context, ie. when some method or property is declared as static:
class Math {
public static function sin($angle) {
return ...;
}
}
$result = Math::sin(123);
Also, the :: operator (the Scope Resolution Operator, a.k.a Paamayim Nekudotayim) is used in dynamic context when you invoke a method/property of a parent class:
class Rectangle {
protected $x, $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
}
class Square extends Rectangle {
public function __construct($x) {
parent::__construct($x, $x);
}
}
-> is used in dynamic context, ie. when you deal with some instance of some class:
class Hello {
public function say() {
echo 'hello!';
}
}
$h = new Hello();
$h->say();
By the way: I don't think that using Symfony is a good idea when you don't have any OOP experience.
Actually by this symbol we can call a class method that is static and not be dependent on other initialization...
class Test {
public $name;
public function __construct() {
$this->name = 'Mrinmoy Ghoshal';
}
public static function doWrite($name) {
print 'Hello '.$name;
}
public function write() {
print $this->name;
}
}
Here the doWrite() function is not dependent on any other method or variable, and it is a static method. That's why we can call this method by this operator without initializing the object of this class.
Test::doWrite('Mrinmoy');
// Output: Hello Mrinmoy.
But if you want to call the write method in this way, it will generate an error because it is dependent on initialization.
The => operator is used to assign key-value pairs in an associative array. For example:
$fruits = array(
'Apple' => 'Red',
'Banana' => 'Yellow'
);
It's meaning is similar in the foreach statement:
foreach ($fruits as $fruit => $color)
echo "$fruit is $color in color.";
The difference between static and instantiated methods and properties seem to be one of the biggest obstacles to those just starting out with OOP PHP in PHP 5.
The double colon operator (which is called the Paamayim Nekudotayim from Hebrew - trivia) is used when calling an object or property from a static context. This means an instance of the object has not been created yet.
The arrow operator, conversely, calls methods or properties that from a reference of an instance of the object.
Static methods can be especially useful in object models that are linked to a database for create and delete methods, since you can set the return value to the inserted table id and then use the constructor to instantiate the object by the row id.
Yes, I just hit my first 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. My bad, I had a $instance::method() that should have been $instance->method(). Silly me.
The odd thing is that this still works just fine on my local machine (running PHP 5.3.8) - nothing, not even a warning with error_reporting = E_ALL - but not at all on the test server, there it just explodes with a syntax error and a white screen in the browser. Since PHP logging was turned off at the test machine, and the hosting company was too busy to turn it on, it was not too obvious.
So, word of warning: apparently, some PHP installations will let you use a $instance::method(), while others don't.
If anybody can expand on why that is, please do.
I'm coming from a .Net background and I'm trying to wrap my brain around a programming pattern that I'm used to but in PHP.
I've got a class with an associative array property. I'd like to "elevate" some, but not all, of the associative array keys to class-level properties. In C# I'd normally do something like this:
//C# Code
class MyClass{
private Dictionary<string, string> attributes = new Dictionary<string,string>();
//Get/Set the ID from the private store
public string ID{
get { return (attributes.ContainsKey("ID") ? attributes["ID"] : "n/a"); }
set { attributes.Add("ID", value); }
}
}
This allows my object to control default values for missing properties. In PHP I couldn't find any way to do this directly. My first workaround was to just use functions:
//PHP Code
class MyClass{
private $attributes = array();
//Get the ID
public function getID(){
return (array_key_exists('ID', $this->attributes) ? $this->attributes['ID'] : 'n/a');
}
//Set the ID
public function setID($value){
$this->attributes['ID'] = $value;
}
}
This works although the calling syntax is slightly different and I've got two methods per property. Also, the code that is consuming these objects is currently inspecting object variables so functions wouldn't be found.
Then I started going down the magic method paths of __set and __get on the object itself and just switch case on the $name that's passed in and setting/getting my local variables. Unfortunately these methods don't get invoked if you modify the underlying array directly.
So my question is, is it possible in PHP to have a class-level property/variable that doesn't get calculated until it gets used?
PHP doesn't have properties as C# programmers would understand the concept, so you'll have to use methods as the getter and setter, but the principle is exactly the same.
class MyClass {
private $attributes = array ();
public function getSomeAttribute () {
if (!array_key_exists ('SomeAttribute', $this -> attributes)) {
// Do whatever you need to calculate the value of SomeAttribute here
$this -> attributes ['SomeAttribute'] = 42;
}
return $this -> attributes ['SomeAttribute'];
}
// or if you just want a predictable result returned when the value isn't set yet
public function getSomeAttribute () {
return array_key_exists ('SomeAttribute', $this -> attributes)?
$this -> attributes ['SomeAttribute']:
'n/a';
}
public function setSomeAttribute ($value) {
$this -> attributes ['SomeAttribute'] = $value;
}
}
You essentially got the basic ideas right with your implementation, but it does mean a lot of "boilerplate" code. In theory you can avoid a lot of that with __get and __set, but I'd strongly advise against those as they can lead to epic amounts of confusion and nasty logical tangles like the "what happens if the value is set within the class instead of from outside?" issue that you've run into.
In PHP You can do something like this:
<?php
class MyClassWithoutParams{
function test(){
return $this->greeting . " " . $this->subject;
}
}
$class = new MyClassWithoutParams();
$class->greeting = "Hello";
$class->subject = "world";
echo $class->greeting . " " . $class->subject . "<br />"; //Hello World
echo $class->test(). "<br />"; //Hello World
?>
You don't need to define any property, getter or setter to use properties. Of course it is better to do so, because it makes the code easier to read and allows autocomplete-functions of eclipse (or whatever IDE) to understand what you are looking for - but if you are just looking for the laziest way to implement an entity, that would work as well.
A more common approach would be to use an associative array instead of a class - but on arrays you cant define methods.
<?php
$array = new array();
$array["greeting"] = "Hello";
$array["subject"] = "World";
echo $array["greeting"] . " " . $array["subject"]; //Output: Hello World
?>
I was looking to some php codes, and I saw an object that will call multiple methods in the same line.
I've tried to understand how to do it, and why we need to use it?
$object->foo("Text")->anotherFoo()->bar("Aloha")
What this styling called? and what is the best way to use it in php applications.
This syntax is called method chaining, and it's possible because each method returns the object itself ($this). This is not necessarily always the case, it's also used to retrieve an object's property that in turn also can be an object (which can have properties that are objects, and so on).
It is used to reduce the amount of lines that you need to write code on. Compare these two snippets:
Without chaining
$object->foo("Text");
$object->anotherFoo();
$object->->bar("Aloha");
Using method chaining
$object->foo("Text")->anotherFoo()->bar("Aloha");
this is used when the first function returns an object that will contains the second function that will return another object and so on...
class X
{
public function A()
{
echo "A";
}
public function B()
{
echo "B";
}
}
class Y
{
public function A()
{
echo "Y";
}
public function B()
{
return $this;
}
}
$y = new Y();
$y->B()->A();//this will run
$x = new X();
$x->A()->B();//this won't run, it will output "A" but then A->B(); is not valid
I understand how it works but why would we practically use this?
<?php
class cat {
public function __toString() {
return "This is a cat\n";
}
}
$toby = new cat;
print $toby;
?>
Isn't this the same as this:
<?php
class cat {
public function random_method() {
echo "This is a cat\n";
}
}
$toby = new cat;
$toby->random_method();
?>
can't we just use any other public method to output any text?
Why do we need magic method like this one?
You don't "need" it. But defining it allows your object to be implicitly converted to string, which is convenient.
Having member functions that echo directly is considered poor form because it gives too much control of the output to the class itself. You want to return strings from member functions, and let the caller decide what to do with them: whether to store them in a variable, or echo them out, or whatever. Using the magic function means you don't need the explicit function call to do this.
In addition to all existing answers, here's an example, :
class Assets{
protected
$queue = array();
public function add($script){
$this->queue[] = $script;
}
public function __toString(){
$output = '';
foreach($this->queue as $script){
$output .= '<script src="'.$script.'"></script>';
}
return $output;
}
}
$scripts = new Assets();
It's a simple class that helps you manage javascripts. You would register new scripts by calling $scripts->add('...').
Then to process the queue and print all registered scripts simply call print $scripts;.
Obviously this class is pointless in this form, but if you implement asset dependency, versioning, checks for duplicate inclusions etc., it starts to make sense (example).
The basic idea is that the main purpose of this object is to create a string (HTML), so the use of __toString in this case is convenient...
__toString() is called when an object is passed to a function (esp echo() or print()) when its context is expected to be a string. Since an object is not a string, the __toString() handles the transformation of the object into some string representation.
It's just a standardized method to produce a string representation of an object. Your random_method approach works if you assume all objects in your program uses that same method, which might not be the case if you use third party libraries.
You don't need the magic method, but it provides convenience, as you'll never really have to call it explicitly.
Also, if PHP should internally ever want to turn your object into text, it knows how to do that.
The __toString method allows a class to decide how it will react when it is treated like a string
http://www.php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
__toString allows you to define the output when your object is converted to a string. This means that you can print the object itself, rather than the return value of a function. This is frequently more convenient. See the manual entry.
__toString allows you to define the output when your object is converted to a string. This means that you can print the object itself, rather than the return value of a function.
Have a look at below example:
<?php
class Student
{
protected $name;
protected $age;
public function getName(){
return $this->name;
}
public function getAge(){
return $this->age;
}
private function setName($name){
$this->name = $name;
}
private function setAge($age){
$this->age = $age;
}
public function __construct($name, $age) {
$this->setName($name);
$this->setAge($age);
}
public function __toString(){
return "hello ". $this->getName(). " my age is ". $this->getAge();
}
}
$obj = new Student("Sajib", 23);
echo $obj;
Using __toString() overrides the operator that is called when you print objects of that class, so it makes it easier for you to configure how an object of that class should be displayed.
__String helps us it returning error message in case there is some error in constructor.
Following dummy code will clarify it better. Here if creation of object is failed, an error string is sent:
class Human{
private $fatherHuman;
private $errorMessage ="";
function __construct($father){
$errorMessage = $this->fatherHuman($father);
}
function fatherHuman($father){
if($father qualified to be father){
$fatherHuman = $father;
return "Object Created";//You can have more detailed string info on the created object like "This guy is son of $fatherHuman->name"
} else {
return "DNA failed to match :P";
}
}
}
function run(){
if(ctype_alpha($Rahul = Human(KingKong)){
echo $Rahul;
}
}
run(); // displays DNA failed to match :P
You don't have to specifically call the toString method. When ever you print the object toString is being called implicitly. Any other method would have to be called explicitly.
it's like override with c# :
class Person
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return FirstName + “ “ + LastName;
}
}