FUDforum
Fast Uncompromising Discussions. FUDforum will get your users talking.

Home » Imported messages » comp.lang.php » out of sheer curiosity...
Show: Today's Messages :: Polls :: Message Navigator
Switch to threaded view of this topic Create a new topic Submit Reply
Re: out of sheer curiosity... [message #177566 is a reply to message #177562] Tue, 10 April 2012 00:25 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/9/2012 6:27 PM, Scott Johnson wrote:
> On 4/9/2012 2:03 PM, Thomas Mlynarczyk wrote:
>> Scott Johnson schrieb:
>>
>>> What would be the reason to serialize an object other then to save it
>>> for later use, and at the time I can't really come up with a reason
>>> for that in my mind (lack of experience in this area I suppose)
>>
>> True, this seems to be the most common use case: Make the object persist
>> between different HTTP requests.
>>

Scotty, please see my reply to Thomas. Only the state persists between
requests. The behavior doesn't. This is a huge difference.

>>> Now if you are saving it for later use then the original object would
>>> no longer exist and the external resources as Jerry explained would no
>>> longer be available if not for the constructor.
>>
>> The point is that an unserialized object would usually be in a different
>> state than a "fresh" object created using the `new` operator and thus
>> require different initialization tasks to be performed. That's why
>> different magic methods exist:
>>
>> __construct(): Object is "fresh", created using `new`
>> __clone(): Object was copied from another object
>> __wakeup(): Object was unserialized
>>
>> Greetings,
>> Thomas
>>
> OK I see.
>
> I had not even thought about the need for creating the object from
> either new or from a copied version.
>

Actually, both are quite common in true OO languages such as C++, Java
or Smalltalk.

> Thanks for squeezing my brain.
>
> Scotty


--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177568 is a reply to message #177564] Tue, 10 April 2012 08:05 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
Am 10.04.2012 02:17, schrieb Jerry Stuckle:
> On 4/9/2012 4:50 PM, Thomas Mlynarczyk wrote:
>
>> And this initialization is not needed (or might even prove harmful) when
>> the object is copied rather than created from scratch, because in that
>> case the initialization was already done on the original object and the
>> copy was thus created from an already initialized object and it will
>> "inherit" the initialized state. Instead, there are __clone() and
>> __wakeup() which replace __construct() and can do different
>> initialization tasks depending on how the object was created.
>>
>
> Initialization is NEVER harmful if it is done properly. That's the whole purpose of
> initialization!. wakeup() is NOT a constructor - any more than sleep() is a destructor.

'if done properly' fits everywhere and is just too true to be useful.

In PHP the constructor is called on an object without state (data). So you would
normally in the constructor just write out our data, like setting a counter to zero
or a date to the current time. This would be harmful to do on a 'not new' object.

Now PDO comes in. When getting a query result as object your constructor is called
*after* the properties are set.

I found it quite annoying to have an exception from the rule. But thinking more about
it I found out they had a choice of either calling __construct() after setting the
data, or to define another magic method like __pdoconstruct() to give the programmer
a chance to adapt the init process to the data.

Bottom line is: you just have to know your programming language very well, and test
everything thoroughly. Knowledge of OO principles help a lot, but are often too
general to be operational (like for example the "Open Close Principle").

/Str.
Re: out of sheer curiosity... [message #177571 is a reply to message #177565] Tue, 10 April 2012 10:43 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

> Objects NEVER persist between different HTTP requests. By definition,
> HTTP is a transactional environment and at the end of the request any
> objects are destroyed.

True. But since we do need objects to persist, we invent things like
sessions and serialization so our scripts can *pretend* they persist and
will never know the difference.

> Objects by definition have state and behavior. Only the state can
> persist between transactions; behavior never can - which is why objects
> need to be reconstructed.

Behaviour is "the methods". And they surely persist since the source
files are not destroyed after each request. All instances of a class
share the same methods, after all.

> Both __construct() and __clone() are types of constructors. __wakeup()
> is not (unless you consider sleep() to be a destructor - see above).

Why do you keep insisting that I must consider __sleep() to be a
destructor if I consider __wakeup() to be a constructor?

Consider:

1) __sleep() is called before the corresponding __wakeup() -- by your
logic this would mean the destructor is called before the constructor

2) __sleep() is called on a different object than the corresponding
__wakeup() -- so it cannot be the destructor corresponding to __wakeup()

3) __sleep() does not destroy anything. On the contrary, it helps to
preserve something. It is therefore not a destructor.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177572 is a reply to message #177566] Tue, 10 April 2012 10:48 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:
>>> True, this seems to be the most common use case: Make the object persist
>>> between different HTTP requests.
>
> Scotty, please see my reply to Thomas. Only the state persists between
> requests. The behavior doesn't. This is a huge difference.

Behaviour persists as long as you don't modify your script. The
behaviour is defined in the class and each instance uses that very same
behaviour.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177573 is a reply to message #177568] Tue, 10 April 2012 11:28 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
M. Strobel schrieb:

> Now PDO comes in. When getting a query result as object your constructor is called
> *after* the properties are set.

Really? That would be very strange indeed.

[minutes later]
I just tested it and it is indeed as you state. Thanks for pointing that
out -- is this documented?

> I found it quite annoying to have an exception from the rule. But thinking more about
> it I found out they had a choice of either calling __construct() after setting the
> data, or to define another magic method like __pdoconstruct() to give the programmer
> a chance to adapt the init process to the data.

I don't quite follow you here. Why did they have no choice? I don't see
why they (c|sh)ould not call the constructor before setting the data.
After all, that would be the only logical and sensible thing to do. If
you would do this "manually", you would do it like this:

foreach ( $rows as $row ):
$item = new MyClass( 'foo', 'bar' );
foreach ( $row as $name => $value ):
$item->$name = $value;
endforeach;
$result[] = $item;
endforeach;

And I guess it would be impossible to do it the other way round (first
setting data, then calling constructor). The setting of the data can be
controlled using the magic __set() method, so there's no need for
__pdoconstruct(), if I understand you correctly.

A more intelligent approach may have been to define an interface which
any "result row" class must implement and which defines a method like
setData( $rowAsArray ). Or maybe even better: make use of the existing
__set_state() magic method.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177574 is a reply to message #177564] Tue, 10 April 2012 11:44 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

> In OO terminology, the correct term is "constructor". I'm not familiar
> with Python, so I can't say what Python calls it. But the name is not
> as important as the job.

True. But one still has to keep in mind that the constructor is not
constructing the object, but initializing it.

> Initialization is NEVER harmful if it is done properly. That's the
> whole purpose of initialization!. wakeup() is NOT a constructor - any
> more than sleep() is a destructor.

You would have to take extra measures to prevent re-initializing an
already initialized object. Your constructor would need to detect what
type of initialization is required (freshly created by `new`, cloned or
unserialized). While certainly possible, this would be cumbersome.
Different magic initializers are clearly the better way to go.

> wakeup() is not a constructor. If you consider it a constructor, then
> you must also consider sleep() to be a destructor - in which case it
> would be illegal to call the destructor after calling sleep().

__wakeup() is an initializer, just like __construct() and __clone(). And
__sleep() is still not a destructor -- see my earlier post.

> It is the opposite of wakeup() - just like __construct() is the opposite
> of __destruct(). You can't have it both ways.

I think we do agree that __sleep() is not a destructor. And maybe we can
agree that __construct(), __clone() and __wakeup() all perform
initialization tasks and thus could be all called "initializers".

Greetings,
Thomas


--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177575 is a reply to message #177568] Tue, 10 April 2012 11:58 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 4:05 AM, M. Strobel wrote:
> Am 10.04.2012 02:17, schrieb Jerry Stuckle:
>> On 4/9/2012 4:50 PM, Thomas Mlynarczyk wrote:
>>
>>> And this initialization is not needed (or might even prove harmful) when
>>> the object is copied rather than created from scratch, because in that
>>> case the initialization was already done on the original object and the
>>> copy was thus created from an already initialized object and it will
>>> "inherit" the initialized state. Instead, there are __clone() and
>>> __wakeup() which replace __construct() and can do different
>>> initialization tasks depending on how the object was created.
>>>
>>
>> Initialization is NEVER harmful if it is done properly. That's the whole purpose of
>> initialization!. wakeup() is NOT a constructor - any more than sleep() is a destructor.
>
> 'if done properly' fits everywhere and is just too true to be useful.
>
> In PHP the constructor is called on an object without state (data). So you would
> normally in the constructor just write out our data, like setting a counter to zero
> or a date to the current time. This would be harmful to do on a 'not new' object.
>

But you are creating an object without state. When the object state is
serialized, by definition it is no longer an object because it has no
behavior.

You need to understand what an object is according to Object Oriented
principles. An object has both state and behavior - it has properties
and methods which act on those properties. The latter is not possible
in a serialized object.

And yes, you call the constructor when creating ANY object, even if the
object is being created from existing data.

Your understanding of object oriented principles shows you have never
read much about it nor have you use a true OO language.

> Now PDO comes in. When getting a query result as object your constructor is called
> *after* the properties are set.
>

And exactly how is that?

> I found it quite annoying to have an exception from the rule. But thinking more about
> it I found out they had a choice of either calling __construct() after setting the
> data, or to define another magic method like __pdoconstruct() to give the programmer
> a chance to adapt the init process to the data.
>

Another problem - you should NEVER call the constructor. True OO
languages do that for you as part of creating a new object. And you
never have to call the parent constructor, either.

PHP is sadly lacking as an OO language, that's for sure.

> Bottom line is: you just have to know your programming language very well, and test
> everything thoroughly. Knowledge of OO principles help a lot, but are often too
> general to be operational (like for example the "Open Close Principle").
>
> /Str.

Bottom line is - PHP's OO is sadly lacking, as it is in so many areas.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177577 is a reply to message #177574] Tue, 10 April 2012 12:04 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 7:44 AM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> In OO terminology, the correct term is "constructor". I'm not familiar
>> with Python, so I can't say what Python calls it. But the name is not
>> as important as the job.
>
> True. But one still has to keep in mind that the constructor is not
> constructing the object, but initializing it.
>

It does more than that. The system allocates memory for the object.
The constructor parcels out that memory into the appropriate pieces then
initializes those pieces. In truth, it does "construct" the object.

>> Initialization is NEVER harmful if it is done properly. That's the
>> whole purpose of initialization!. wakeup() is NOT a constructor - any
>> more than sleep() is a destructor.
>
> You would have to take extra measures to prevent re-initializing an
> already initialized object. Your constructor would need to detect what
> type of initialization is required (freshly created by `new`, cloned or
> unserialized). While certainly possible, this would be cumbersome.
> Different magic initializers are clearly the better way to go.
>

A serialized object is not an object. By definition, an object has both
state (properties) and behavior (methods operating on those properties).
A serialized object has only state - it is not an object.

True OO languages handle this quite well. But PHP can't seem to figure
that out. But then there are so many ways PHP is lacking.

>> wakeup() is not a constructor. If you consider it a constructor, then
>> you must also consider sleep() to be a destructor - in which case it
>> would be illegal to call the destructor after calling sleep().
>
> __wakeup() is an initializer, just like __construct() and __clone(). And
> __sleep() is still not a destructor -- see my earlier post.
>

__construct() and __clone() are constructors - a term specifically used
in OO terminology ("initializer" is not). Changing their name does not
change the facts.

>> It is the opposite of wakeup() - just like __construct() is the
>> opposite of __destruct(). You can't have it both ways.
>
> I think we do agree that __sleep() is not a destructor. And maybe we can
> agree that __construct(), __clone() and __wakeup() all perform
> initialization tasks and thus could be all called "initializers".
>
> Greetings,
> Thomas
>
>

I agree that __construct() and __clone() are constructors. There is no
"initializer" in OO terminology. Only "constructor".

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177578 is a reply to message #177572] Tue, 10 April 2012 12:06 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 6:48 AM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>>>> True, this seems to be the most common use case: Make the object
>>>> persist
>>>> between different HTTP requests.
>>
>> Scotty, please see my reply to Thomas. Only the state persists between
>> requests. The behavior doesn't. This is a huge difference.
>
> Behaviour persists as long as you don't modify your script. The
> behaviour is defined in the class and each instance uses that very same
> behaviour.
>
> Greetings,
> Thomas
>

No, a serialized object (or an object stored in a database) has only
state. The behavior doesn't exist until you create a new object from
that state.

A huge difference - and one real OO languages understand and handle.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177579 is a reply to message #177571] Tue, 10 April 2012 12:11 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 6:43 AM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> Objects NEVER persist between different HTTP requests. By definition,
>> HTTP is a transactional environment and at the end of the request any
>> objects are destroyed.
>
> True. But since we do need objects to persist, we invent things like
> sessions and serialization so our scripts can *pretend* they persist and
> will never know the difference.
>
>> Objects by definition have state and behavior. Only the state can
>> persist between transactions; behavior never can - which is why
>> objects need to be reconstructed.
>
> Behaviour is "the methods". And they surely persist since the source
> files are not destroyed after each request. All instances of a class
> share the same methods, after all.
>

No, you cannot use those methods to act on the data while it is
serialized, i.e. on disk or in a database. Only the state is present.

To use those methods, you need to create a new object using that state
data.

It is a huge difference which true OO languages handle just fine. Only
PHP seems to have a problem with it.


>> Both __construct() and __clone() are types of constructors. __wakeup()
>> is not (unless you consider sleep() to be a destructor - see above).
>
> Why do you keep insisting that I must consider __sleep() to be a
> destructor if I consider __wakeup() to be a constructor?
>
> Consider:
>
> 1) __sleep() is called before the corresponding __wakeup() -- by your
> logic this would mean the destructor is called before the constructor
>
> 2) __sleep() is called on a different object than the corresponding
> __wakeup() -- so it cannot be the destructor corresponding to __wakeup()
>
> 3) __sleep() does not destroy anything. On the contrary, it helps to
> preserve something. It is therefore not a destructor.
>
> Greetings,
> Thomas
>

If you are considering __wakeup() to be a constructor, then __sleep(),
being exactly the opposite, would be a destructor. (why do you think
they are called "sleep" and "wakeup" if the designers didn't consider
them to be opposites?).

And what you're saying is that the destructor (__sleep()) is called
after a constructor (__construct(), __clone() or __wakeup()).



--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177580 is a reply to message #177578] Tue, 10 April 2012 12:22 Go to previous messageGo to next message
Leonardo Azpurua is currently offline  Leonardo Azpurua
Messages: 46
Registered: December 2010
Karma: 0
Member
"Jerry Stuckle" <jstucklex(at)attglobal(dot)net> escribió en el mensaje
news:jm17o8$ngo$2(at)dont-email(dot)me...
> On 4/10/2012 6:48 AM, Thomas Mlynarczyk wrote:
>> Jerry Stuckle schrieb:
>>>> > True, this seems to be the most common use case: Make the object
>>>> > persist
>>>> > between different HTTP requests.
>>>
>>> Scotty, please see my reply to Thomas. Only the state persists between
>>> requests. The behavior doesn't. This is a huge difference.
>>
>> Behaviour persists as long as you don't modify your script. The
>> behaviour is defined in the class and each instance uses that very same
>> behaviour.
>>
>> Greetings,
>> Thomas
>>
>
> No, a serialized object (or an object stored in a database) has only
> state. The behavior doesn't exist until you create a new object from that
> state.
>
> A huge difference - and one real OO languages understand and handle.

Hi,

Behaviour is defined by the code within the class.

State is (shallowly) preserved by serialization.

It is the environment (a third factor that has to be taken into account)
what *may* be lost.

__wakeup should inspect the environment and ensure that all requirements are
met.

And, by the definition, __wakeup is a special case of constructor.

There is no need to get dogmatic about terms.

--
Re: out of sheer curiosity... [message #177583 is a reply to message #177575] Tue, 10 April 2012 15:04 Go to previous messageGo to next message
Tim Streater is currently offline  Tim Streater
Messages: 328
Registered: September 2010
Karma: 0
Senior Member
In article <jm178k$l6m$1(at)dont-email(dot)me>,
Jerry Stuckle <jstucklex(at)attglobal(dot)net> wrote:

> Another problem - you should NEVER call the constructor. True OO
> languages do that for you as part of creating a new object. And you
> never have to call the parent constructor, either.

AIUI, it does call the constructor - but not the parent constructor,
although you could do that yourself in the constructor if you so wished.

--
Tim

"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
Re: out of sheer curiosity... [message #177585 is a reply to message #177575] Tue, 10 April 2012 15:25 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

> But you are creating an object without state. When the object state is
> serialized, by definition it is no longer an object because it has no
> behavior.

class Foo { public $bar = 42; }
$foo = new Foo;
Now, $foo has state but no behaviour. According to you, $foo is not an
object?

Look, we are all aware that a serialized object is just a dead sequence
of characters representing the state of the object and that it can be
used -- together with the class definition -- to reconstruct an object
which, to the script, will appear to be identical to the original one.
Now if we just concentrate to what's essential for our script, we can
say that we "store away" the object in that sequence of characters and
retrieve it back from there. Simplification for convenience's sake.

>> Now PDO comes in. When getting a query result as object your
>> constructor is called
>> *after* the properties are set.
>
> And exactly how is that?

Just as he said. Didn't want to believe it. Wrote a test script. It's
true. When __construct() is called, the data is already set.

> Another problem - you should NEVER call the constructor.

But he doesn't! What makes you think he called the constructor?

[with true OO languages...]
> you never have to call the parent constructor, either.

I think that's a bad idea. First: there may be no need to call the
parent constructor (the child constructor may completely replace it).
Second: When should the parent constructor be called? Before? After? Or
maybe somewhere within the child constructor? It's much better and more
flexible when the child has to call the parent constructor explicitly.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177589 is a reply to message #177577] Tue, 10 April 2012 15:37 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

> But then there are so many ways PHP is lacking.

Finally a sentence I completely agree with ;-)

> __construct() and __clone() are constructors - a term specifically used
> in OO terminology ("initializer" is not). Changing their name does not
> change the facts.

True. And I am aware that "initializer" is not official terminology. I
used the word merely to better illustrate the purpose of those magic
methods.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177591 is a reply to message #177583] Tue, 10 April 2012 16:10 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 11:04 AM, Tim Streater wrote:
> In article <jm178k$l6m$1(at)dont-email(dot)me>,
> Jerry Stuckle <jstucklex(at)attglobal(dot)net> wrote:
>
>> Another problem - you should NEVER call the constructor. True OO
>> languages do that for you as part of creating a new object. And you
>> never have to call the parent constructor, either.
>
> AIUI, it does call the constructor - but not the parent constructor,
> although you could do that yourself in the constructor if you so wished.
>

Yes, but the parent is also an object, and the system should call the
constructor for you. Otherwise you may have an uninitialized parent.

That's how it works in OO languages - and it works quite well.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177592 is a reply to message #177579] Tue, 10 April 2012 16:15 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

> If you are considering __wakeup() to be a constructor, then __sleep(),
> being exactly the opposite, would be a destructor. (why do you think
> they are called "sleep" and "wakeup" if the designers didn't consider
> them to be opposites?).

They are opposites with respect to the process of serialization and may
be thought of as "to-do-before" and "to-do-after". And __sleep() is not
the exact opposite of __wakeup() -- the object is still awake after
__sleep() has been called and will continue to "work". You can have a
class defining both methods and still have only one of the two methods
called during the life time of the instance:

$foo = new Foo;
echo serialize( $foo );
// end of script
// __sleep() is called, but never __wakeup()

$string = '<manually created serialized representation of object>';
$foo = unserialize( $string );
// end of script
// __wakeup() is called, but never __sleep()

> And what you're saying is that the destructor (__sleep()) is called
> after a constructor (__construct(), __clone() or __wakeup()).

I said the exact opposite: __sleep() is called *before* the
corresponding __wakeup().

And look what the PHP manual has to say (emphasis mine):

<http://de2.php.net/manual/en/language.oop5.magic.php#object.wakeup>:
"Conversely, unserialize() checks for the presence of a function with
the magic name __wakeup(). If present, this function can *reconstruct*
any resources that the object may have."

(So __wakeup() is meant to "reconstruct" something, thus clearly acting
as a constructor.)

<http://de2.php.net/manual/en/class.serializable.php>
"Classes that implement this interface no longer support __sleep() and
__wakeup(). The method serialize is called whenever an instance needs to
be serialized. This does not invoke __destruct() or has any other side
effect unless programmed inside the method. When the data is
unserialized the class is known and the appropriate unserialize() method
is called as a *constructor* instead of calling __construct()."

(Clearly, unserialize() replaces __wakeup(), and if unserialize() acts
as a constructor, then so does __wakeup() which it replaces.)

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177593 is a reply to message #177585] Tue, 10 April 2012 16:16 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 11:25 AM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> But you are creating an object without state. When the object state is
>> serialized, by definition it is no longer an object because it has no
>> behavior.
>
> class Foo { public $bar = 42; }
> $foo = new Foo;
> Now, $foo has state but no behaviour. According to you, $foo is not an
> object?
>

If you created a constructor for it, the constructor will be called. If
you don't create your own, a dummy constructor is called, which does
nothing except satisfy the requirement a constructor is called.

> Look, we are all aware that a serialized object is just a dead sequence
> of characters representing the state of the object and that it can be
> used -- together with the class definition -- to reconstruct an object
> which, to the script, will appear to be identical to the original one.
> Now if we just concentrate to what's essential for our script, we can
> say that we "store away" the object in that sequence of characters and
> retrieve it back from there. Simplification for convenience's sake.
>

It is not an object once it has been serialized. To use it, you must
create an object with the deserialized data - which means a constructor
must be called according to OO principles.

>>> Now PDO comes in. When getting a query result as object your
>>> constructor is called
>>> *after* the properties are set.
>>
>> And exactly how is that?
>
> Just as he said. Didn't want to believe it. Wrote a test script. It's
> true. When __construct() is called, the data is already set.
>

OK, not a problem. It doesn't say the constructor must be called after
some properties are set. Just the constructor must be called when the
object is being created and before it is first used.

>> Another problem - you should NEVER call the constructor.
>
> But he doesn't! What makes you think he called the constructor?
>

You have to call a parent's constructor when constructing a child.

> [with true OO languages...]
>> you never have to call the parent constructor, either.
>
> I think that's a bad idea. First: there may be no need to call the
> parent constructor (the child constructor may completely replace it).
> Second: When should the parent constructor be called? Before? After? Or
> maybe somewhere within the child constructor? It's much better and more
> flexible when the child has to call the parent constructor explicitly.
>
> Greetings,
> Thomas
>

No, the child constructor NEVER replaces the parent constructor. The
child's constructor is responsible for creating the child object. The
parent's constructor is responsible for creating the parent object.

For instance, the child can never access private members of the parent
(encapsulation - one of the four attributes of OO languages).

And if the child needs to change the parent like that, you probably have
an invalid design. The child should always extend the parent - not
replace it.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177594 is a reply to message #177591] Tue, 10 April 2012 16:18 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

> Yes, but the parent is also an object, and the system should call the
> constructor for you. Otherwise you may have an uninitialized parent.

No. When you instantiate the child, then the child is an object, but
there is no instance of a "parent object".

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177595 is a reply to message #177589] Tue, 10 April 2012 16:19 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 11:37 AM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> But then there are so many ways PHP is lacking.
>
> Finally a sentence I completely agree with ;-)
>
>> __construct() and __clone() are constructors - a term specifically
>> used in OO terminology ("initializer" is not). Changing their name
>> does not change the facts.
>
> True. And I am aware that "initializer" is not official terminology. I
> used the word merely to better illustrate the purpose of those magic
> methods.
>
> Greetings,
> Thomas
>

But if you want to call it object oriented, you need to be using the
correct terminology. Here constructor and destructor have specific
meanings. Yes, one of the purposes (the main, many would argue,
including myself) is to initialize the object. But the term used is
constructor.

For instance, in other languages, part of the constructor's job might be
to dynamically allocate memory. That memory is not part of the original
memory allocated by new(), but it is part of the object. It is truly
"constructing" something, not just initializing it.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177596 is a reply to message #177580] Tue, 10 April 2012 16:20 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 8:22 AM, Leonardo Azpurua wrote:
> "Jerry Stuckle"<jstucklex(at)attglobal(dot)net> escribió en el mensaje
> news:jm17o8$ngo$2(at)dont-email(dot)me...
>> On 4/10/2012 6:48 AM, Thomas Mlynarczyk wrote:
>>> Jerry Stuckle schrieb:
>>>> >> True, this seems to be the most common use case: Make the object
>>>> >> persist
>>>> >> between different HTTP requests.
>>>>
>>>> Scotty, please see my reply to Thomas. Only the state persists between
>>>> requests. The behavior doesn't. This is a huge difference.
>>>
>>> Behaviour persists as long as you don't modify your script. The
>>> behaviour is defined in the class and each instance uses that very same
>>> behaviour.
>>>
>>> Greetings,
>>> Thomas
>>>
>>
>> No, a serialized object (or an object stored in a database) has only
>> state. The behavior doesn't exist until you create a new object from that
>> state.
>>
>> A huge difference - and one real OO languages understand and handle.
>
> Hi,
>
> Behaviour is defined by the code within the class.
>
> State is (shallowly) preserved by serialization.
>
> It is the environment (a third factor that has to be taken into account)
> what *may* be lost.
>
> __wakeup should inspect the environment and ensure that all requirements are
> met.
>
> And, by the definition, __wakeup is a special case of constructor.
>
> There is no need to get dogmatic about terms.
>
> --
>
>

If you want to call __wakeup() a constructor, then you need to call
__sleep() a destructor. You can't have it both ways.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177597 is a reply to message #177596] Tue, 10 April 2012 16:33 Go to previous messageGo to next message
Leonardo Azpurua is currently offline  Leonardo Azpurua
Messages: 46
Registered: December 2010
Karma: 0
Member
"Jerry Stuckle" <jstucklex(at)attglobal(dot)net> escribió en el mensaje
news:jm1mku$hqm$3(at)dont-email(dot)me...
>
> If you want to call __wakeup() a constructor, then you need to call
> __sleep() a destructor. You can't have it both ways.

Hi,

That would be if I had an obssesive love for symmetry, which is not the case
:-)

I don't care much about terms.

PHP lacks polymorphic constructors (a limitation which, after several years
using the best available OO practices with VB6, I can perfectly cope with).
So, if you need an alternate way to fill an object's data members, then
__wakeup seems to come in very handy.

With __construct(<args>), you initialize -i.e. fill data members and create
the appropriate internal states- the object from args.

With __wakeup you know you have your top level data members initialized
(from a previous state), so you have to rebuild the apropriate internal
states.

I have no problem at all with that. It may not be symmetric (but, again, who
cares?), but it is precisely documented and it works as expected (I guess,
since I have had no experience at all with PHP serialization).

--
Re: out of sheer curiosity... [message #177598 is a reply to message #177591] Tue, 10 April 2012 16:41 Go to previous messageGo to next message
Tim Streater is currently offline  Tim Streater
Messages: 328
Registered: September 2010
Karma: 0
Senior Member
In article <jm1m10$e7i$2(at)dont-email(dot)me>,
Jerry Stuckle <jstucklex(at)attglobal(dot)net> wrote:

> On 4/10/2012 11:04 AM, Tim Streater wrote:
>> In article <jm178k$l6m$1(at)dont-email(dot)me>,
>> Jerry Stuckle <jstucklex(at)attglobal(dot)net> wrote:
>>
>>> Another problem - you should NEVER call the constructor. True OO
>>> languages do that for you as part of creating a new object. And you
>>> never have to call the parent constructor, either.
>>
>> AIUI, it does call the constructor - but not the parent constructor,
>> although you could do that yourself in the constructor if you so wished.

> Yes, but the parent is also an object, and the system should call the
> constructor for you. Otherwise you may have an uninitialized parent.
>
> That's how it works in OO languages - and it works quite well.

OK. This essentially above my pay grade (but, then, everything is as I'm
retired :-)

--
Tim

"That excessive bail ought not to be required, nor excessive fines imposed,
nor cruel and unusual punishments inflicted" -- Bill of Rights 1689
Re: out of sheer curiosity... [message #177599 is a reply to message #177595] Tue, 10 April 2012 16:44 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

> But if you want to call it object oriented, you need to be using the
> correct terminology. Here constructor and destructor have specific
> meanings. Yes, one of the purposes (the main, many would argue,
> including myself) is to initialize the object. But the term used is
> constructor.

My using of the word "initializer" was merely meant to be illustrative
with respect to the purpose of __construct(), __clone() and __wakeup()
in PHP.

> For instance, in other languages, part of the constructor's job might be
> to dynamically allocate memory. That memory is not part of the original
> memory allocated by new(), but it is part of the object. It is truly
> "constructing" something, not just initializing it.

You are right, of course. I was considering only PHP.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177600 is a reply to message #177573] Tue, 10 April 2012 16:54 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
Am 10.04.2012 13:28, schrieb Thomas Mlynarczyk:
> M. Strobel schrieb:
>
>> Now PDO comes in. When getting a query result as object your constructor is called
>> *after* the properties are set.
>
> Really? That would be very strange indeed.
>
> [minutes later]
> I just tested it and it is indeed as you state. Thanks for pointing that out -- is
> this documented?
>
>> I found it quite annoying to have an exception from the rule. But thinking more about
>> it I found out they had a choice of either calling __construct() after setting the
>> data, or to define another magic method like __pdoconstruct() to give the programmer
>> a chance to adapt the init process to the data.
>
> I don't quite follow you here. Why did they have no choice? I don't see why they
> (c|sh)ould not call the constructor before setting the data. After all, that would be
> the only logical and sensible thing to do. If you would do this "manually", you would
> do it like this:
>
> foreach ( $rows as $row ):
> $item = new MyClass( 'foo', 'bar' );
> foreach ( $row as $name => $value ):
> $item->$name = $value;
> endforeach;
> $result[] = $item;
> endforeach;
>

Meanwhile I have more ideas about choices.

The correct way would have been to pass the row to the constructor. This would have
required a matching parameter definition for the constructor, and the corresponding
code, quite error prone.

In your example above the problem is if you need to do more init work on the data you
need an extra method call. With the implemented solution you just have to know that
the constructor is called after setting the vars, and you can detect it, testing the
unique key or so, but need not do so if you don't care.

> And I guess it would be impossible to do it the other way round (first setting data,
> then calling constructor). The setting of the data can be controlled using the magic
> __set() method, so there's no need for __pdoconstruct(), if I understand you correctly.

Are you aware of the fact that __set() is not called for defined variables? Test:
<?php
class Upset {
public $var1;
function __set($n, $v) {
echo "setting variable $n to: $v\n";
$this->$n = $v;
}
}
$c = new Upset();
$c->var1 = 'Try this';
$c->another = ' and this ';
echo "Values are now $c->var1 $c->another\n";
------------------- Result: ----
setting variable another to: and this
Values are now Try this and this


> A more intelligent approach may have been to define an interface which any "result
> row" class must implement and which defines a method like setData( $rowAsArray ). Or
> maybe even better: make use of the existing __set_state() magic method.

The rationale (or use case) of __set_state() is a mystery to me.

Maybe they did not want to ask too much from PHP programmers...

/Str.
Re: out of sheer curiosity... [message #177601 is a reply to message #177592] Tue, 10 April 2012 17:09 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
Am 10.04.2012 18:15, schrieb Thomas Mlynarczyk:
> Jerry Stuckle schrieb:
>
>> If you are considering __wakeup() to be a constructor, then __sleep(), being
>> exactly the opposite, would be a destructor. (why do you think they are called
>> "sleep" and "wakeup" if the designers didn't consider them to be opposites?).
>
> They are opposites with respect to the process of serialization and may be thought of
> as "to-do-before" and "to-do-after". And __sleep() is not the exact opposite of
> __wakeup() -- the object is still awake after __sleep() has been called and will
> continue to "work".

Good point, the object is still awake, that's why you get a destruct call at the end
of script.

> And look what the PHP manual has to say (emphasis mine):
>
> <http://de2.php.net/manual/en/language.oop5.magic.php#object.wakeup>:
> "Conversely, unserialize() checks for the presence of a function with the magic name
> __wakeup(). If present, this function can *reconstruct* any resources that the object
> may have."
>
> (So __wakeup() is meant to "reconstruct" something, thus clearly acting as a
> constructor.)
>
> <http://de2.php.net/manual/en/class.serializable.php>
> "Classes that implement this interface no longer support __sleep() and __wakeup().
> The method serialize is called whenever an instance needs to be serialized. This does
> not invoke __destruct() or has any other side effect unless programmed inside the
> method. When the data is unserialized the class is known and the appropriate
> unserialize() method is called as a *constructor* instead of calling __construct()."
>

And note the Note:

It is not possible for __sleep() to return names of private properties in parent
classes. (...) Instead you may use the Serializable interface.

But it is more work.

/Str.
Re: out of sheer curiosity... [message #177604 is a reply to message #177594] Tue, 10 April 2012 17:20 Go to previous messageGo to next message
The Natural Philosoph is currently offline  The Natural Philosoph
Messages: 993
Registered: September 2010
Karma: 0
Senior Member
Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> Yes, but the parent is also an object, and the system should call the
>> constructor for you. Otherwise you may have an uninitialized parent.
>
> No. When you instantiate the child, then the child is an object, but
> there is no instance of a "parent object".
>

Parthenogenesis?

;-)

> Greetings,
> Thomas
>


--
To people who know nothing, anything is possible.
To people who know too much, it is a sad fact
that they know how little is really possible -
and how hard it is to achieve it.
Re: out of sheer curiosity... [message #177605 is a reply to message #177604] Tue, 10 April 2012 17:31 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
Am 10.04.2012 19:20, schrieb The Natural Philosopher:
> Thomas Mlynarczyk wrote:
>> Jerry Stuckle schrieb:
>>
>>> Yes, but the parent is also an object, and the system should call the constructor
>>> for you. Otherwise you may have an uninitialized parent.
>>
>> No. When you instantiate the child, then the child is an object, but there is no
>> instance of a "parent object".
>>
>
> Parthenogenesis?
>
No, parent-child-identity. The concept of eternal live.

/Str.
Re: out of sheer curiosity... [message #177606 is a reply to message #177600] Tue, 10 April 2012 18:10 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
M. Strobel schrieb:

> In your example above the problem is if you need to do more init work on the data you
> need an extra method call. With the implemented solution you just have to know that
> the constructor is called after setting the vars, and you can detect it, testing the
> unique key or so, but need not do so if you don't care.

Hm, yes, but it still feels wrong to me that the constructor call is not
the very first thing happening to the object.

> Are you aware of the fact that __set() is not called for defined variables?

Yes, it's not called for defined /public/ variables. But you rarely have
public variables in your classes.

> The rationale (or use case) of __set_state() is a mystery to me.

Well, it's used by var_export() when exporting objects. For example,

$a = (object) array( 'foo' => 'bar' );

will be exported as

stdClass::__set_state(array( 'foo' => 'bar', ))

even though PHP should know very well that stdClass has no such static
method. Consequently, writing the output of var_export() to a file and
then re-including it, will fail, thus defeating the whole purpose of
var_export(). Test code:

$a = (object) array( 'foo' => 'bar' );
$s = var_export( $a, true );
var_dump( $a, $s );
$b = eval( "return $s;" );
var_dump( $b );

But __set_state() seems to be some sort of "factory method" which is
called as a static method on a class, passing an array with "state
information" and the method is supposed to create an object, set its
state using the passed array and return the new object. And that would
be exactly what PDO needs to set the data of the row object: no need to
define an array with extra constructor arguments -- just tell PDO the
class name and make sure the class has a __set_state() method defined.
But alas, it's not what PDO does.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177607 is a reply to message #177601] Tue, 10 April 2012 18:17 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
M. Strobel schrieb:

> It is not possible for __sleep() to return names of private properties in parent
> classes. (...) Instead you may use the Serializable interface.

I wish I could use __sleep() without having to return an array of
properties at all so I could just sing a lullaby to my object and let
serialize() serialize /all/ properties without having to specify them all.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177608 is a reply to message #177606] Tue, 10 April 2012 18:23 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
Am 10.04.2012 20:10, schrieb Thomas Mlynarczyk:
> M. Strobel schrieb:
>
>> In your example above the problem is if you need to do more init work on the data you
>> need an extra method call. With the implemented solution you just have to know that
>> the constructor is called after setting the vars, and you can detect it, testing the
>> unique key or so, but need not do so if you don't care.
>
> Hm, yes, but it still feels wrong to me that the constructor call is not the very
> first thing happening to the object.
>
>> Are you aware of the fact that __set() is not called for defined variables?
>
> Yes, it's not called for defined /public/ variables. But you rarely have public
> variables in your classes.
>
>> The rationale (or use case) of __set_state() is a mystery to me.
>
> Well, it's used by var_export() when exporting objects. For example,
>
> $a = (object) array( 'foo' => 'bar' );
>
> will be exported as
>
> stdClass::__set_state(array( 'foo' => 'bar', ))
>
> even though PHP should know very well that stdClass has no such static method.
> Consequently, writing the output of var_export() to a file and then re-including it,
> will fail, thus defeating the whole purpose of var_export(). Test code:
>
> $a = (object) array( 'foo' => 'bar' );
> $s = var_export( $a, true );
> var_dump( $a, $s );
> $b = eval( "return $s;" );
> var_dump( $b );
>
> But __set_state() seems to be some sort of "factory method" which is called as a
> static method on a class, passing an array with "state information" and the method is
> supposed to create an object, set its state using the passed array and return the new
> object. And that would be exactly what PDO needs to set the data of the row object:
> no need to define an array with extra constructor arguments -- just tell PDO the
> class name and make sure the class has a __set_state() method defined. But alas, it's
> not what PDO does.

Still a mystery, why should I want to do var_export()? And your code gives a fatal error.

<shrug> but it's late here, getting dark

/Str.
Re: out of sheer curiosity... [message #177609 is a reply to message #177607] Tue, 10 April 2012 18:25 Go to previous messageGo to next message
M. Strobel is currently offline  M. Strobel
Messages: 386
Registered: December 2011
Karma: 0
Senior Member
Am 10.04.2012 20:17, schrieb Thomas Mlynarczyk:
> M. Strobel schrieb:
>
>> It is not possible for __sleep() to return names of private properties in parent
>> classes. (...) Instead you may use the Serializable interface.
>
> I wish I could use __sleep() without having to return an array of properties at all
> so I could just sing a lullaby to my object and let serialize() serialize /all/
> properties without having to specify them all.

Omit _sleep(), and sing.

/Str.
Re: out of sheer curiosity... [message #177610 is a reply to message #177600] Tue, 10 April 2012 21:08 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 12:54 PM, M. Strobel wrote:
> Am 10.04.2012 13:28, schrieb Thomas Mlynarczyk:
>> M. Strobel schrieb:
>>
>>> Now PDO comes in. When getting a query result as object your constructor is called
>>> *after* the properties are set.
>>
>> Really? That would be very strange indeed.
>>
>> [minutes later]
>> I just tested it and it is indeed as you state. Thanks for pointing that out -- is
>> this documented?
>>
>>> I found it quite annoying to have an exception from the rule. But thinking more about
>>> it I found out they had a choice of either calling __construct() after setting the
>>> data, or to define another magic method like __pdoconstruct() to give the programmer
>>> a chance to adapt the init process to the data.
>>
>> I don't quite follow you here. Why did they have no choice? I don't see why they
>> (c|sh)ould not call the constructor before setting the data. After all, that would be
>> the only logical and sensible thing to do. If you would do this "manually", you would
>> do it like this:
>>
>> foreach ( $rows as $row ):
>> $item = new MyClass( 'foo', 'bar' );
>> foreach ( $row as $name => $value ):
>> $item->$name = $value;
>> endforeach;
>> $result[] = $item;
>> endforeach;
>>
>
> Meanwhile I have more ideas about choices.
>
> The correct way would have been to pass the row to the constructor. This would have
> required a matching parameter definition for the constructor, and the corresponding
> code, quite error prone.
>

Yes, that's how C++ does it, for instance (overloaded functions). It
would be harder in PHP, but it could be done.

> In your example above the problem is if you need to do more init work on the data you
> need an extra method call. With the implemented solution you just have to know that
> the constructor is called after setting the vars, and you can detect it, testing the
> unique key or so, but need not do so if you don't care.
>
>> And I guess it would be impossible to do it the other way round (first setting data,
>> then calling constructor). The setting of the data can be controlled using the magic
>> __set() method, so there's no need for __pdoconstruct(), if I understand you correctly.
>
> Are you aware of the fact that __set() is not called for defined variables? Test:
> <?php
> class Upset {
> public $var1;
> function __set($n, $v) {
> echo "setting variable $n to: $v\n";
> $this->$n = $v;
> }
> }
> $c = new Upset();
> $c->var1 = 'Try this';
> $c->another = ' and this ';
> echo "Values are now $c->var1 $c->another\n";
> ------------------- Result: ----
> setting variable another to: and this
> Values are now Try this and this
>
>

That is correct - you are directly setting a public variable. Now make
$var1 private and see what happens.

>> A more intelligent approach may have been to define an interface which any "result
>> row" class must implement and which defines a method like setData( $rowAsArray ). Or
>> maybe even better: make use of the existing __set_state() magic method.
>
> The rationale (or use case) of __set_state() is a mystery to me.
>
> Maybe they did not want to ask too much from PHP programmers...
>
> /Str.


--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177611 is a reply to message #177606] Tue, 10 April 2012 21:11 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 2:10 PM, Thomas Mlynarczyk wrote:
> M. Strobel schrieb:
>
>> In your example above the problem is if you need to do more init work
>> on the data you
>> need an extra method call. With the implemented solution you just have
>> to know that
>> the constructor is called after setting the vars, and you can detect
>> it, testing the
>> unique key or so, but need not do so if you don't care.
>
> Hm, yes, but it still feels wrong to me that the constructor call is not
> the very first thing happening to the object.
>

I agree that it "feels wrong", but is perfectly valid. There are other
examples - for instance in Java and C++, the vase class constructor is
called before the derived class constructor.

>> Are you aware of the fact that __set() is not called for defined
>> variables?
>
> Yes, it's not called for defined /public/ variables. But you rarely have
> public variables in your classes.
>
>> The rationale (or use case) of __set_state() is a mystery to me.
>
> Well, it's used by var_export() when exporting objects. For example,
>
> $a = (object) array( 'foo' => 'bar' );
>
> will be exported as
>
> stdClass::__set_state(array( 'foo' => 'bar', ))
>
> even though PHP should know very well that stdClass has no such static
> method. Consequently, writing the output of var_export() to a file and
> then re-including it, will fail, thus defeating the whole purpose of
> var_export(). Test code:
>
> $a = (object) array( 'foo' => 'bar' );
> $s = var_export( $a, true );
> var_dump( $a, $s );
> $b = eval( "return $s;" );
> var_dump( $b );
>
> But __set_state() seems to be some sort of "factory method" which is
> called as a static method on a class, passing an array with "state
> information" and the method is supposed to create an object, set its
> state using the passed array and return the new object. And that would
> be exactly what PDO needs to set the data of the row object: no need to
> define an array with extra constructor arguments -- just tell PDO the
> class name and make sure the class has a __set_state() method defined.
> But alas, it's not what PDO does.
>
> Greetings,
> Thomas
>

Possibly for future use? Most of PDO was written before __set_state()
was added, so maybe newer versions will use it.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177612 is a reply to message #177608] Tue, 10 April 2012 21:17 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
M. Strobel schrieb:

> Still a mystery, why should I want to do var_export()?

I recently had a use for it: Reading some data from an external source
and creating a PHP file like this:

<?php return array( ... lots ... of ... data ... ); ?>

so I could later retrieve the data with

$data = include $datafile;

I thought var_export() would be the simplest way to do this. But the
array contained stdclass objects and var_export() fails on them :-(
(I ended up running str_replace() over the string returned by
var_export() to change the stdClass::__set_state to (object).

> And your code gives a fatal error.

Exactly. Because var_export(), although supposed to produce valid PHP
code, fails to do so.

> <shrug> but it's late here, getting dark

Yeah, here too.

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177613 is a reply to message #177594] Tue, 10 April 2012 21:20 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 12:18 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> Yes, but the parent is also an object, and the system should call the
>> constructor for you. Otherwise you may have an uninitialized parent.
>
> No. When you instantiate the child, then the child is an object, but
> there is no instance of a "parent object".
>
> Greetings,
> Thomas
>

Although not a separate entity, the parent is still considered an
object. You can, for instance, call public methods which are defined in
the parent but not the child. Those methods will operate on the parent,
just as if you had a parent object.

So basically what you have is "dual identity" - the object is considered
both a parent and a child, depending on the context.

And the parent's constructor is responsible for constructing the parent
object; the child is only responsible for constructing the child object.

This is actually quite important. This allows you to change the
implementation (code and private variables) of the parent object without
affecting any child objects.

Remember that the child object always has a parent object; the opposite
is not necessarily true, and the parent object should not depend on
anything in the child (abstract classes are a special case - but even
then the parent should never depend on anything in the child).

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177614 is a reply to message #177609] Tue, 10 April 2012 21:21 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
M. Strobel schrieb:

>> I wish I could use __sleep() without having to return an array of properties at all
>> so I could just sing a lullaby to my object and let serialize() serialize /all/
>> properties without having to specify them all.
>
> Omit _sleep(), and sing.

// SCNR
while ( !asleep() ) { $sheep++; }

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177615 is a reply to message #177599] Tue, 10 April 2012 21:23 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 12:44 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> But if you want to call it object oriented, you need to be using the
>> correct terminology. Here constructor and destructor have specific
>> meanings. Yes, one of the purposes (the main, many would argue,
>> including myself) is to initialize the object. But the term used is
>> constructor.
>
> My using of the word "initializer" was merely meant to be illustrative
> with respect to the purpose of __construct(), __clone() and __wakeup()
> in PHP.
>
>> For instance, in other languages, part of the constructor's job might
>> be to dynamically allocate memory. That memory is not part of the
>> original memory allocated by new(), but it is part of the object. It
>> is truly "constructing" something, not just initializing it.
>
> You are right, of course. I was considering only PHP.
>
> Greetings,
> Thomas
>

But OO is language-insensitive. OO only defines a methodology, and the
requirements to implement that methodology. It does not define *how*
the methodology is implemented. That's up to the language.

I see PHP is trying to become more OO. However, due to the poor
"design" it has suffered from the start, there are a lot of things
holding it back.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177616 is a reply to message #177597] Tue, 10 April 2012 21:28 Go to previous messageGo to next message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 12:33 PM, Leonardo Azpurua wrote:
> "Jerry Stuckle"<jstucklex(at)attglobal(dot)net> escribió en el mensaje
> news:jm1mku$hqm$3(at)dont-email(dot)me...
>>
>> If you want to call __wakeup() a constructor, then you need to call
>> __sleep() a destructor. You can't have it both ways.
>
> Hi,
>
> That would be if I had an obssesive love for symmetry, which is not the case
> :-)
>
> I don't care much about terms.
>
> PHP lacks polymorphic constructors (a limitation which, after several years
> using the best available OO practices with VB6, I can perfectly cope with).
> So, if you need an alternate way to fill an object's data members, then
> __wakeup seems to come in very handy.
>
> With __construct(<args>), you initialize -i.e. fill data members and create
> the appropriate internal states- the object from args.
>
> With __wakeup you know you have your top level data members initialized
> (from a previous state), so you have to rebuild the apropriate internal
> states.
>
> I have no problem at all with that. It may not be symmetric (but, again, who
> cares?), but it is precisely documented and it works as expected (I guess,
> since I have had no experience at all with PHP serialization).
>
> --
>
>

Because it's a violation of OO concepts? It's caused me problems more
than once. I no longer even try to store objects in the session. It's
hopeless.

For instance - what if one of the things your object needs is a database
connection? And what if you have several objects using that same
connection? There is no way to pass an existing database connection to
__wakeup(). You either have to use a global variable, restricting
variable names in the rest of your code and limiting flexibility, or
create a new connection in the __wakeup() call or remember to call
another method to set the database connection after unserializing the
object.

None are good answers - but all could be easily handled with proper use
of constructors.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Re: out of sheer curiosity... [message #177617 is a reply to message #177611] Tue, 10 April 2012 21:30 Go to previous messageGo to next message
Thomas Mlynarczyk is currently offline  Thomas Mlynarczyk
Messages: 131
Registered: September 2010
Karma: 0
Senior Member
Jerry Stuckle schrieb:

[setting data on object before constructor is called]
> I agree that it "feels wrong", but is perfectly valid. There are other
> examples - for instance in Java and C++, the vase class constructor is
> called before the derived class constructor.

The base constructor, okay, yes. But setting data on the object,
possibly invoking __set() which, in turn might (need to) do things
requiring prior object initialization?

[PDO does not use __set_state()]
> Possibly for future use? Most of PDO was written before __set_state()
> was added, so maybe newer versions will use it.

Hm, maybe. Meanwhile I think I can live with the fact that the
constructor is called after setting the data. It's just something one
must know and remember...

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)
Re: out of sheer curiosity... [message #177618 is a reply to message #177592] Tue, 10 April 2012 21:34 Go to previous messageGo to previous message
Jerry Stuckle is currently offline  Jerry Stuckle
Messages: 2598
Registered: September 2010
Karma: 0
Senior Member
On 4/10/2012 12:15 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> If you are considering __wakeup() to be a constructor, then __sleep(),
>> being exactly the opposite, would be a destructor. (why do you think
>> they are called "sleep" and "wakeup" if the designers didn't consider
>> them to be opposites?).
>
> They are opposites with respect to the process of serialization and may
> be thought of as "to-do-before" and "to-do-after". And __sleep() is not
> the exact opposite of __wakeup() -- the object is still awake after
> __sleep() has been called and will continue to "work". You can have a
> class defining both methods and still have only one of the two methods
> called during the life time of the instance:
>
> $foo = new Foo;
> echo serialize( $foo );
> // end of script
> // __sleep() is called, but never __wakeup()
>
> $string = '<manually created serialized representation of object>';
> $foo = unserialize( $string );
> // end of script
> // __wakeup() is called, but never __sleep()
>
>> And what you're saying is that the destructor (__sleep()) is called
>> after a constructor (__construct(), __clone() or __wakeup()).
>
> I said the exact opposite: __sleep() is called *before* the
> corresponding __wakeup().
>

I know you did. And I said __sleep() is called after the constructor.
It can also be called after __wakeup(), i.e. if an unserialized object
is serialized again.

> And look what the PHP manual has to say (emphasis mine):
>
> <http://de2.php.net/manual/en/language.oop5.magic.php#object.wakeup>:
> "Conversely, unserialize() checks for the presence of a function with
> the magic name __wakeup(). If present, this function can *reconstruct*
> any resources that the object may have."
>
> (So __wakeup() is meant to "reconstruct" something, thus clearly acting
> as a constructor.)
>

OK, now - one of the members of the object is a reference to a database
connection object. How are you going to set that in your __wakeup() call?

Yes, I know what the PHP manual says. But it's also pretty obvious that
those who wrote the manual are the same ones who created the language.

Thanks, I'll go with recognized OO experts when discussing how OO works
- not the PHP folks.

> <http://de2.php.net/manual/en/class.serializable.php>
> "Classes that implement this interface no longer support __sleep() and
> __wakeup(). The method serialize is called whenever an instance needs to
> be serialized. This does not invoke __destruct() or has any other side
> effect unless programmed inside the method. When the data is
> unserialized the class is known and the appropriate unserialize() method
> is called as a *constructor* instead of calling __construct()."
>
> (Clearly, unserialize() replaces __wakeup(), and if unserialize() acts
> as a constructor, then so does __wakeup() which it replaces.)
>
> Greetings,
> Thomas
>

My statement stands for a database object with the unserialize() method.

If either followed the OO rules for constructing an object, this would
not be a problem.

--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstucklex(at)attglobal(dot)net
==================
Pages (3): [ «    1  2  3    »]  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: 5.4 windows installer.
Next Topic: Does PHP5 treat $_SERVER['PHP_AUTH_USER']) differently?
Goto Forum:
  

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ]

Current Time: Thu Nov 28 06:04:33 GMT 2024

Total time taken to generate the page: 0.03162 seconds