Link to home
Start Free TrialLog in
Avatar of rgb192
rgb192Flag for United States of America

asked on

typecasting to an object

what is the difference between


$test_object = (object) array(
  'hello' => 'world',
  'nested' => array('key'=>'value'),
);


and
$test_object = (object) 12345;



I modified code to show both
echo '<h2>Testing typecasting to an object</h2>';
$test_object = (object) array(
  'hello' => 'world',
  'nested' => array('key'=>'value'),
);
echo '<tt><pre>'.var_export($test_object,TRUE).'</pre></tt>';

echo '<h2>Testing typecasting to an object scaler</h2>';
$test_object = (object) 12345;
echo '<tt><pre>'.var_export($test_object,TRUE).'</pre></tt>';

Open in new window





output

Testing typecasting to an object
stdClass::__set_state(array(
   'hello' => 'world',
   'nested' =>
  array (
    'key' => 'value',
  ),
))
Testing typecasting to an object scaler
stdClass::__set_state(array(
   'scalar' => 12345,
))




3 minute lynda.com tutorial transcript
00:00	In this chapter, I'm going to explore built-in PHP objects.
00:04	I'll start with the standard class, which is pretty generic,
00:07	then demonstrate how to get objects from the database.
00:10	We'll handle errors in an object-oriented way, then customize them to meet our needs.
00:14	Let's start with the standard class.
00:16	A standard class is a generic class that can be created by typecasting a value
00:20	as an object, like casting the string "hello, world" as an object.
00:24	It won't have any methods, but it will have values.
00:27	In case you were wondering, if you typecast an object to an object, that's kind of
00:31	goofy, and nothing will happen.
00:34	If you typecast that array to an object, the result will be an object with
00:37	properties named for the keys to the array, with values corresponding to the array values.
00:43	Let's clean up the demo, and remove the cloning tests.
00:46	Create a test standard class object out of a nested array.
00:51	Echo <h2> Testing typecasting to an object>.
01:01	$test_object = (object). This is the typecasting. array. hello as the key and
01:10	world as the value. Then nested as an array ( 'key => value').
01:24	Then, debug the test object.
01:29	Save, then refresh your browser.
01:33	The result will be a standard class with properties "hello" and "nested," with nested
01:37	containing an array.
01:39	If I was to typecast any other data type like a string, the value would be
01:43	converted to a standard object, with one property named scalar.
01:47	Return to the demo, and replace the array definition with the number 12345. Save, and refresh.
02:00	The test object now has one property, scalar, with the value 12345.
02:07	Standard class objects are practically used in a number of ways.
02:10	For example, returning a defined data structure with fixed branches without nesting.
02:16	Sometimes, it's used as a shorthand to speed code development, as it takes less
02:20	characters to access a property than it does to specify a key.
02:24	Finally, you can use a standard object when interacting with a method that is
02:28	looking for an object with particular properties, but isn't actually
02:31	checking for the class.
02:33	In the next video, I will show you how to load objects directly from the
02:37	database, then intelligently load addresses from the database into the
02:40	correct class.

Open in new window

Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

What do you actually need to know?

Casting to an object does exactly that - takes one type and makes it work like an object. In the case of the array the elements become properties that can be accessed (using your example) like so

$test_object->hello
But the nested array would still be an array
$test->object->nested['key'];

In the second example the casting to an object of a scaler results in an object being created with a single property called scalar with the value of 12345 in this case.

The text describes this quite clearly though as well as explaining why you would want to do this - hence my opening question of what you are looking for as an answer?

The code below demonstrates identical output from casting to object vs declaring as an object to begin with
<?php
$test_object = (object) array(
  'hello' => 'world',
  'nested' => array('key'=>'value'),
);
echo '<pre>';
print_r($test_object);
echo '</pre>';

class myObject {
    public $hello;
    public $nested;
    function __construct($hello, $nested)
    {
        $this->hello = $hello;
        $this->nested = $nested;
    }
}
$test_object = new myObject('World', array('key' => 'value'));
echo '<pre>';
print_r($test_object);
echo '</pre>';

class myOtherObject {
    public $scalar;

    function __construct($scalar)
    {
         $this->scalar = $scalar;
    }
}

$test_object = new myOtherObject(12345);
echo '<pre>';
print_r($test_object);
echo '</pre>';

$test_object = (object) 12345;
echo '<pre>';
print_r($test_object);
echo '</pre>';
?>

Open in new window

Historically, PHP is a loosely typed language.  This means that data types can (sometimes) assume different forms, depending on the context in which they are used.  For example, a string containing digits can be used as a string or as a number, depending on whether you want to write it into a data base, or use it in a computation.  This is part of PHP's funhouse history of trying to be the "easiest" language.  Refs here:
http://php.net/manual/en/language.types.php
http://php.net/manual/en/language.types.type-juggling.php
http://php.net/manual/en/types.comparisons.php

As computer science tries to bring some engineering principles into play, object oriented programming has been brought forth with the goal of allowing programmers to build something that is a reusable component.  For better or worse, OOP does not always play well with PHP's free and easy variable definitions.  Some kinds of automatic typecasting just don't make sense in the OOP environment, and now PHP programmers have to think about data types.  (Non-PHP programmers always had to think about data types, so this should not be seen as a burden.)

Complex data types, including arrays and objects are a little more difficult to pigeon-hole when you're trying to do automatic typecasting, and PHP does a stupefyingly bad job here.  What if you try to echo  a number?  You get a string.  But what if you try to echo an object?  PHP echo will try to convert the object to a string and will sometimes succeed or sometimes fail, creating a run-time situation that is a time bomb.  The only thing you don't know is when she will blow.  To try to bring some structure into the typecasting of objects as strings, PHP has introduced the magic method __toString() which is great, but is not always enforced by the language.  When programming languages do not enforce language requirements, programmers tend to make mistakes that create run-time errors.

The difference in addressing data in arrays and objects is frequently nothing more than syntax.  Arrays require you to write quotes and brackets; object properties use -> and do not require quotes and brackets.  For this reason alone, I find it easier to retrieve data base rows with fetch_object() methods.  And if you want to use HEREDOC notation for templating your HTML, the OO notation works better than the quoted array notation.

When you cast a PHP variable to an object via (object) PHP creates an instance of the built-in empty class, stdClass.  This class does not play well with echo.  When you try to echo an array, you get the word, "Array."  Neither result makes sense in the logic of trying to create human-usable output from an internal data structure.  So the programmer has to come up with something that shows the data from the array or object.  And that necessarily means the programmer has to think about the type of the variable and write programming accordingly.

Run this to see what's happening.

<?php // RAY_temp_rgb192.php
ini_set('display_errors', TRUE);
error_reporting(E_ALL);
echo '<pre>';


// SEE http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_28232334.html


// CREATE ARRAY AND OBJECT CAST FROM ARRAY
$test_arr = array(
  'hello' => 'world',
  'nested' => array('key'=>'value'),
);

$test_obj = (object) array(
  'hello' => 'world',
  'nested' => array('key'=>'value'),
);

// SHOW THE COMPLEX VARIABLES
var_dump($test_arr);
var_dump($test_obj);

// SHOW HOW TO ADDRESS AN ELEMENT OF THE ARRAY
echo $test_arr['hello'];

// SHOW HOW TO ADDRESS A PROPERTY OF THE OBJECT
echo $test_obj->hello;

// SHOW WHAT HAPPENS WHEN YOU ECHO THE ARRAY AND OBJECT
echo $test_arr;
echo $test_obj;

Open in new window

Avatar of rgb192

ASKER

Ray's answer:

from your explanation, echoing array is always 'ARRAY'
but why

echo $test_arr;
echo $test_obj;

and why cant object be echoed causing error
Catchable fatal error:  Object of class stdClass could not be converted to string in C:\wamp\www\oop_examples\ray-typcast.php on line 33

is there any way to try and catch object error
or how else to print the array and object
Avatar of rgb192

ASKER

julianH:

I do not understand the difference between the two classes.

is one an object class and the other a scaler class


and
'World', array('key' => 'value')
passed in the class

versus
$scalar
For testing purposes, you can (and should) use var_dump() to print out any variable.  It will tell you the type, length, etc., and it will explore the data recursively.

The problem with PHP echo is that it was created a long time ago, before much thought was given to PHP arrays or any thought was given to PHP objects.  The problem with PHP arrays is that instead of creating a fatal error when you try to typecast them inappropriately, a years-ago decision was made to return the word Array.  Design mistake?  Probably.

I think you can extend the stdClass to add a __toString() method, but I've never tried it.  You would probably need to instantiate an object from the new class.  I would not expect typecasting to create an instance of anything other than the stdClass.

You can use try/catch with catchable errors.
Footnote: scalar != scaler
hello, , you ask -"I do not understand the difference between the two classes., , , is one an object class and the other a scaler class"

But this question can NOT be answered, as YOU have decided that there are two different classes called "object class" and   "scaler class", but there is NO distinction or terminology or way to talk about your "object class" and   "scaler class", because these do not exist anywhere.

A short answer for your question for -
$object1 = (object) array( 'one' => 'hello',  'two' => "world",);
$object2 = (object) 12345;

is that Both of these produce an Object, not a Class, both of these make objects ($object1 , $object2) that are from the SAME CLASS definition the default PHP stdClass.

I doubt that my next explanation will mean much to you, BUT, PHP has little error control for typecasting as (object), instead, it will just add the "Default" property name of "scalar" to a default object creation of PHP stdClass using the property value for whatever is behind the (object) declaration, but WHY you ask? ?, because there absolutely has to be a property name for any property in an Object, since there is NO PROPERTY NAME Given in this -
$object2 = (object) 'This is a Value, but I do not have any Property Name';
PHP just uses the text of "scalar" for the property name, even though it makes no sense, but I guess it is a good of text name as any other? But It HAS TO USE SOMETHING for the PROPERTY NAME!

OK if you use an araay
$object1 = (object) array( 'one' => 'hello',  'two' => "world");
with KEY and Value, then PHP has something to use as a Property NAME AND a Property VALUE, so the "scalar"  is NOT used for this, but PHP is using the SAME method for for typecasting as (object) with BOTH OF THESE, with the information available during the typecasting as (object).
You can do var_export($test_object,TRUE)  or var_dump()  all day long, and it will not help you to understand what typecasting is doing, untill you understand some of the PHP method of typecasting as (object).

It may be for most developers, that  typecasting as (object), is NOT VERY USEFUL.
@Slick812:
It may be for most developers, that  typecasting as (object), is NOT VERY USEFUL.
Agreed.  I have never seen a professional programmer do that!  And I just scanned my teaching example library.  I have over 1/2 million lines of examples.  Not one of them contains (object) until I did it today to test the idea!

I do not understand the difference between the two classes.
is one an object class and the other a scaler class

No - both are objects - a scalar is just a value like an int - denoting a simple type.

When casting a scalar (non-complex type) to an object PHP creates a class for you with a property called scalar set to the value of the variable you cast.

When you cast a complex type like an array to an object then PHP creates an object with properties matching the names of the elements in the complex type.

For example
<?php
$ctype = array("a"=>1, "b" => 2, "c" => 3);
$cobj = (object)$ctype;
echo "<pre>";
print_r($cobj);
echo "</pre>";
echo $cobj->a;
?>
However contstast that with
<?php
$ctype = array(1, 2, 3);
$cobj = (object)$ctype;
echo "<pre>";
print_r($cobj);
echo "</pre>";
echo $cobj->a;
?>
PHP will create the object for you but you won't be able to access the values in the array unless you cast it back again

The point being - cast should be used only when it adds value - and thought must be given to how it is used.
The requirement for a property name is not really a requirement, as this code example shows.  You can still use iterators to access the anonymous properties.  But in real life, nobody would ever do anything like this!  There is almost never any situation in which it makes sense to take a simple data structure and make it into a more complicated data structure, so just don't do that.

<?php
error_reporting(E_ALL);
echo "<pre>";

// CREATE AN ASSOCIATIVE ARRAY AND CAST IT AS AN OBJECT
$ctype = array("a"=>1, "b" => 2, "c" => 3);
$cobj = (object)$ctype;
var_dump($cobj);

// ECHO ONE OF THE PROPERTIES
echo PHP_EOL . "OBJECT PROPERTY 'a' CONTAINS: " . $cobj->a;
echo PHP_EOL;

// OVERWRITE THE VARIABLE WITH A NUMERICALLY INDEXED ARRAY AND CAST IT TO OBJECT
$ctype = array(1, 2, 3);
$cobj = (object)$ctype;
var_dump($cobj);

// OBVIOUSLY, THIS IS NOW AN UNDEFINED VARIABLE
echo $cobj->a;

// USE AN ITERATOR TO ACCESS THE ANONYMOUS PROPERTIES
foreach ($cobj as $key => $val)
{
    echo PHP_EOL . "KEY $key POINTS TO VAL $val";
}
echo PHP_EOL;

// CAST SOMETHING ELSE USELESS
$thing = (object)FALSE;
var_dump($thing);

// IS THIS TRUE OR FALSE?
if ($thing) echo PHP_EOL . "GOTCHA" . PHP_EOL;

// CAST A FLOATING POINT NUMBER AS AN OBJECT
$thing = (object)3.1416;
var_dump($thing);

// CAST AN OBJECT AS AN OBJECT
$thing = (object)$thing;
var_dump($thing);

Open in new window

Avatar of rgb192

ASKER

Julian:
second part of code
echo $cobj->a;
I tried
echo $cobj->1;

how could I echo variables?

Ray:

// OBVIOUSLY, THIS IS NOW AN UNDEFINED VARIABLE
echo $cobj->a;

is this a defined variable?
echo $cobj['a'];

Slick812:

is that Both of these produce an Object, not a Class, both of these make objects ($object1 , $object2) that are from the SAME CLASS definition the default PHP stdClass.

I do not understand how these are from the same class.
Have both these objects been instantiated?
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of rgb192

ASKER

thanks for typecasting object array information