Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

out of sheer curiosity...

15 views
Skip to first unread message

Leonardo Azpurua

unread,
Mar 27, 2012, 1:01:10 PM3/27/12
to
Is there any good reason for not implementing the dot as a member selector
for objects?

i.e. instead of $object->memberFunction(...), just
$object.memberFunction(...)

Jumping back and forth between javaScript and PHP (which I guess is a common
situation for PHP developers) makes it easy to use dots when arrows should
be used, and viceversa.

Regards.

--


"Álvaro G. Vicario"

unread,
Mar 27, 2012, 1:06:43 PM3/27/12
to
El 27/03/2012 19:01, Leonardo Azpurua escribió/wrote:
> Is there any good reason for not implementing the dot as a member selector
> for objects?

Because it's already the concatenation operator:

>
> i.e. instead of $object->memberFunction(...), just
> $object.memberFunction(...)

... and will break backwards compatibility at syntax level:

<?php

function memberFunction(){
return 'Hi!';
}

class Foo{
public function __toString(){
return '(foo)';
}
}

$object = new Foo;
echo $object.memberFunction(); // We are concatenating!



--
-- http://alvaro.es - Álvaro G. Vicario - Burgos, Spain
-- Mi sitio sobre programación web: http://borrame.com
-- Mi web de humor satinado: http://www.demogracia.com
--

Leonardo Azpurua

unread,
Mar 27, 2012, 1:34:38 PM3/27/12
to
(slapping my own forehead) Of course!

The __toString() thing was also useful.

I whish I had time to read the manual from cover to cover.


Thanks.


""Álvaro G. Vicario"" <alvaro.NO...@demogracia.com.invalid> escribió
en el mensaje news:jkss34$trc$1...@dont-email.me...

Thomas 'PointedEars' Lahn

unread,
Mar 28, 2012, 3:12:24 PM3/28/12
to
Leonardo Azpurua wrote:

> Is there any good reason for not implementing the dot as a member selector
> for objects?

Perhaps to have a separate operator for string concatenation?

> i.e. instead of $object->memberFunction(...), just
> $object.memberFunction(...)
>
> Jumping back and forth between javaScript and PHP (which I guess is a
> common situation for PHP developers)

There is no `javaScript'. [1a, 1b] However, you may have observed that
(barring String and Array methods) you need to use the `+' operator both for
addition and string concatenation in ECMAScript implementations [2].
Because those languages are loosely and dynamically typed [3], that has
turned out to be a disadvantage as it is a frequent problem (not only for
beginners) there, especially with calculation in Web forms (where all
control values are strings [4]). In PHP you get implicit conversion to a
numeric type with the `+' operator, and implicit conversion to string with
the `.' operator. [5] In PHP, '1' + 2 will never result in '12' as it will
in ECMAScript.

In order to complement Java [6, 7], Netscape JavaScript needed to be Java-
like; PHP did not. So only with the former, the `.' punctuator was already
taken for property access. That propagated from JavaScript 1.1 (at the
latest) to Microsoft JScript 1.0, therefore to the ECMAScript Language
Specification whose first edition was based on both languages [8], and
naturally to later ECMAScript implementations.

> makes it easy to use dots when arrows should be used, and viceversa.

Programming becomes a lot easier when you accept the fact that there are
different programming languages with different syntaxes and sets of
paradigms that are supported. Do not try (as a programmer) to make one
programming look or work like another; try to leverage the advantages of
each programming language instead.

Indeed, with PHP code and code written in/for ECMAScript implementations
often being used in the same file but *usually* executed in different
runtime environments (PHP: server-side; ECMAScript implementations: client-
side), and supporting by default different sets of programming paradigms and
inheritance types (PHP: procedural-imperative, object-oriented with class-
based inheritance, partially functional¹; ECMAScript implementations:
procedural-imperative, object-oriented with prototype-based inheritance,
fully functional¹) it is good that their syntax does not look the same, as
the different syntax is helpful in telling them apart.


HTH

PointedEars
___________
¹ supporting lambda calculus, like e.g. Lisp or Haskell

References:

[1a] Lahn, Thomas (2011-08-21). ECMAScript Support Matrix.
<http://PointedEars.de/scripts/test/es-matrix/>.
[1b] Lahn, Thomas (2012). Features von ECMAScript-basierten
Programmiersprachen – Eine vergleichende Analyse. BSc SUPSI.
Fernfachhochschule Schweiz (FFHS).
[2] Ecma International (2011-06). Standard ECMA-262. ECMAScript Language
Specification. 5.1 Edition.
<http://www.ecma-international.org/publications/files/
ECMA-ST/Ecma-262.pdf> (accessed 2011-08-27). Section 11.6.1.
[3] ibid., section 8.
[4] World Wide Web Consortium (2003). Document Object Model (DOM) Level
2 HTML Specification. Version 1.0. Appendix D: ECMAScript Language
Binding.
<http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html>
(accessed 2012-03-28).
[5] The PHP Documentation Group (2012). PHP Manual. Operators.
<http://php.net/operators> (accessed 2012-03-28).
[6] Krill, Paul (2008-06-23). „JavaScript creator ponders past, future“.
In: InfoWorld. Developer World.
<http://www.infoworld.com/d/developer-world/
javascript-creator-ponders-past-future-704> (accessed 2011-12-22).
[7] Hamilton, Naomi (2008-07-31). „The A-Z of Programming Languages:
JavaScript“. In: Computerworld. The A-Z of Programming Languages.
<http://www.computerworld.com.au/article/255293/a-z_programming_
languages_javascript/> (accessed 2011-12-31).
[8] Ecma International (June 1997). Standard ECMA-262 – ECMAScript: A
general-purpose, cross-platform programming language.
<http://www.mozilla.org/js/language/E262.pdf (accessed 2003-12-15).
p. 2.
--
When all you know is jQuery, every problem looks $(olvable).

Leonardo Azpurua

unread,
Mar 28, 2012, 8:53:34 PM3/28/12
to

"Thomas 'PointedEars' Lahn" <Point...@web.de> escribió en el mensaje
news:17777949....@PointedEars.de...
> Programming becomes a lot easier when you accept the fact that there are
> different programming languages with different syntaxes and sets of
> paradigms that are supported. Do not try (as a programmer) to make one
> programming look or work like another; try to leverage the advantages of
> each programming language instead.

Good explanation and best advice.

Thanks!

--


M. Strobel

unread,
Mar 29, 2012, 4:00:47 AM3/29/12
to
Yes, this was truly an article.

Next problem (or assignment) is to understand the supported paradigms, and how to use
them to meet your requirements.

I think of the - real or felt? - large ignorance of OO programming in PHP.

/Str.

Leonardo Azpurua

unread,
Mar 29, 2012, 5:53:42 AM3/29/12
to

"M. Strobel" <sorry_no_...@nowhere.dee> escribió en el mensaje
news:9tij5f...@mid.uni-berlin.de...

> Yes, this was truly an article.
>
> Next problem (or assignment) is to understand the supported paradigms,
> and how to use them to meet your requirements.
>
> I think of the - real or felt? - large ignorance of OO programming in PHP.


Probably felt.

I mean, I am ignorant of much of PHP. But its support for OOP is quite
standard: single inheritance, interfaces, private, public and protected
visibility, abstract vs. concrete classes and methods. The "magic methods"
which I just discovered thanks to Alvaro Vicario's response to my original
post are sort of "idiosincratic", but perfectly understandable. It lacks
operator overloading (which I have never actually used) and signature based
overloading (which might come handy, but would probably conflict with the
dynamic nature of PHP function calls, which I certainly prefer).

I have been using (crippled) OO languages for the last couple of decades,
and my analisys and design methods are purely OO.

My ignorance of PHP is absolute, not just OO related.

--


The Natural Philosopher

unread,
Mar 29, 2012, 6:46:22 AM3/29/12
to
Leonardo Azpurua wrote:
> "M. Strobel" <sorry_no_...@nowhere.dee> escribi� en el mensaje
Do you know, I don't even know when my analysis and design methods are
OO and when they are not.

Its just another way of doing things and I let my understanding of the
problem guide me, not a set of arbitrary rules.

I dont use OOP languages, because having read up on them extensively
when they first appeared I simply thought 'oh, ok, I see where they are
coming from' and incorporated a few ideas about how code and data should
be organised in pseudo object form, and moved on. The benefits are in
the way of looking at things, not enforcing a set of strictures on
programming. Especially when many coding problems do not lend themselves
to those strictures.

(and almost all of the problems to which PHP is the natural language of
choice do not benefit from OOP. If a web site is the application each
php 'page' is an object in its own right..anyway. Neither are
microprocessors in the end object oriented. Object orientation stresses
the structure of data, whereas procedural coding stresses the way in
which processing is carried out.)




> My ignorance of PHP is absolute, not just OO related.
>
> --
>
>


--
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.

M. Strobel

unread,
Mar 29, 2012, 8:02:11 AM3/29/12
to
This is exactly what I mean: how does the OO concept help me?

You could compare it maybe to languages: there is the passive and the active
knowledge, passive means you understand (some), active means you talk (some).
Understanding what someone says is far easier than saying it yourself.

You must get to talk OO - or whatever the concept is. I only learned talking OO after
attending some Java courses, and I already had 10 years of IT experience then.

/Str.


Erwin Moller

unread,
Mar 29, 2012, 8:33:07 AM3/29/12
to
On 3/29/2012 12:46 PM, The Natural Philosopher wrote:
> Leonardo Azpurua wrote:
>> "M. Strobel" <sorry_no_...@nowhere.dee> escribi� en el mensaje
>> news:9tij5f...@mid.uni-berlin.de...
>>
>>> Yes, this was truly an article.
>>>
>>> Next problem (or assignment) is to understand the supported paradigms,
>>> and how to use them to meet your requirements.
>>>
>>> I think of the - real or felt? - large ignorance of OO programming in
>>> PHP.
>>
>>
>> Probably felt.
>>
>> I mean, I am ignorant of much of PHP. But its support for OOP is quite
>> standard: single inheritance, interfaces, private, public and
>> protected visibility, abstract vs. concrete classes and methods. The
>> "magic methods" which I just discovered thanks to Alvaro Vicario's
>> response to my original post are sort of "idiosincratic", but
>> perfectly understandable. It lacks operator overloading (which I have
>> never actually used) and signature based overloading (which might come
>> handy, but would probably conflict with the dynamic nature of PHP
>> function calls, which I certainly prefer).
>>
>> I have been using (crippled) OO languages for the last couple of
>> decades, and my analisys and design methods are purely OO.
>>
>
> Do you know, I don't even know when my analysis and design methods are
> OO and when they are not.

Erm... seriously TNP?

Hint: If you use words like 'class' and 'new' you are typically in OO.
If you use functions outside a class you are typically procedural.

I think you know.


>
> Its just another way of doing things and I let my understanding of the
> problem guide me, not a set of arbitrary rules.

As it should!

But what 'rules' are you referring to?

PHP's OO is pretty straightforward.
I think they did a decent job implementing OO.(php 5 that is)

Creating smart classes is up to the programmer.
I am not aware of any extra 'rules'.

Are you maybe referring to all kinds of design patterns scattered around
the web?
(In which case I tend to agree, because implementing other people's
solutions can take the fun out of programming. But reading them never
hurts. And when you agree to a certain approach you can even decide to
follow it yourself. It is all up to you, the programmer.)

>
> I dont use OOP languages, because having read up on them extensively
> when they first appeared I simply thought 'oh, ok, I see where they are
> coming from' and incorporated a few ideas about how code and data should
> be organised in pseudo object form, and moved on. The benefits are in
> the way of looking at things, not enforcing a set of strictures on
> programming. Especially when many coding problems do not lend themselves
> to those strictures.

True, but also a truism.
"If a certain problem is unfit for OO approach, it is unfit for OO
approach."

But even then, OO often won't hurt too much either.
You can simply use your procedural logic in OO too.
I worked like that in Java when I started learning the language, until I
discovered how idiotic I was. All part of the learning curve. :-)


>
> (and almost all of the problems to which PHP is the natural language of
> choice do not benefit from OOP. If a web site is the application each
> php 'page' is an object in its own right..anyway.

True for a simple plain webpage, but when you have something more
complex OO can certainly help.
Most (all?) modern MVC software are at least partly OO, simply because
it makes things easier to organize.

With OO you don't have to drag all the information around to each
function that (might) need it. And scope is better organized: more
intuitive.

OO makes things easier to organize, that's all, but it DOESN'T define
how to solve your problem at hand.



> Neither are
> microprocessors in the end object oriented. Object orientation stresses
> the structure of data, whereas procedural coding stresses the way in
> which processing is carried out.)

Both true, but I don't think that the exact implementation on some
microprocessor is relevant for >99% of all programmers.

Most programmers have no clue how to code directly for a cpu.
The last microprocessor I coded directly was the 6502.
I have NO IDEA how to code for my current quadcode, and I don't care either.

We have compilers and interpreters and bytecode and what's more to solve
that.
Programmers focus on the task at hand, often in a high level language.
And OO is a very fine addition.
Give it another try one day. :-)


Regards,
Erwin Moller



--
"That which can be asserted without evidence, can be dismissed without
evidence."
-- Christopher Hitchens

The Natural Philosopher

unread,
Mar 29, 2012, 9:37:40 AM3/29/12
to
Oh I use it now and again when forced to - not in PHP because its never
been necessary or helpful for the sort of projects I want to code in php
at all.

Its has its place more in designing C++ GUI apps. But even there huge
chunks have to be written in procedural code. Even if that code is
wrapped as an object..

In short you can code without an OOP language, but you cant code without
a procedural one, even if its only machine code.

And if you cant at least envisage how your code maps to a register set
and program counter and stack - well no wonder the world is full of
bloatware.





> Regards,
> Erwin Moller

Jerry Stuckle

unread,
Mar 29, 2012, 9:39:32 AM3/29/12
to
You forget who you're talking to, Erwin. TNP is not a programmer, both
by his own admission and by his posts here. It doesn't surprise me he
doesn't think OO is any good. I knew a guy like that when I worked for
IBM back in '90. He "read a book about it and didn't see any advantage
in it". But then he wasn't a programmer, either.

>
>>
>> Its just another way of doing things and I let my understanding of the
>> problem guide me, not a set of arbitrary rules.
>
> As it should!
>
> But what 'rules' are you referring to?
>
> PHP's OO is pretty straightforward.
> I think they did a decent job implementing OO.(php 5 that is)
>
> Creating smart classes is up to the programmer.
> I am not aware of any extra 'rules'.
>
> Are you maybe referring to all kinds of design patterns scattered around
> the web?
> (In which case I tend to agree, because implementing other people's
> solutions can take the fun out of programming. But reading them never
> hurts. And when you agree to a certain approach you can even decide to
> follow it yourself. It is all up to you, the programmer.)
>

Any rules TNP doesn't bother to understand are "arbitrary" in his mind.
He doesn't even like having to follow PHP syntax rules - as he has
also said in the past.

But I disagree that PHP 5's implementation of OO is decent. I think
it's half-assed at best. Truly written by people who have no
understanding of OO. But then that can be said of a lot of PHP.

>>
>> I dont use OOP languages, because having read up on them extensively
>> when they first appeared I simply thought 'oh, ok, I see where they are
>> coming from' and incorporated a few ideas about how code and data should
>> be organised in pseudo object form, and moved on. The benefits are in
>> the way of looking at things, not enforcing a set of strictures on
>> programming. Especially when many coding problems do not lend themselves
>> to those strictures.
>
> True, but also a truism.
> "If a certain problem is unfit for OO approach, it is unfit for OO
> approach."
>
> But even then, OO often won't hurt too much either.
> You can simply use your procedural logic in OO too.
> I worked like that in Java when I started learning the language, until I
> discovered how idiotic I was. All part of the learning curve. :-)
>

I agree - I've seen some things which work better using a procedural
approach. But I've also found the more complicated something gets, the
more appropriate an OO approach becomes.

It's like designing a soap box derby racer vs. an SUV. I'd build a kids
racer out of raw materials. It's small, simple and relatively easy.
However, do you think car manufacturers do it this way? Or do they take
an engine from one model, modify the body style from another, etc.? And
if they don't have the right engine, do they design that as part of the
car? Or do they specify the dimensions, mounting, etc. and separately
design the engine to that specification?

No, they don't have to do it that way - they could design each piece
from the bottom up. And then if they change the seats from bench to
bucket, they might find an interdependency and have to also change spark
plugs.

>
>>
>> (and almost all of the problems to which PHP is the natural language of
>> choice do not benefit from OOP. If a web site is the application each
>> php 'page' is an object in its own right..anyway.
>
> True for a simple plain webpage, but when you have something more
> complex OO can certainly help.
> Most (all?) modern MVC software are at least partly OO, simply because
> it makes things easier to organize.
>

No, a page is not an object. A page is closer to a transactional
application. For instance, the page cannot be reused in another page
without modifications. Objects can.

> With OO you don't have to drag all the information around to each
> function that (might) need it. And scope is better organized: more
> intuitive.
>
> OO makes things easier to organize, that's all, but it DOESN'T define
> how to solve your problem at hand.
>
>

Very true.

>
>> Neither are
>> microprocessors in the end object oriented. Object orientation stresses
>> the structure of data, whereas procedural coding stresses the way in
>> which processing is carried out.)
>
> Both true, but I don't think that the exact implementation on some
> microprocessor is relevant for >99% of all programmers.
>

That's because if it isn't good for microprocessors, it must not be good
for anything, according to TNP.

> Most programmers have no clue how to code directly for a cpu.
> The last microprocessor I coded directly was the 6502.
> I have NO IDEA how to code for my current quadcode, and I don't care
> either.
>
> We have compilers and interpreters and bytecode and what's more to solve
> that.
> Programmers focus on the task at hand, often in a high level language.
> And OO is a very fine addition.
> Give it another try one day. :-)
>

I can code Intel processors - I started back in '82 when the typical PC
had 64K or 128K of RAM (and slow). We needed to do some stuff in 808x
assembler. I still do a little as a hobby (mainly to keep up with it),
but I don't go down to the OS level.

>
> Regards,
> Erwin Moller
>
>
>


--
==================
Remove the "x" from my email address
Jerry Stuckle
JDS Computer Training Corp.
jstu...@attglobal.net
==================

Erwin Moller

unread,
Mar 29, 2012, 9:59:38 AM3/29/12
to
On 3/29/2012 3:37 PM, The Natural Philosopher wrote:

<snip>

> Its has its place more in designing C++ GUI apps. But even there huge
> chunks have to be written in procedural code. Even if that code is
> wrapped as an object..
>

Let's go 100% off topic. ;-)

Just curious (that was also the original subject of this thread): How
do you write GUI with C++?
I am studying C++ right now (for hobby) and I mainly looking into QT
because it targets both *nix and Windows.

Erwin Moller

unread,
Mar 29, 2012, 10:21:52 AM3/29/12
to
On 3/29/2012 3:39 PM, Jerry Stuckle wrote:
> On 3/29/2012 8:33 AM, Erwin Moller wrote:
>> On 3/29/2012 12:46 PM, The Natural Philosopher wrote:

<snip>

>>> Its just another way of doing things and I let my understanding of the
>>> problem guide me, not a set of arbitrary rules.
>>
>> As it should!
>>
>> But what 'rules' are you referring to?
>>
>> PHP's OO is pretty straightforward.
>> I think they did a decent job implementing OO.(php 5 that is)
>>
>> Creating smart classes is up to the programmer.
>> I am not aware of any extra 'rules'.
>>
>> Are you maybe referring to all kinds of design patterns scattered around
>> the web?
>> (In which case I tend to agree, because implementing other people's
>> solutions can take the fun out of programming. But reading them never
>> hurts. And when you agree to a certain approach you can even decide to
>> follow it yourself. It is all up to you, the programmer.)
>>
>
> Any rules TNP doesn't bother to understand are "arbitrary" in his mind.
> He doesn't even like having to follow PHP syntax rules - as he has also
> said in the past.
>
> But I disagree that PHP 5's implementation of OO is decent. I think it's
> half-assed at best. Truly written by people who have no understanding of
> OO. But then that can be said of a lot of PHP.
>

Jerry,

What are your main objections to the PHP5's OO approach?

For myself: I must say I love its simplicity.
(Simplicity is a Good Thing in my opinion.)



<snip>

>> But even then, OO often won't hurt too much either.
>> You can simply use your procedural logic in OO too.
>> I worked like that in Java when I started learning the language, until I
>> discovered how idiotic I was. All part of the learning curve. :-)
>>
>
> I agree - I've seen some things which work better using a procedural
> approach. But I've also found the more complicated something gets, the
> more appropriate an OO approach becomes.
>

Exactly. :-)

<snip>

>>>
>>> (and almost all of the problems to which PHP is the natural language of
>>> choice do not benefit from OOP. If a web site is the application each
>>> php 'page' is an object in its own right..anyway.
>>
>> True for a simple plain webpage, but when you have something more
>> complex OO can certainly help.
>> Most (all?) modern MVC software are at least partly OO, simply because
>> it makes things easier to organize.
>>
>
> No, a page is not an object. A page is closer to a transactional
> application. For instance, the page cannot be reused in another page
> without modifications. Objects can.
>

No, of course a page is not an object in the OO meaning.
I was referring to using OO to help building the page.

I wonder: one might defend that storing serialized objects in a session
is object persistence, and that a page is hence also part of it because
it is coupled via sess_id to that object.
Nah.. too farfetched.
(And I never store objects in a session anymore: not worth the trouble
in my opinion.)

<snip>

>
> I can code Intel processors - I started back in '82 when the typical PC
> had 64K or 128K of RAM (and slow). We needed to do some stuff in 808x
> assembler. I still do a little as a hobby (mainly to keep up with it),
> but I don't go down to the OS level.
>

Nice!
And I feel like a relic now with my 6502 hands-on experience. ;-)

The Natural Philosopher

unread,
Mar 29, 2012, 12:58:05 PM3/29/12
to
Erwin Moller wrote:
> On 3/29/2012 3:37 PM, The Natural Philosopher wrote:
>
> <snip>
>
>> Its has its place more in designing C++ GUI apps. But even there huge
>> chunks have to be written in procedural code. Even if that code is
>> wrapped as an object..
>>
>
> Let's go 100% off topic. ;-)
>
> Just curious (that was also the original subject of this thread): How
> do you write GUI with C++?
> I am studying C++ right now (for hobby) and I mainly looking into QT
> because it targets both *nix and Windows.
>

I am using the GTK toolkit.

Because what I wanted to do would be on a gnomeish platform, and its teh
easy way to do that.

I think a windows version exists.

But its more of an adventure in design than a serious project at this time.

The Natural Philosopher

unread,
Mar 29, 2012, 1:09:31 PM3/29/12
to
It is an object in that its self contained .. and doesn't extend into
other pages. Its data is self contained.


> I wonder: one might defend that storing serialized objects in a session
> is object persistence, and that a page is hence also part of it because
> it is coupled via sess_id to that object.
> Nah.. too farfetched.
> (And I never store objects in a session anymore: not worth the trouble
> in my opinion.)
>

No. Its simpler to generate your own cookie, use that to id the
transaction and store everything else elsewhere. Typically a database.


> <snip>
>
>>
>> I can code Intel processors - I started back in '82 when the typical PC
>> had 64K or 128K of RAM (and slow). We needed to do some stuff in 808x
>> assembler. I still do a little as a hobby (mainly to keep up with it),
>> but I don't go down to the OS level.
>>
>
> Nice!
> And I feel like a relic now with my 6502 hands-on experience. ;-)
>
I've coded 8080, z80, 8088, 8086 and 6809.. after that it was mostly
done in C...

C is just qa faster way to write quality assembler.

Once you step into the arena of garbage collection, invisible memory
manipulation and start hiding the actual realities of the machine from
the language you end up with the possibility of really bad bloated code
and seriously crap performance.

I.e. basically what the modern user application is characterised by.



> Regards,
> Erwin Moller

Jerry Stuckle

unread,
Mar 29, 2012, 4:11:09 PM3/29/12
to
Well, to start with, the lack of function overloading. It is quite a
good feature to be able to overload functions - especially constructors.
And because of that, you have to run through all kinds of hoops when
doing things like storing an object in the $_SESSION.

Even then it doesn't work. When you store an object in the $_SESSION,
the object's destructor is called at the end of the script, but on the
next script the constructor is never called. A direct violation of OO
principles.

Inheritance is also screwed up. You should never have to call the
constructor of the parent object from your child's constructor. It
should be automatic.

Polymorphism works half-assed, but again you need to run through hoops.
For instance, base class has static method "foo". It also calls
static method "bar". Derived class also has method "bar". If you call
derived::foo(), you will end up calling Base::bar() instead of
Derived::bar(). They fixed this in 5.3 by forcing (yet another!) use of
the keyword static - instead of making the code work transparently.

There are all kinds of similar things in PHP. But that's not really
that surprising to me.

>
> <snip>
>
>>>>
>>>> (and almost all of the problems to which PHP is the natural language of
>>>> choice do not benefit from OOP. If a web site is the application each
>>>> php 'page' is an object in its own right..anyway.
>>>
>>> True for a simple plain webpage, but when you have something more
>>> complex OO can certainly help.
>>> Most (all?) modern MVC software are at least partly OO, simply because
>>> it makes things easier to organize.
>>>
>>
>> No, a page is not an object. A page is closer to a transactional
>> application. For instance, the page cannot be reused in another page
>> without modifications. Objects can.
>>
>
> No, of course a page is not an object in the OO meaning.
> I was referring to using OO to help building the page.
>
> I wonder: one might defend that storing serialized objects in a session
> is object persistence, and that a page is hence also part of it because
> it is coupled via sess_id to that object.
> Nah.. too farfetched.
> (And I never store objects in a session anymore: not worth the trouble
> in my opinion.)
>
> <snip>
>

Storing the object in the $_SESSION is object persistence. But that
doesn't make the page itself an object in the OO sense, any more than MS
Word is an object because you can store a document on disk for later
retrieval.

And I agree about storing objects in the session (see above). But that
also means even more hoops you have to run through to store and retrieve
your object.

>>
>> I can code Intel processors - I started back in '82 when the typical PC
>> had 64K or 128K of RAM (and slow). We needed to do some stuff in 808x
>> assembler. I still do a little as a hobby (mainly to keep up with it),
>> but I don't go down to the OS level.
>>
>
> Nice!
> And I feel like a relic now with my 6502 hands-on experience. ;-)
>
> Regards,
> Erwin Moller
>

I should add, I never did any 6502. I did some 6800 back around 1980 or
so, and have done lots of IBM Mainframe assembler (and even a fair
amount of machine code - their instruction set makes it relatively
easy). But never had the opportunity to do anything on the 6502.

I have mixed feelings about assembler. It's nice when you need the
speed and/or memory, but those aren't so much of a problem nowadays.
But it really is a bear to try to do anything more than adding a couple
of registers together :)
Message has been deleted
Message has been deleted

M. Strobel

unread,
Mar 29, 2012, 5:43:18 PM3/29/12
to
Am 29.03.2012 23:07, schrieb Tim Streater:
> In article <jl250b$lkq$1...@news.albasani.net>,
> The Natural Philosopher <t...@invalid.invalid> wrote:
>
>> Erwin Moller wrote:
>
>> > Nice!
>> > And I feel like a relic now with my 6502 hands-on experience. ;-)
>> > I've coded 8080, z80, 8088, 8086 and 6809.. after that it was mostly done in C...
>
> I found I could do a decent job on the 7090 and Sigma7, and a very decent job on the
> 68000. 6502/Z80/8080 were simple but hard to do very much with. I avoided the x86.
> The IBM/360 definitely had the worst I've ever seen. PDP-11 and VAX were quite good.

I did a lot in /370 assembler, and it really has a different paradigma: no stack, but
15 registers which was a lot at that time.

No problem, I wrote a FORTH on it.

Which brings us back to the subject: make best use of what your environment has to
offer. The environment today has more to offer than assembler.

/Str.

Jerry Stuckle

unread,
Mar 29, 2012, 7:29:04 PM3/29/12
to
On 3/29/2012 5:01 PM, Tim Streater wrote:
> In article <jl2fl0$v97$1...@dont-email.me>,
> Jerry Stuckle <jstu...@attglobal.net> wrote:
>
>> On 29/3/2012 10:21 AM, Erwin Moller wrote:
>
>> > What are your main objections to the PHP5's OO approach?
>> >
>> > For myself: I must say I love its simplicity.
>> > (Simplicity is a Good Thing in my opinion.)
>
>> Well, to start with, the lack of function overloading. It is quite a
>> good feature to be able to overload functions - especially
>> constructors. And because of that, you have to run through all kinds
>> of hoops when doing things like storing an object in the $_SESSION.
>
> [snip other reasons]
>
> You brought any of this up on the PHP mailing lists?
>

It's been brought up so many times it isn't even funny, and some of it
in the bugs list.

I do not have a lot of respect for those in charge of PHP. Just because
they can program an interpreter does not mean they can design a
language. And PHP is proof of that.

The Natural Philosopher

unread,
Mar 29, 2012, 11:52:06 PM3/29/12
to
Tim Streater wrote:
> In article <jl250b$lkq$1...@news.albasani.net>,
> The Natural Philosopher <t...@invalid.invalid> wrote:
>
>> Erwin Moller wrote:
>
>> > Nice!
>> > And I feel like a relic now with my 6502 hands-on experience. ;-)
>> > I've coded 8080, z80, 8088, 8086 and 6809.. after that it was mostly
>> done in C...
>
> I found I could do a decent job on the 7090 and Sigma7, and a very
> decent job on the 68000. 6502/Z80/8080 were simple but hard to do very
> much with. I avoided the x86. The IBM/360 definitely had the worst I've
> ever seen. PDP-11 and VAX were quite good.
>
>> C is just a faster way to write quality assembler.
>
> While this is true, there are times when machine code is unavoidable.
>
of course. mostly when actually zapping hardware. Unless your C library
has specific hardware access stuff. And interrupt routine hooks.

M. Strobel

unread,
Apr 8, 2012, 4:50:06 PM4/8/12
to
Works fine here. Test script:
#!/usr/local/bin/php
<?php

class C1 {
public $var1 = 'M.';
public $var2 = 'Strobel';
function __construct() {
echo "\t--> call ". __METHOD__.PHP_EOL;
}
function __destruct() {
echo "\t--> call ". __METHOD__.PHP_EOL;
}
function __sleep() {
echo "\t--> call ". __METHOD__.PHP_EOL;
return array('var1','var2');
}
function __wakeup() {
echo "\t--> call ". __METHOD__.PHP_EOL;
}
} // end class C1

echo "----- creating class\n";
$c = new C1;
echo "----- serializing class\n";
$ser = serialize($c);
echo "----- deserializing class\n";
$cc = unserialize($ser);
echo "----- deleting first class\n";
unset($c);
echo "----- deleting unserialized class\n";
unset($cc);
exit(0);
#-----------------------

Result:
strobel@s114-intel:~/projekte/PHP> ./magicmethods.php
----- creating class
--> call C1::__construct
----- serializing class
--> call C1::__sleep
----- deserializing class
--> call C1::__wakeup
----- deleting first class
--> call C1::__destruct
----- deleting unserialized class
--> call C1::__destruct

What exactly did you criticize?

/Str.

Jerry Stuckle

unread,
Apr 8, 2012, 5:15:00 PM4/8/12
to
Look at it again. You have two destructor calls but only one
constructor call. A direct violation of OO principles.

And BTW - I said nothing about serializing.

You really do need to learn to read.

M. Strobel

unread,
Apr 8, 2012, 6:39:57 PM4/8/12
to
No evasions, get to the point. I have one explicit constructor, and one wakeup which
is a constructor.

What did you talk about if not about serializing?

/Str.

The Natural Philosopher

unread,
Apr 8, 2012, 7:59:02 PM4/8/12
to
c'mon. Jerry just cut and pasted something he read somewhere.

Its not as if he understood what he was posting. Go easy on the poor old
chap.

Jerry Stuckle

unread,
Apr 8, 2012, 8:24:51 PM4/8/12
to
I know a one-to-one correspondence is very difficult for someone of your
(lack of) intellect to understand, but I'll try again anyway.

You have these calls:
--> call C1::__construct

That's ONE call to a constructor.


--> call C1::__destruct
--> call C1::__destruct

That's TWO calls to destructors. IOW, an object was constructed without
calling a constructor. This is a direct violation of OO principals (all
objects must have exactly one constructor call and one destructor call).

And ONE does not equal TWO. wakeup() is not a constructor, any more
than sleep() is a destructor (and if sleep() were a destructor, then you
would see a call to sleep() and a call to the destructor).

And I was referring to storing in a session, not serializing the data, i.e.

$_SESSION['stupid'] = $idiot;

Jerry Stuckle

unread,
Apr 8, 2012, 8:28:05 PM4/8/12
to
Ah, the biggest troll on Usenet once again shows just how stoopid he is.
He refuses to use his real name because he doesn't want everyone to
know he's neither a programmer or the electrical engineer he claims to
be. He's made that all too obvious so many times.

No, he's just a ditch digger who got fired because he couldn't figure
out which end of the shovel to use.

M. Strobel

unread,
Apr 9, 2012, 5:29:14 AM4/9/12
to
This is evasion, or your troll rite.

> You have these calls:
> --> call C1::__construct
>
> That's ONE call to a constructor.
>
>
> --> call C1::__destruct
> --> call C1::__destruct
>
> That's TWO calls to destructors. IOW, an object was constructed without calling a
> constructor. This is a direct violation of OO principals (all objects must have
> exactly one constructor call and one destructor call).
>
> And ONE does not equal TWO. wakeup() is not a constructor, any more than sleep() is
> a destructor (and if sleep() were a destructor, then you would see a call to sleep()
> and a call to the destructor).

You should admit that serialize() is a special function that creates a frozen
portable copy of an object. The object loses it's identity in the process, but keeps
it's data. The calls to sleep() and wakeup() are okay.

> And I was referring to storing in a session, not serializing the data, i.e.
>
> $_SESSION['stupid'] = $idiot;

You could probably not work in a team, because you can't talk/write. You could
certainly not work as a teacher.

This is very interesting, and I never ran into this in my 20000+ lines of code
(current project), because I have a feeling of what makes sense. I always serialize
my objects myself.

The handling of objects in session variables seems broke. This is IMO no defect in
the object model, but in the session code.

Here is the test code, see yourself:

<head>
<title>object activity in session</title>
<meta http-equiv="content-type"
content="text/html;charset=utf-8" />
</head>
<body>
<h2>test script, see source code</h2>
<pre>
<?php
session_start();
if (!isset($_SESSION['cnt'])) $_SESSION['cnt']=1;
class C1 {
public $var1 = 'M. ';
public $var2 = 'Strobel';
function __construct() {
echo "\t--> call ". __METHOD__.PHP_EOL;
}
function __destruct() {
echo "\t--> call ". __METHOD__.PHP_EOL;
}
function __sleep() {
echo "\t--> call ". __METHOD__.PHP_EOL;
return array('var1','var2');
}
function __wakeup() {
echo "\t--> call ". __METHOD__.PHP_EOL;
}
function greet() { echo 'Hi, I am ',$this->var1, $this->var2, "\n"; }
} // end class C1

echo "This is call number ", $_SESSION['cnt'], "\n";

switch ($_SESSION['cnt']) {
case 1:
echo "creating object directly in session:\n";
$_SESSION['c1'] = new C1;
break;
case 2:
echo "Trying to access object in session:\n";
$_SESSION['c1']->greet();
break;
case 3:
echo "clearing session to start over, return code: ", session_destroy(), "\n";
break;
default:
echo "\nThis should not happen.\n";
}
$_SESSION['cnt']++;
?>
</pre></body></html>


/Str.

Jerry Stuckle

unread,
Apr 9, 2012, 8:27:16 AM4/9/12
to
On 4/9/2012 5:29 AM, M. Strobel wrote:
>
> You should admit that serialize() is a special function that creates a frozen
> portable copy of an object. The object loses it's identity in the process, but keeps
> it's data. The calls to sleep() and wakeup() are okay.
>

It doesn't make any difference what serialize is. OO requires exactly
one constructor and one destructor call for every object. Other
languages such as C++, SmallTalk and Java handle it fine.

sleep() and wakeup() are not constructors or destructors, and have a
different purpose.

>> And I was referring to storing in a session, not serializing the data, i.e.
>>
>> $_SESSION['stupid'] = $idiot;
>
> You could probably not work in a team, because you can't talk/write. You could
> certainly not work as a teacher.

I've been working in team environments for over 40 years. I have been
managing multi-programmer projects for over 25 years. And I have been
teaching for corporations (mostly Fortune 500) for over 20 years -
mainly C, C++, Java and OOAD (although some others also).

But then my students are intelligent. You wouldn't last a month there.

>
> This is very interesting, and I never ran into this in my 20000+ lines of code
> (current project), because I have a feeling of what makes sense. I always serialize
> my objects myself.
>

Shows how stoopid you really are. Glad you aren't on one of my projects
- you wouldn't last long (see above).

> The handling of objects in session variables seems broke. This is IMO no defect in
> the object model, but in the session code.
>

It is a flat out conflict in OO requirements. It has nothing to do with
sessions.

> Here is the test code, see yourself:
>

<snip>

Who gives a crap?

The bottom line is that PHP violates OO principles. No other language
does so. But then I'm sure you don't have any experience with other
languages.

> /Str.

You really are showing how ignorant of basic OO principles you are.

Thomas Mlynarczyk

unread,
Apr 9, 2012, 9:20:08 AM4/9/12
to
Jerry Stuckle schrieb:

> It doesn't make any difference what serialize is. OO requires exactly
> one constructor and one destructor call for every object.

Says who? What does object orientation have to do with constructors and
destructors? They're not required.

A constructor is called when a new object is constructed. A serialized
object has already been constructed so there's no point in calling its
constructor again when it is unserialized. In fact, the process of
serializing/unserializing creates a copy of the original object. (The
same holds for clone'd objects, by the way).

Greetings,
Thomas

--
Ce n'est pas parce qu'ils sont nombreux à avoir tort qu'ils ont raison!
(Coluche)

Jerry Stuckle

unread,
Apr 9, 2012, 12:03:55 PM4/9/12
to
On 4/9/2012 9:20 AM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> It doesn't make any difference what serialize is. OO requires exactly
>> one constructor and one destructor call for every object.
>
> Says who? What does object orientation have to do with constructors and
> destructors? They're not required.
>

Check any of the recognized OO experts - Booch and Yourdon, for
instance. Constructors are used to build objects, and destructors are
used to clean up objects. They have EVERYTHING to do with object
orientation!

And this is true of ALL true OO languages - such as C++, Java and
Smalltalk.

> A constructor is called when a new object is constructed. A serialized
> object has already been constructed so there's no point in calling its
> constructor again when it is unserialized. In fact, the process of
> serializing/unserializing creates a copy of the original object. (The
> same holds for clone'd objects, by the way).
>
> Greetings,
> Thomas
>

No, a serialized object is NOT necessarily constructed. It may have,
for instance, references to external resources which are no longer
available, such as a database connection. When this is the case, the
object is no longer valid - because the external resource is no longer
available.

One of the basic tenets of OO is that an object is responsible for its
own validity. An object must always be valid (or, if it is not valid
for some reason, not allow operations on it which depend on it being valid).

The __clone() method is a form of a constructor. But wakeup() isn't.

And if you argue that wakeup() is a form of a constructor, then you have
to argue that sleep() is a form of a destructor - in which case it would
be invalid to call the destructor after calling sleep().

Thomas Mlynarczyk

unread,
Apr 9, 2012, 2:04:59 PM4/9/12
to
Jerry Stuckle schrieb:

> The __clone() method is a form of a constructor. But wakeup() isn't.

Neither is. Cloning simply copies a previously constructed object while
__wakeup() changes the state of a previously constructed object.

> And if you argue that wakeup() is a form of a constructor,

I don't and never did.

> then you have
> to argue that sleep() is a form of a destructor - in which case it would
> be invalid to call the destructor after calling sleep().

Serialization creates a kind of "frozen" copy of an object. The original
object continues to exist and its destructor is called as expected.
Later, the "frozen" copy is "warmed up" and can pretend to be the
original object, but it is not the same object. The __sleep() and
__wakeup() methods simply assist with the freezing and warming up and
have nothing to do with the copying.

To sum it up: A new object can be created by either constructing it
(which calls __construct()) or by copying an existing object (via clone
or via serialization) and this happens without calling __construct() on
the copy since the object is already constructed. And this explains why
there may be more __destruct() calls than __construct() calls in a script.

Jerry Stuckle

unread,
Apr 9, 2012, 2:37:31 PM4/9/12
to
On 4/9/2012 2:04 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> The __clone() method is a form of a constructor. But wakeup() isn't.
>
> Neither is. Cloning simply copies a previously constructed object while
> __wakeup() changes the state of a previously constructed object.
>

Yes, __clone() is a form of a constructor. It creates a new object from
an existing object of the same type. In C++ this would be known as the
copy constructor, for instance. In Java it is the clone() method. Both
are considered constructors.

Also, when the object is serialized, it no longer is an object. It has
state but no behavior - the data are there but not the methods.

So when it is deserialized, a new object is created and by definition a
constructor must be called.

>> And if you argue that wakeup() is a form of a constructor,
>
> I don't and never did.
>
>> then you have to argue that sleep() is a form of a destructor - in
>> which case it would be invalid to call the destructor after calling
>> sleep().
>
> Serialization creates a kind of "frozen" copy of an object. The original
> object continues to exist and its destructor is called as expected.
> Later, the "frozen" copy is "warmed up" and can pretend to be the
> original object, but it is not the same object. The __sleep() and
> __wakeup() methods simply assist with the freezing and warming up and
> have nothing to do with the copying.
>

No, all serialization does is save the contents of the object. It is no
longer an object. The call to the original object's destructor is
correct. And, as you mentioned, when it is deserialized, it is no
longer the same object - it is a new one, so a constructor must be called.

> To sum it up: A new object can be created by either constructing it
> (which calls __construct()) or by copying an existing object (via clone
> or via serialization) and this happens without calling __construct() on
> the copy since the object is already constructed. And this explains why
> there may be more __destruct() calls than __construct() calls in a script.
>
> Greetings,
> Thomas
>

In object oriented programming, a new object can ONLY be created by
calling a constructor. As noted above, different languages have
different terms for them. But a constructor MUST be called according to
OO principles.

Scott Johnson

unread,
Apr 9, 2012, 2:50:55 PM4/9/12
to
On 4/9/2012 11:04 AM, Thomas Mlynarczyk wrote:

>
> Serialization creates a kind of "frozen" copy of an object. The original
> object continues to exist and its destructor is called as expected.
> Later, the "frozen" copy is "warmed up" and can pretend to be the
> original object, but it is not the same object. The __sleep() and
> __wakeup() methods simply assist with the freezing and warming up and
> have nothing to do with the copying.

I am not even near to being a voice for OOP in php but something ran
through my mind when i read this.

I use serialize to save form data from time to time into a DB. Easier
then having to have a separate column for each field (with obvious query
drawbacks - but I digress)

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)

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.

I am not sure if I am even making sense, this just kind of went across
my mind as i was reading.

Scotty





Thomas Mlynarczyk

unread,
Apr 9, 2012, 4:50:45 PM4/9/12
to
Jerry Stuckle schrieb:

> In object oriented programming, a new object can ONLY be created by
> calling a constructor. As noted above, different languages have
> different terms for them. But a constructor MUST be called according to
> OO principles.

Just to avoid confusion: When a new object is created, PHP must do some
work under the hood like allocating memory etc. and this of course is
"construction" work which is always done and in that sense a constructor
is indeed always called.

But after that, there is (or is not) the call to __construct(). And now
that I think of it, the name __construct() is actually not quite
correct, since the actual construction of the object is already done at
that point. What __construct() really does is perform some
initialization (in Python, the corresponding method is indeed called
__init__()).

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.

Therefore I must correct my earlier remark about neither __clone() nor
__wakeup() being constructors: __construct(), __clone() and __wakeup()
are all "of the same kind" -- performing initialization of an object
depending on how it was created.

On the other hand, __sleep() is not a destructor, because nothing is
destroyed when it is called. Note that __sleep() is supposed to return
an array, contrary to __destruct(). So, while the names __sleep() and
__wakeup() suggest a correspondence like __destruct() and __construct(),
this is not the case, since __sleep() is called on the original object,
while __wakeup() is called on the resurrected copy, so they're not
called on the same object.

Anyway, I must thank you for making me think more thoroughly about this.

Thomas Mlynarczyk

unread,
Apr 9, 2012, 5:03:59 PM4/9/12
to
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.

> 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

Scott Johnson

unread,
Apr 9, 2012, 6:27:38 PM4/9/12
to
OK I see.

I had not even thought about the need for creating the object from
either new or from a copied version.

Thanks for squeezing my brain.

Scotty

Jerry Stuckle

unread,
Apr 9, 2012, 8:17:58 PM4/9/12
to
On 4/9/2012 4:50 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> In object oriented programming, a new object can ONLY be created by
>> calling a constructor. As noted above, different languages have
>> different terms for them. But a constructor MUST be called according
>> to OO principles.
>
> Just to avoid confusion: When a new object is created, PHP must do some
> work under the hood like allocating memory etc. and this of course is
> "construction" work which is always done and in that sense a constructor
> is indeed always called.
>

No, memory allocation is NOT the same as a constructor. Memory
allocation makes space for the object. The constructor initializes it.

> But after that, there is (or is not) the call to __construct(). And now
> that I think of it, the name __construct() is actually not quite
> correct, since the actual construction of the object is already done at
> that point. What __construct() really does is perform some
> initialization (in Python, the corresponding method is indeed called
> __init__()).
>

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.

> 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.

> Therefore I must correct my earlier remark about neither __clone() nor
> __wakeup() being constructors: __construct(), __clone() and __wakeup()
> are all "of the same kind" -- performing initialization of an object
> depending on how it was created.
>

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().

> On the other hand, __sleep() is not a destructor, because nothing is
> destroyed when it is called. Note that __sleep() is supposed to return
> an array, contrary to __destruct(). So, while the names __sleep() and
> __wakeup() suggest a correspondence like __destruct() and __construct(),
> this is not the case, since __sleep() is called on the original object,
> while __wakeup() is called on the resurrected copy, so they're not
> called on the same object.
>

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

> Anyway, I must thank you for making me think more thoroughly about this.
>
> Greetings,
> Thomas
>


--

Jerry Stuckle

unread,
Apr 9, 2012, 8:22:45 PM4/9/12
to
On 4/9/2012 5: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.
>

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. Data may be saved between requests (i.e.
$_SESSION in PHP, a database, etc.). But these are not objects.

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.

>> 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:
>

Which is why objects can never persist across transactions. A new
object requires a constructor, under OO rules.

> __construct(): Object is "fresh", created using `new`
> __clone(): Object was copied from another object
> __wakeup(): Object was unserialized
>
> Greetings,
> Thomas
>

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

Jerry Stuckle

unread,
Apr 9, 2012, 8:25:14 PM4/9/12
to
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


M. Strobel

unread,
Apr 10, 2012, 4:05:26 AM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 6:43:25 AM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 6:48:31 AM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 7:28:42 AM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 7:44:23 AM4/10/12
to
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".

Jerry Stuckle

unread,
Apr 10, 2012, 7:58:08 AM4/10/12
to
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.

Jerry Stuckle

unread,
Apr 10, 2012, 8:04:52 AM4/10/12
to
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".

Jerry Stuckle

unread,
Apr 10, 2012, 8:06:28 AM4/10/12
to
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.

Jerry Stuckle

unread,
Apr 10, 2012, 8:11:35 AM4/10/12
to
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()).

Leonardo Azpurua

unread,
Apr 10, 2012, 8:22:16 AM4/10/12
to

"Jerry Stuckle" <jstu...@attglobal.net> escribió en el mensaje
news:jm17o8$ngo$2...@dont-email.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.

--


Message has been deleted

Thomas Mlynarczyk

unread,
Apr 10, 2012, 11:25:09 AM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 11:37:22 AM4/10/12
to
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.

Jerry Stuckle

unread,
Apr 10, 2012, 12:10:05 PM4/10/12
to
On 4/10/2012 11:04 AM, Tim Streater wrote:
> In article <jm178k$l6m$1...@dont-email.me>,
> Jerry Stuckle <jstu...@attglobal.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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 12:15:38 PM4/10/12
to
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.)

Jerry Stuckle

unread,
Apr 10, 2012, 12:16:54 PM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 12:18:47 PM4/10/12
to
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".

Jerry Stuckle

unread,
Apr 10, 2012, 12:19:38 PM4/10/12
to
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.

Jerry Stuckle

unread,
Apr 10, 2012, 12:20:43 PM4/10/12
to
If you want to call __wakeup() a constructor, then you need to call
__sleep() a destructor. You can't have it both ways.

Leonardo Azpurua

unread,
Apr 10, 2012, 12:33:32 PM4/10/12
to

"Jerry Stuckle" <jstu...@attglobal.net> escribió en el mensaje
news:jm1mku$hqm$3...@dont-email.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).

--


Message has been deleted

Thomas Mlynarczyk

unread,
Apr 10, 2012, 12:44:10 PM4/10/12
to
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.

M. Strobel

unread,
Apr 10, 2012, 12:54:24 PM4/10/12
to
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.

M. Strobel

unread,
Apr 10, 2012, 1:09:15 PM4/10/12
to
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.

The Natural Philosopher

unread,
Apr 10, 2012, 1:20:26 PM4/10/12
to
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.

M. Strobel

unread,
Apr 10, 2012, 1:31:05 PM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 2:10:33 PM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 2:17:11 PM4/10/12
to
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.

M. Strobel

unread,
Apr 10, 2012, 2:23:01 PM4/10/12
to
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.


M. Strobel

unread,
Apr 10, 2012, 2:25:59 PM4/10/12
to
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.

Jerry Stuckle

unread,
Apr 10, 2012, 5:08:03 PM4/10/12
to
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.


Jerry Stuckle

unread,
Apr 10, 2012, 5:11:15 PM4/10/12
to
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.
Possibly for future use? Most of PDO was written before __set_state()
was added, so maybe newer versions will use it.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 5:17:09 PM4/10/12
to
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.

Jerry Stuckle

unread,
Apr 10, 2012, 5:20:52 PM4/10/12
to
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).

Thomas Mlynarczyk

unread,
Apr 10, 2012, 5:21:56 PM4/10/12
to
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++; }

Jerry Stuckle

unread,
Apr 10, 2012, 5:23:12 PM4/10/12
to
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.

Jerry Stuckle

unread,
Apr 10, 2012, 5:28:43 PM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 5:30:41 PM4/10/12
to
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...

Jerry Stuckle

unread,
Apr 10, 2012, 5:34:49 PM4/10/12
to
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.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 5:57:12 PM4/10/12
to
Jerry Stuckle schrieb:

> 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.

Hm. Makes sense.

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

Yes, thinking more about it, it becomes a bit clearer. A child is also
an instance of all of its parent classes.

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

So the parent has a "private part" and the child has a "private part",
but they might also have a "shared part" ("protected") and there both
child and parent are responsible.

If the child overwrites a parent method, this will also affect the
parent since $this->method() will refer to the child's method, even if
called from a method defined in the parent class.

> 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.

So if there is no "shared part" between parent and child, does that mean
the child class should not have been derived from the parent in the
first place? Like "nothing to share -- nothing to inherit"?

Thomas Mlynarczyk

unread,
Apr 10, 2012, 6:13:56 PM4/10/12
to
Jerry Stuckle schrieb:

> I no longer even try to store objects in the session. It's hopeless.

Why? I never had any real problems with storing objects in the session.
Or maybe I was just lucky ;-)

> 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.

MyDatabaseSingleton::getInstance() ?

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

And how would a "proper use of constructors" solve the above problem?
Even if unserialize() called __construct(), you would have no chance to
pass any arguments to the constructor.

Thomas Mlynarczyk

unread,
Apr 10, 2012, 7:00:34 PM4/10/12
to
Jerry Stuckle schrieb:

[__sleep()]
> It can also be called after __wakeup(), i.e. if an unserialized object
> is serialized again.

Yes, but that would start a new "sleep cycle". You have to go to sleep
*before* you can wake up again.

> 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?

I would put all the objects referencing the database object along with
the database object in a container object and serialize that. After
unserializing, the objects will again reference the same database
object. No need for __wakeup() here.

Jerry Stuckle

unread,
Apr 10, 2012, 7:43:11 PM4/10/12
to
On 4/10/2012 5:30 PM, Thomas Mlynarczyk wrote:
> 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?
>

That is correct. That way __set() does not need to check to see if the
object has been initialized already.

> [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
>


--

Jerry Stuckle

unread,
Apr 10, 2012, 7:50:44 PM4/10/12
to
On 4/10/2012 5:57 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> 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.
>
> Hm. Makes sense.
>
>> So basically what you have is "dual identity" - the object is
>> considered both a parent and a child, depending on the context.
>
> Yes, thinking more about it, it becomes a bit clearer. A child is also
> an instance of all of its parent classes.
>
>> And the parent's constructor is responsible for constructing the
>> parent object; the child is only responsible for constructing the
>> child object.
>
> So the parent has a "private part" and the child has a "private part",
> but they might also have a "shared part" ("protected") and there both
> child and parent are responsible.
>

Generally, protected variables are frowned upon. Remember - ANYTHING
exposed outside the class can never be changed once the class is put
into production. You don't know how it will affect other classes.

Also, protected member variables leave the possibility open that a child
class can place an invalid value in it, potentially corrupting the base
class.

Private members (both variables and methods) and the code in the methods
are never available outside the class. As long as the result is the
same, how the class is implemented is immaterial.

This can be very handy when prototyping, for instance. You can create a
"quick and dirty" implementation of the class and use it. Later you can
come back and clean it up, making it more efficient, etc.

> If the child overwrites a parent method, this will also affect the
> parent since $this->method() will refer to the child's method, even if
> called from a method defined in the parent class.
>

Nope. If it's important to the parent, then the child's method should
call the parent's method. But many times I've had methods in the child
class which don't call the parent method for various reasons.

>> 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.
>
> So if there is no "shared part" between parent and child, does that mean
> the child class should not have been derived from the parent in the
> first place? Like "nothing to share -- nothing to inherit"?
>
> Greetings,
> Thomas
>

There is always something to inherit - the public interface. But the
child class should always be a more specific instance of the parent
class. For instance, Person->Employee would be ok, because Employee is
a more specific instance of Person. However, Employee->Contractor would
not - a contractor is not an employee.

The Person class can have private members for name, address, etc.
Employee would have additional fields such as start_date, employee_id, etc.

And from Employee you could derive Manager.

Jerry Stuckle

unread,
Apr 10, 2012, 7:53:32 PM4/10/12
to
On 4/10/2012 6:13 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> I no longer even try to store objects in the session. It's hopeless.
>
> Why? I never had any real problems with storing objects in the session.
> Or maybe I was just lucky ;-)
>
>> 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.
>
> MyDatabaseSingleton::getInstance() ?
>

What if you don't want a singleton? Many times I've had the need to
access different databases, for instance. You are limiting the
versatility of the class.

>> None are good answers - but all could be easily handled with proper
>> use of constructors.
>
> And how would a "proper use of constructors" solve the above problem?
> Even if unserialize() called __construct(), you would have no chance to
> pass any arguments to the constructor.
>
> Greetings,
> Thomas
>

By definition you can pass arguments to the constructor. That's why
unserialize() is not a good implementation.

Jerry Stuckle

unread,
Apr 10, 2012, 7:54:37 PM4/10/12
to
On 4/10/2012 7:00 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
> [__sleep()]
>> It can also be called after __wakeup(), i.e. if an unserialized object
>> is serialized again.
>
> Yes, but that would start a new "sleep cycle". You have to go to sleep
> *before* you can wake up again.
>
>> 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?
>
> I would put all the objects referencing the database object along with
> the database object in a container object and serialize that. After
> unserializing, the objects will again reference the same database
> object. No need for __wakeup() here.
>
> Greetings,
> Thomas
>

No, because the database objects themselves will rely on external
resources which are not serialized. You have the same problem as before.

M. Strobel

unread,
Apr 11, 2012, 4:40:26 AM4/11/12
to
Let's see, this gives a good reference:

<?php
class Upset {
public $pubvar;
private $privvar;
function __set($n, $v) {
echo "setting variable $n to: $v\n";
$this->$n = $v;
}
function __get($n) {
echo "getting variable $n\n";
if (isset($this->$n)) return $this->$n;
else return null;
}
}
$c = new Upset();
$c->pubvar = 'Try this';
$c->privvar = ' private ';
$c->adhoc = ' and this ';
echo "Values are now $c->pubvar $c->privvar $c->adhoc\n";
------------------- Result is: ----
setting variable privvar to: private
setting variable adhoc to: and this
getting variable privvar
Values are now Try this private and this


/Str.

Thomas Mlynarczyk

unread,
Apr 11, 2012, 4:10:07 PM4/11/12
to
Jerry Stuckle schrieb:

> No, because the database objects themselves will rely on external
> resources which are not serialized. You have the same problem as before.

The external resource would be the actual database connection here.
Which the database object can easily re-acquire in its __wakeup()
method, like

class MyDatabase
{
public function __wakeup()
{
$this->pdo = new PDO( ... );

Thomas Mlynarczyk

unread,
Apr 11, 2012, 4:17:51 PM4/11/12
to
Jerry Stuckle schrieb:

>> MyDatabaseSingleton::getInstance() ?
>
> What if you don't want a singleton? Many times I've had the need to
> access different databases, for instance. You are limiting the
> versatility of the class.

MyDatabase::getConnection( $id )

> By definition you can pass arguments to the constructor. That's why
> unserialize() is not a good implementation.

But how would you pass any constructor arguments to an unserialize()
function anyway? You cannot be sure what the string to be unserialized
really contains, so how would you know which constructor arguments to
pass? This could be a job for __set_state(): unserialize() then wouldn't
create objects, but simply call the __set_state() method on the class in
question, passing the unserialized state information and leave it to
that method to reconstruct the actual object. But this does not seem to
be the way PHP works.

Jerry Stuckle

unread,
Apr 11, 2012, 4:30:28 PM4/11/12
to
On 4/11/2012 4:17 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>>> MyDatabaseSingleton::getInstance() ?
>>
>> What if you don't want a singleton? Many times I've had the need to
>> access different databases, for instance. You are limiting the
>> versatility of the class.
>
> MyDatabase::getConnection( $id )
>

Which once again doesn't reuse an existing connection, nor does it
specify what connection is being used. Which host? Which database?

If it's defined within the MyDatabase class, you're restricted to that
one connection/database. If it's defined in the serialized class,
you've limited the usefulness of that class.

All is resolved by passing a database object in the constructor of the
class. You are using the object the program wants - not one predefined
by the class itself.

> > By definition you can pass arguments to the constructor. That's why
>> unserialize() is not a good implementation.
>
> But how would you pass any constructor arguments to an unserialize()
> function anyway? You cannot be sure what the string to be unserialized
> really contains, so how would you know which constructor arguments to
> pass? This could be a job for __set_state(): unserialize() then wouldn't
> create objects, but simply call the __set_state() method on the class in
> question, passing the unserialized state information and leave it to
> that method to reconstruct the actual object. But this does not seem to
> be the way PHP works.
>
> Greetings,
> Thomas
>

Which is a big problem with unserialize(). Other languages handle it
quite well by having different constructors available. For instance,
there could be a constructor which takes the serialized object and an
array (or variable arg list) which would unserialize the data and use
the additional arguments.

But problems like this make almost any but the simplest objects useless
for any type of serialization.

Jerry Stuckle

unread,
Apr 11, 2012, 4:31:58 PM4/11/12
to
On 4/11/2012 4:10 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>> No, because the database objects themselves will rely on external
>> resources which are not serialized. You have the same problem as before.
>
> The external resource would be the actual database connection here.
> Which the database object can easily re-acquire in its __wakeup()
> method, like
>
> class MyDatabase
> {
> public function __wakeup()
> {
> $this->pdo = new PDO( ... );
> }
> }
>
> Greetings,
> Thomas
>

Which connection? Which database? Specifying the data here makes the
class less reusable.

And what if you want to use an existing PDO object?

Thomas Mlynarczyk

unread,
Apr 11, 2012, 4:40:30 PM4/11/12
to
Jerry Stuckle schrieb:

>> class MyDatabase
>> {
>> public function __wakeup()
>> {
>> $this->pdo = new PDO( ... );
>> }
>> }
>
> Which connection? Which database? Specifying the data here makes the
> class less reusable.

The connection parameters would be taken from some config file or they
would have been serialized along with the object.

> And what if you want to use an existing PDO object?

MyDatabaseFactory::getConnectionObject( $config )

Jerry Stuckle

unread,
Apr 12, 2012, 12:02:07 AM4/12/12
to
On 4/11/2012 4:40 PM, Thomas Mlynarczyk wrote:
> Jerry Stuckle schrieb:
>
>>> class MyDatabase
>>> {
>>> public function __wakeup()
>>> {
>>> $this->pdo = new PDO( ... );
>>> }
>>> }
>>
>> Which connection? Which database? Specifying the data here makes the
>> class less reusable.
>
> The connection parameters would be taken from some config file or they
> would have been serialized along with the object.
>

OK, that part would work.

>> And what if you want to use an existing PDO object?
>
> MyDatabaseFactory::getConnectionObject( $config )
>
> Greetings,
> Thomas
>

You have 5 different connections to the database. Which one is the
correct one to use?

M. Strobel

unread,
Apr 12, 2012, 6:00:42 AM4/12/12
to
Am 12.04.2012 06:02, schrieb Jerry Stuckle:
> On 4/11/2012 4:40 PM, Thomas Mlynarczyk wrote:
>> Jerry Stuckle schrieb:
>>
>>>> class MyDatabase
>>>> {
>>>> public function __wakeup()
>>>> {
>>>> $this->pdo = new PDO( ... );
>>>> }
>>>> }
>>>
>>> Which connection? Which database? Specifying the data here makes the
>>> class less reusable.
>>
>> The connection parameters would be taken from some config file or they
>> would have been serialized along with the object.
>>
>
> OK, that part would work.
>
>>> And what if you want to use an existing PDO object?
>>
>> MyDatabaseFactory::getConnectionObject( $config )
>>
>> Greetings,
>> Thomas
>>
>
> You have 5 different connections to the database. Which one is the correct one to use?
>

Follow the same logic you used in the first place.

Anyway, I vote for a streamlined init code executed at every HTTP request, this
matches the nature of the HTTP protocol. I can't see why server name and protocol,
client IP and some session flags would not do it.

For the biggest requirements an application server would be a match.

/Str.

Jerry Stuckle

unread,
Apr 12, 2012, 7:45:27 AM4/12/12
to
On 4/12/2012 6:00 AM, M. Strobel wrote:
> Am 12.04.2012 06:02, schrieb Jerry Stuckle:
>> On 4/11/2012 4:40 PM, Thomas Mlynarczyk wrote:
>>> Jerry Stuckle schrieb:
>>>
>>>>> class MyDatabase
>>>>> {
>>>>> public function __wakeup()
>>>>> {
>>>>> $this->pdo = new PDO( ... );
>>>>> }
>>>>> }
>>>>
>>>> Which connection? Which database? Specifying the data here makes the
>>>> class less reusable.
>>>
>>> The connection parameters would be taken from some config file or they
>>> would have been serialized along with the object.
>>>
>>
>> OK, that part would work.
>>
>>>> And what if you want to use an existing PDO object?
>>>
>>> MyDatabaseFactory::getConnectionObject( $config )
>>>
>>> Greetings,
>>> Thomas
>>>
>>
>> You have 5 different connections to the database. Which one is the correct one to use?
>>
>
> Follow the same logic you used in the first place.
>

And how do you do that? In the first place you pass the database object
you wish to use in the constructor.

> Anyway, I vote for a streamlined init code executed at every HTTP request, this
> matches the nature of the HTTP protocol. I can't see why server name and protocol,
> client IP and some session flags would not do it.
>

What do those have to do with it? Database connection doesn't depend on
the client IP, for instance.

> For the biggest requirements an application server would be a match.
>
> /Str.

And how would that help?

These things are quite easy in true OO languages - and quite often done
when doing transactional programming (like web pages are). But they
can't be done the way PHP implements it.

Just another case of how PHP screws things up.
0 new messages