Please take a look at the output I get when I print out the contents of an Exception object (using the built-in class here):
Exception Object
(
[message:protected] => My custom message
[string:Exception:private] =>
[code:protected] => 2281488
[file:protected] => /home/user/scripts/test.php
[line:protected] => 18
[trace:Exception:private] => Array
(
)
[previous:Exception:private] =>
)
Most of the fields have the field_name:visibility_keyword format, but two of them have Exception appear in between. What does this denote?
Also, two other fields, namely $string and $trace, aren't mentioned in the official manual but I know the latter receives a value when an exception object is thrown within a function, so it contains the order in which functions are called until one of them creates said exception.
The string field gets assigned a value when I try to echo an exception and remains empty unless I echo it before the contents of the object are printed out. Can you please enlighten me on how this field works exactly?
I'd appreciate any input I can get. Thanks!
This has nothing to do with exceptions, it's just how var_dump() and print_r() display private and protected properties of objects.
Private properties are always shown with the name of the class before :private
That tells you which class in the inheritance hierarchy is allowed to access that property.
This isn't needed for protected properties, because any class in the hierarchy can access them.
class Class1 {
private $private1;
protected $protected1;
public $public1;
}
class Class2 extends Class1 {
private $private2;
protected $protected2;
public $public2;
}
print_r(new Class2);
displays
Class2 Object
(
[private2:Class2:private] =>
[protected2:protected] =>
[public2] =>
[private1:Class1:private] =>
[protected1:protected] =>
[public1] =>
)
Private properties aren't mentioned in the manual because they're not part of the public interface, they're just for internal use by the class. That's why they're declared private.
Protected properties are documented because you can access them if you define subclasses of Exception.
string:Exception:private.
string means a property of Exception class that has private visibility. Same with the previous and trace. These three properties are exclusively available only in the Exception class. As you noticed, protected properties have no class between because it can be passed on the child classes. This statement is also true to public properties.
Related
I am having trouble accessing the object property. It should be straightforward, but I am getting
Notice : Undefined property: myClass::$myname:protected in ...
My object, when I do a print_r looks like this:
myClass Object
(
[myname:protected] => Array
(
[key1] => stdClass Object
(
[slug] => name
[name] => Big Name
)
.
.
.
[mykey] => stdClass Object
(...
And I tried printing
print_r($this->{'myname:protected'});
to see if I'll get the array out, from which I can get what I need. But I got the above error.
print_r($this); returns my object, since I am inside a public function (method) in my class myClass.
Why can't I access that key, but when I do print_r($this->mykey->property1) for instance, I can easily get any property for mykey object?
Why is it adding $ in front of the name? I know some oo php, but I'm still a beginner. I have a
protected $myname;
at the beginning of the file, and I'm using it in my __construct() like
public function __construct($myname){...}
Note: I am trying to modify and figure out someone else's code, so I'm not 100% sure what every single piece does yet :\
EDIT:
When I do
print_r($this->myname);
I get the array I need. Can anyone clarify why is that? Thanks.
The member name is myname - the :protected shown in the output of print_r is just debugging information to show that its a protected member of the object.
So from a class method, you would access the member as:
$this->myname
I have a main class that includes component classes, an app class, and a section class.
Everything was fine until I tried to eliminate recursion I found in a print_r of the final $this
Now every class extends from another. Only the components and app class extend from the main class. The section extends from the app class. Which at this point seems fine except for one problem:
When I call a top level function from within an inherited class, the function unsets an important class from the top level parent.
class Framework
{
protected $Data;
function __construct()
{
// include all files...
$this->Data = new MySQLClass;
}
function getItem( $item )
{
$this->Data->table = 'items';
$this->Data->data = array( 'id' => $item );
$this->Data->Query();
}
}
Inside the component class (inherits from main) a call is made to $this->getItem()
It now returns
Fatal error: Call to undefined method stdClass::Query()
I did a print_r of $this->Data at the beginning and end of getItem() and sure enough the lines that define the class action (Data->table, Data->data) are redefining $this->Data
First print_r (normal at this point)
MySQLClass Object ( ... )
Second print_r (changed to values set in function)
stdClass Object
(
[table] => items
[data] => Array
(
[id] => 1
)
)
This function works as intended when called from the main class, and has always worked as intended before the classes were extended. I'm thinking of just holding down CTRL + Z and forgetting I ever noticed. Don't fix what ain't broke right? Still I would like to know exactly why this is happening and how to properly call top level functions from child classes.
Thanks,
class Test
{
private $private = "";
public function add($string) {
$this->private[] = $string;
}
public function evaluate(Test $container) {
return $container->private;
}
}
$test = new Test();
$test->add("zero");
$test->add("one");
$test->add("two");
$result = new Test();
print_r($result->evaluate($test));
The above code demonstrates the dump of a private string, how is this possible?
Then, why is it called "private"?
Can anyone explain this to me?
Output:
Array (
[0] => one
[1] => two
[2] => four
)
Because you are calling that private property from inside the class. private means it can only be used by properties and methods inside it's own class. You call a method, which is allowed to use that property. Private properties are accessible by it's class, even if it's a different instance of the class.
You'll find the following:
print_r($result::$private);
Will give you the error:
Fatal error: Cannot access private property
private in PHP means private to any object of the same type.
As stated here in the PHP manual:
Objects of the same type will have access to each others private and protected members even though they are not the same instances.
Yes, it is different to some other languages, but it is documented, and this is the way it works.
This is because even though the attribute $private is private, the class Test still knows about it and can access it, even though it's a different instance. If you were to create a second class Test2() with the same evaluate method which expects a Test instance then the evaluate will fail. This is a bit tricky, but the class Test knows all about its members even from remote instances.
public function evaluate is public and it can access private variable inside the class. you can't direct access the public variable like $result->$private
is private because you can't access this variable/member out of class.
i get a resultset from a class that manages WSDL Data.
I didn't write the code to the class, i only use it.
I call a function to create an ID with the service and want to work with that ID later in the same script.
My Resultset looks like this:
Array
(
[0] => SaveResult Object
(
[id:protected] => newgeneratedID
[success:protected] => 1
)
)
So I tried $response[0]->id to get the ID i need.
Now I get a fatal error.
PHP Fatal error: Cannot access protected property SaveResult::$id
I know it´s a noob question, but I don't get why I can print_r the object but not get the values inside.
You cannot use any of protected data from another space except the same object.
But you can edit the SaveResult object and add getter for id:
public function getId() {
return $this->id;
}
There ought to be a method you can call in the SaveResult class which lets you access the data, something like:
$response[0]->getId();
See the documentation/source code of the class.
You can read a protected property with the ReflectionProperty interface.
The HandyMan component from the phptoolcase library has a handy method to read inaccessible objects properties.
$value = PtcHandyMan::getProperty( $your_object , 'propertyName');
Static property from a singleton class:
$value = PtcHandyMan::getProperty( 'myCLassName' , 'propertyName');
Very simple and usefull, though it is only adviced in few situations as protected/private properties are shouldn't be used outside of their scope.
You can find the HandyMan class here: http://phptoolcase.com/guides/ptc-hm-guide.html
In java we have Object type which can be used to cast to specific class type.
How do we do this in PHP ?
Regards,
Mithun
Generic objects in PHP are instances of stdClass. However it is not a base class, meaning classes don't inherit from it unless you specify extends stdClass in the class declaration.
Typecasting something to (object) in PHP yields a stdClass. For example:
$a = array('foo' => 'bar');
$o = (object) $a;
var_dump($o instanceof stdClass); // bool(true)
var_dump($o->foo); // string(3) "bar"
In PHP there is no concept of upcasting and downcasting. You can type hint for superclasses or interfaces but that's about it. An object is always recognized as an instance of whatever class you construct it as, e.g. with new.
As someone with both php and Java experience, I can say that there is no equivalent in php to Java's object. In Java every object extends Object class, in php a class you make does not extend anything by default. The Java's Object has some convenient methods like toString(), hashCode(), getClass() and a few more that would not be relevant to php.
I like these standard methods in Java, they are very convenient for debugging and logging, so I miss then in php. That's why I usually create my own base class in php and make every class extend it. Then it becomes easy to log and debug, you can just $logger->log($obj);
and it will use magic __toString(), dumping at least basic info about the object.
The bottom line is that you can make your own base class in php and then just make every class extend it.
My usual base class:
/**
* Base class for all custom objects
* well, not really all, but
* many of them, especially
* the String and Array objects
*
* #author Dmitri Snytkine
*
*/
class BaseObject
{
/**
* Get unique hash code for the object
* This code uniquely identifies an object,
* even if 2 objects are of the same class
* and have exactly the same properties, they still
* are uniquely identified by php
*
* #return string
*/
public function hashCode()
{
return spl_object_hash($this);
}
/**
* Getter of the class name
* #return string the class name of this object
*/
public function getClass()
{
return get_class($this);
}
/**
* Outputs the name and uniqe code of this object
* #return string
*/
public function __toString()
{
return 'object of type: '.$this->getClass().' hashCode: '.$this->hashCode();
}
}
This would be stdClass (which is not a base class ftm).
Note that you can only typecast to stdClass not any other classes, e.g. this will work
$obj = (object) array( 'foo' => 'bar' );
but not
$observer = (Observer) new Subject;
Quoting the manual:
If an object is converted to an object, it is not modified. If a value of any other type is converted to an object, a new instance of the stdClass built-in class is created. If the value was NULL, the new instance will be empty. Arrays convert to an object with properties named by keys, and corresponding values. For any other value, a member variable named scalar will contain the value.
Well, unless you are willing to utilize black magic and unreliable hacks, such as those given in:
Cast the current object ($this) to a descendent class
Ciaran answer is helpful,
Despite what the other two answers
say, stdClass is not the base class
for objects in PHP. This can be
demonstrated fairly easily:
class Foo{}
$foo = new Foo();
echo ($foo instanceof stdClass)?'Yes':'No';
it outputs 'N' stdClass is instead just a
generic 'empty' class that's used when
casting other types to objects. I
don't believe there's a concept of a
base object in PHP
Since PHP does not have type declarations, there is no need for a global base class. There isn't really anything to do: just declare variables and use them.