Where and why do we use __toString() in PHP? - php

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;
}
}

Related

Calling Static Member Function on Class Stored as String in PHP?

Since I am aware that one can call a member function on Class stored as String. But I was wondering if there is any way to do the same for static member function in PHP.
for example:
class A
{
public static function run(){
echo "OK";
}
}
"A"::"run"()
Something similar to the above example.
Please help me out. Thanks in advance.
you can call class as string like this
<?php
class A
{
public static function run()
{
echo "OK";
}
}
$stringClass = "A";
$staticMethod = "run";
$stringClass::$staticMethod();
To tackle this type of problem, which I faced while developing a user-friendly PHP framework, is to store the class name and static method name as a string in some PHP variables.
$className = "A";
$methodName = "run";
And call it like so:
$className::$methodName();
or second way
$func = "A::run";
$func(); //or
"A::run"();
And this is how one calls the static method on the class stored as a string.
This one of the ways, more can be found at https://www.designcise.com/web/tutorial/how-to-dynamically-invoke-a-class-method-in-php

Method return different type of var depending on the context

Better than few words, what I want to do is :
Return string
$obj->method();
In this case, I want method() to return an object
$obj->method()->method2();
Is that possible?
And if possible, someone could help me please ?
No. The method() method cannot know whether it will be used as a string or as an object. The only thing you can do that comes somewhat near your expectation would be to have it return an object with a __toString() method:
<?php
class YourObject {
public function method2() {
// ...
}
public function __toString() {
return 'some string';
}
}
?>
and have $obj->method() return an instance of this class. You can use that like a string (echo $obj->method();) as well as an object ($obj->method->method2();).
Pass a simple boolean to the method to tell it what to return.

PHP Multiple Object Dereference

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!

Assigning a function's result to a variable within a PHP class? OOP Weirdness

I know you can assign a function's return value to a variable and use it, like this:
function standardModel()
{
return "Higgs Boson";
}
$nextBigThing = standardModel();
echo $nextBigThing;
So someone please tell me why the following doesn't work? Or is it just not implemented yet? Am I missing something?
class standardModel
{
private function nextBigThing()
{
return "Higgs Boson";
}
public $nextBigThing = $this->nextBigThing();
}
$standardModel = new standardModel;
echo $standardModel->nextBigThing; // get var, not the function directly
I know I could do this:
class standardModel
{
// Public instead of private
public function nextBigThing()
{
return "Higgs Boson";
}
}
$standardModel = new standardModel;
echo $standardModel->nextBigThing(); // Call to the function itself
But in my project's case, all of the information stored in the class are predefined public vars, except one of them, which needs to compute the value at runtime.
I want it consistent so I nor any other developer using this project has to remember that one value has to be function call rather then a var call.
But don't worry about my project, I'm mainly just wondering why the inconsistency within PHP's interpreter?
Obviously, the examples are made up to simplify things. Please don't question "why" I need to put said function in the class. I don't need a lesson on proper OOP and this is just a proof of concept. Thanks!
public $nextBigThing = $this->nextBigThing();
You can only initialize class members with constant values. I.e. you can't use functions or any sort of expression at this point. Furthermore, the class isn't even fully loaded at this point, so even if it was allowed you probably couldn't call its own functions on itself while it's still being constructed.
Do this:
class standardModel {
public $nextBigThing = null;
public function __construct() {
$this->nextBigThing = $this->nextBigThing();
}
private function nextBigThing() {
return "Higgs Boson";
}
}
You can't assign default values to properties like that unless that value is of a constant data type (such as string, int...etc). Anything that essentially processes code (such as a function, even $_SESSION values) can't be assigned as a default value to a property. What you can do though is assign the property whatever value you want inside of a constructor.
class test {
private $test_priv_prop;
public function __construct(){
$this->test_priv_prop = $this->test_method();
}
public function test_method(){
return "some value";
}
}
class standardModel
{
// Public instead of private
public function nextBigThing()
{
return "Higgs Boson";
}
}
$standardModel = new standardModel(); // corection
echo $standardModel->nextBigThing();

calling class method (with constructors) without object instantiation in php

Ive looked and tried but I can't find an answer.
In PHP, is it possible to call a class' member function (when that class requires a constructor to receive parameters) without instantiating it as an object?
A code example (which gives errors):
<?php
class Test {
private $end="";
function __construct($value) {
$this->end=$value;
}
public function alert($value) {
echo $value." ".$this->end;
}
}
//this works:
$example=new Test("world");
$example->alert("hello");
//this does not work:
echo Test("world")::alert("hello");
?>
Unfortunately PHP doesn't have support to do this, but you are a creative and look guy :D
You can use an "factory", sample:
<?php
class Foo
{
private $__aaa = null;
public function __construct($aaa)
{
$this->__aaa = $aaa;
}
public static function factory($aaa)
{
return new Foo($aaa);
}
public function doX()
{
return $this->__aaa * 2;
}
}
Foo::factory(10)->doX(); // outputs 20
Just do this (in PHP >= 5.4):
$t = (new Test("Hello"))->foo("world");
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.
You can't call an instance-level method without an instance. Your syntax:
echo Test("world")::alert("hello");
doesn't make a lot of sense. Either you're creating an inline instance and discarding it immediately or the alert() method has no implicit this instance.
Assuming:
class Test {
public function __construct($message) {
$this->message = $message;
}
public function foo($message) {
echo "$this->message $message";
}
}
you can do:
$t = new Test("Hello");
$t->foo("world");
but PHP syntax doesn't allow:
new Test("Hello")->foo("world");
which would otherwise be the equivalent. There are a few examples of this in PHP (eg using array indexing on a function return). That's just the way it is.
For this you can do a
https://www.php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php
reflect your class and trigger the new instance without constructor.
Here a sample code:
<?php
class Test {
private $end="";
function __construct($value) {
$this->end=$value;
}
public function alert($value) {
echo $value." ".$this->end;
}
public function end($value) {
$this->end = $value;
return $this; // return Test object so that you can chain to other function method.
}
}
// Solution #1:
// reflect your class.
$reflector = new \ReflectionClass('Test');
// Then create a new instance without Constructor.
// This will ignore the constructor BUT it will create a new instance of class Test.
$say = $reflector->newInstanceWithoutConstructor();
// use end method that will return the Test object, then you can chain the alert()
$say->end('World!')->alert("Hello"); // output: Hello World!
?>
// this does not work:
echo Test("world")::alert("hello");
// works, as you are calling not to an object of the class, but to its namespace
echo Test::alert("hello");

Categories