PHP - Object of class could not be converted to string - php

I'm trying to print a property of the simple class below. But instead i get the error above. I haven't found an answer on similar questions on here. The error triggers on this line:
echo "$object1 name = " . $object1->name . "<br>";
Using XAMPP on Windows Help?
<?php
$object1 = new User("Pickle", "YouGotIt");
print_r($object1);
$object1->name = "Alice";
echo "$object1 name = " . $object1->name . "<br>"; /* this triggers the error */
class User
{
public $name, $password;
function __construct($n, $p) { // class constructor
$name = $n;
$password = $p;
}
}
?>

There are two things wrong in your code,
You're using local variables in your class constructor, not instance properties. Your constructor method should be like this:
function __construct($n, $p) {
$this->name = $n;
$this->password = $p;
}
Now comes to your error, Object of class could not be converted to string. This is because of this $object in echo statement,
echo "$object1 name = " ...
^^^^^^^^
You need to escape this $object1 with backslash, like this:
echo "\$object1 name = " . $object1->name . "<br>";

In my case the problem was the way I was initializing the class variable.
This was my code :
public function __construct(User $userObj) {
$this->$userObj = $userObj;
}
and I solved it by changing it to the following :
public function __construct(User $userObj) {
$this->userObj = $userObj;
}
The line in the first snippet caused the problem : $this->$userObj = $userObj

Related

Undefined property in dynamic variable of a PHP class

I am trying to get a dynamic variable value in a PHP class but not sure how to do this. Here's my code:
<?php
class Test
{
public $type = "added";
public $date_added;
public function set_status()
{
$this->date_added = "Pass";
}
public function get_status()
{
echo $this->date_{$type};
}
}
$test = new Test();
$test->set_status();
$test->get_status();
?>
I am getting following error:
Notice: Undefined property: Test::$date_ in...
Notice: Undefined variable: type in ...
If I write echo $this->date_added; in place of echo $this->date_{$type}; then I get output "Pass".
How to fix it and do it properly?
Since you're using variable variables, put them in quotes, then concatenate:
echo $this->{'date_' . $this->type};
// not $type, use `$this->` since it's part of your properties
Or using via formatted string (double quotes will work as well):
echo $this->{"date_{$this->type}"};
<?php
class Test
{
public $type = "added";
public $date_added;
public function set_status()
{
$this->date_added = "Pass";
}
public function get_status()
{
echo $this->{'date_' . $this->type};
}
}
$test = new Test();
$test->set_status();
$test->get_status();
?>
You can do it multiple ways, date_{$type} is not valid expression and to acccess the class property you have to use this keyword .
class Test
{
public $type = "added";
public $date_added;
public function set_status()
{
$this->date_added = "Pass";
}
public function get_status()
{
$prop = 'date_'.$this->type;
echo $this->{'date_'.$this->type}; # one way to do it
echo $this->$prop; # another way to do it
echo $this->{"date_{$this->type}"}; # another way to do it
}
}
$test = new Test();
$test->set_status();
$test->get_status();

function __get() not giving any effect in PHP

So I'm following a tutorial about OOP in PHP and got stuck in understanding how __get() function works. Here's the code:
<?php
class Animal{
protected $name;
protected $favorite_food;
protected $sound;
protected $id;
public static $number_of_animals = 0;
const PI = "3.14159";
//function to return the name
//encapsulation
function getName(){
//when you want to refer attribute in a class
return $this->name;
}
//initialize things
function __construct(){
//generate random 100-10
$this->id = rand(1,10);
echo $this->id ." has been assigned<br/>";
//akses static attribute in a class
Animal::$number_of_animals++;
}
//destruct the object
function __destruct(){
echo $this->name ." is being destroyed :(";
}
//getter : to get protected attribute of a function
function __get($name){
echo "Asked for " . $name . "<br/>";
return $this->$name;
}
//setter : set the attribute to
function __set($name, $value){
switch($name){
case "name" :
$this->name = $value;
break;
case "favorite_food" :
$this->favorite_food = $value;
break;
case "sound" :
$this->sound = $value;
break;
default :
echo $name ."Name not found";
}
echo "Set " .$name. " to " .$value. "<br/>";
}
function run(){
echo $this->name. " runs<br/>";
}
}
class Dog extends Animal{
function run(){
echo $this->name. " runs like crazy<br/>";
}
}
$animal_one = new Animal();
$animal_one->name = " SPOT";
$animal_one->favorite_food = " MEAT";
$animal_one->sound = " RUFF";
echo $animal_one->name ." says". $animal_one->sound. " give me some " .$animal_one->favorite_food. " my id is " .$animal_one->id. " total animal is " .Animal::$number_of_animals. "<br/><br/>";
?>
The output will be like this :
5 has been assigned
Set name to SPOT
Set favorite_food to MEAT
Set sound to RUFF
Asked for name
Asked for sound
Asked for favorite_food
Asked for id
SPOT says RUFF give me some MEAT my id is 5 total animal is 1
SPOT is being destroyed :(
When I try to change the argument and value in __get() function to another attribute like $sound or $favorite_food, it doesn't give any change to the output. The output will still the same. I don't get it why we should set it only to $name.
The name of the parameter inside any function is scoped to that function alone, and doesn't have any reference anywhere else.
You're probably getting confused in that your local function parameter $name has the same name as one of it's class properties $this->name
Notice in your __get method, $name is a stand-in variable for what could be any protected/private property, which is dynamically evaluated at run-time:
$this->$name
as opposed to a hard-coded property
$this->name
Consider this example:
class MyClass {
protected $one = 'first';
protected $name = 'fred';
public function __get(String $property){
return $this->$property;
}
public function getOne(){
return $this->one;
}
public function foo(String $variable_could_be_named_anything){
return $variable_could_be_named_anything;
}
}
$object = new MyClass;
echo $object->one; // first (using __get)
echo $object->getOne(); // first
$object->two = 'second'; // because this property isn't declared protected, accessed normally
echo $object->two; // second
$name = 'jon';
echo $object->name; // fred
echo $object->foo($name); // jon
echo $object->three; // PHP Notice: Undefined property: MyClass::$three
$object->one = 'something'; // Fatal error: Cannot access protected property

Getting a value from a PHP object

I have an object that is returns as below.
print_r($all->getInfo());
//returns the following on browser.
User Object ( [_name:User:private] => Kanye, West [_email:User:private] => kanye#hotmail.com)
I would like to read the name and email and set it to two seperate variables like below.
$email = $all->getInfo()._email;
$name= $all->getInfo()._name;
Any help would be greatly appreciated.
You can do somtething like this to get access to private proprites.
class sampleClass {
private $property1 = 'name';
private $prooerty2 = 'email';
public function getProperty1(){
return $this->property1;
}
public function getProperty2(){
return $this->property2;
}
public function setProperty1($name){
}
$this->property1 = $name;
}
public function setProperty2($email){
$this->property2 = $email;
}
}
To get properties:
$classy = new sampleClass();
echo $classy->getProperty1;
echo $classy->getProperty2;
To set properties:
$classy->setProperty1('name1');
$classy->setProperty2('email2');
You can also use magic methods for __get and __set, more info.
If you want to access the values, you can either set them to public (which may not be the best solution depending on what you're trying to do), or create the __get() magic method
class foo
{
private $value = "foo";
private $value2 = "foo2";
public function __get($name)
{
switch ($name)
{
case "value";
return $this->$name;
default:
return null;
}
}
}
class bar
{
private $value = "bar";
}
$f = new foo;
$b = new bar;
echo "Result:" . $f->value . "<br/>";
echo "Result:" . $f->value2 . "<br/>";
echo "Result:" . $b->value . "<br/>";
this yeilds
Result:foo
Result:
E_ERROR : type 1 -- Cannot access private property bar::$value -- at line 31
Of course, you can also create a function such as get_name() but then you'd have to do that for every private property you want to access.
If you want to control what is and what is not accessible from the __get() method, you can add some logic. This way you know that if you are trying to access a property, it's in the __get() method and not have to try to figure out what the method name is.

How to set class variables dynamically?

Consider the following code:
class Project
{
public $ProjectID;
}
class Work
{
public $WorkID;
}
public function insert($pData, $tableName)
{
//generate insert here
$pData->{$tableName . 'ID'} = $result->getId();
}
$p = new Project();
$w = new Work();
insert($w, 'Work');
insert($p, 'Project');
echo $p . ' -- ' . $w;
Now how would I go about setting the variable in a dynamic way? I'm building a data layer. The $pData->{$tableName . 'ID'} doesn't seem to work...
So, you want to dynamically call setters?
$y = new stdClass();
$y->prop1 = "something";
$targetProperty = "prop1";
$y->$targetProperty = "something else";
echo $y->prop1;
//Echos "something else"
That what you're looking for?
This is what you're looking for:
public function set_to_seven($p_data, $name)
{
$name = $name . 'ID';
$p_data->$name = 7;
}
The property name can be a variable. Just like functions:
$p = 'print_r';
$p('StackOverflow');
For future reference: if you need this statically, you're looking for variable variables,
public function set_to_seven($p_data, $name)
{
$name = $name . 'ID';
$p_data::$$name = 7;
}
You can set public properties by accessing them just like any other definition in the class.
$p = new Project();
$p->ProjectID = 5;
echo $p->ProjectID; // prints 5
http://php.net/manual/en/language.oop5.visibility.php
This worked for me.
class Project {
public $ProjectID;
}
function setToSeven($pData, $name) {
$pData->{$name . "ID"} = 7;
}
$p = new Project();
setToSeven($p, 'Project');
echo $p->ProjectID;
You just need to echo the variable or set up a toString function on the class to echo the class. To String works like this
class Project {
public $ProjectID;
public function __toString(){
return (string)$this->ProjectID;
}
}
function setToSeven($pData, $name) {
$pData->{$name . "ID"} = 7;
}
$p = new Project();
setToSeven($p, 'Project');
echo $p;

Method chanining and re-use of same class

I have the following class:
class DB {
private $name;
public function load($name) {
$this->name = $name;
return $this;
}
public function get() {
return $this->name;
}
}
At the moment if I do:
$db = new DB();
echo $db->load('foo')->get() . "<br>";
echo $db->load('fum')->get() . "<br>";
This outputs "foo" then "fum".
However if I do this:
$db = new DB();
$foo = $db->load('foo');
$fum = $db->load('fum');
echo $foo->get() . "<br>";
echo $fum->get() . "<br>";
It always outputs "fum".
I can sort of see why it would do that, but how could I keep the variable seperate to each instance without having to create a new instance of DB?
IF you mean for DB to be some sort of database connectivity object (which I assume you are), multiple instances may not be the best choice. Perhaps something like this may be what you are trying to do:
$db = new DB();
$foo = $db->load('foo')->get();
$fum = $db->load('fum')->get();
echo $foo . "<br>";
echo $fum . "<br>";
If what I think you are trying to do is correct, it may be better to separate your get logic from the DB class into its own Record class.
class Record {
function __construct($name) {
$this->name = $name;
}
function get(){
return $this->name;
}
private $name;
}
class DB {
public function load($name) {
return new Record($name);
}
}
$db = new DB();
$foo = $db->load('foo');
$fum = $db->load('fum');
echo $foo->get() . "<br>";
echo $fum->get() . "<br>";
To keep it separate to each instance, you would, by definition, need to create a new instance... You could do that though in the load() method. Instead of returning $this, you could return a new DB() configured the way you want. Then make the method static.
This is what's called the factory pattern.
What you're experiencing in your code is similar to PHP's pass by reference feature.
When you set the first variable, $foo is equal to the value of $db->name, when you call it again to set it to 'fum', you're setting $fum equal to $db->name. Since you're echoing them both at the end, they're both going to be the last value you set it to.
Try this and see if your results are different.
$db = new DB();
$foo = $db->load('foo');
echo $foo->get() . "<br>";
$fum = $db->load('fum');
echo $fum->get() . "<br>";
When you run $db->load(), create a new object and return that instead of the object you're currently in.

Categories