php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #26325 At least a notice when accessing private members in a derived class?
Submitted: 2003-11-19 17:49 UTC Modified: 2003-12-23 11:40 UTC
From: drm at melp dot nl Assigned:
Status: Closed Package: Scripting Engine problem
PHP Version: 5.0.0b2 OS: *
Private report: No CVE-ID: None
 [2003-11-19 17:49 UTC] drm at melp dot nl
Description:
------------
Hi :)

I read in the new features list of Zend Engine 2 that access modifiers like private/protected are introduced, but something really weird comes in mind when reading carefully.

Private members are returned _empty_ wheing tried to be accessed from derived classes. "Intended behaviour", is said. OK, i can live with that. But even when i turned on notices with error_reporting, nothing is noticed?

The case grows when looking at the following code sample. This could produce very weird bugs when writing PHP code (i hope you can see that ;)), so I would like to convince you all to at least implement a Notice when trying to access (non-defined) private (parent) members?

It would do the coders not using E_ALL no harm :) Please consider this :)

Reproduce code:
---------------
error_reporting ( E_ALL );
class Test {
   private $member;
   function __construct ()       { $this->member = "Test constructor"; }
   function __toString ()        { return "Member contains: {$this->member}"; }
   function getMember ()         { return $this->member;  }
   function setMember ( $m )     { $this->member = $m; }
}
class DeriveTest extends Test {
   function __construct ()       { parent::__construct (); }
   function __toString ()        { return "Member contains: {$this->member}, though getMember() says: " . $this->getMember() ."?"; }
   function setMember ( $m )     { $this->member = $m; }
}
$o = new DeriveTest ();
echo $o, '<br>';
$o->setMember ( "a" );
echo $o, '<br>';


Expected result:
----------------
The expected result would be for me:

Notice: undefined member ``DeriveTest::$member'' in ...\test.php on line 12
Member contains: , though getMember() says: Test constructor?
Member contains: a, though getMember() says: Test constructor?

or something of the sort

Actual result:
--------------
The actual result is:

Member contains: , though getMember() says: Test constructor?
Member contains: a, though getMember() says: Test constructor?

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2003-11-20 04:45 UTC] drm at melp dot nl
Here's a more explanatory piece of code:
http://gerard.yoursite.nl/php.net/private-members.phps
 [2003-11-20 11:46 UTC] jay@php.net
There are two issues here. 
 
First, PHP 5 is just acting like PHP 4 did -- you can 
initialize a member of an object without explicitly 
declaring it in the class definition and PHP won't 
complain. 
 
Second, Test::$member and DeriveTest::$member aren't the 
same things. Test::$member being private, it's only 
accessible and visible from within Test. DeriveTest has no 
idea it exists, so it creates its own public member called 
$member. If you do a print_r($o) at the end of your 
script, you'll see that there are two members called 
$member, one of which is private and the other public. 
 
So yes, this is intended behaviour. One of the main ideas 
of private members is that they aren't even visible from 
derived classes. If you try to access a private member 
from a parent class, the derived class won't see it and 
will instead try using its own member, and if that doesn't 
exist it will implicitly create it. 
 
J 
 [2003-11-22 09:05 UTC] drm at melp dot nl
Excuse me, but you are *totally* missing my point here. You are telling me things i had already pointed out in the first post.

I'll reduce my feature request to one simple line:

Can *at least* a "notice" be triggered when a private member variable does not exist but is accessed? And by accessed i do NOT mean assigned!

You're saying it behaves the same way php4 does, but that's just plain bs. See the following code in PHP4:

<?
error_reporting ( E_ALL );
class Test {
   function getMember () {
      return $this->member;
   }
}
$t = new Test ();
echo $t->getMember ();
?>

This would yield the following notice:
Notice: Undefined property: member in test.php on line 5

All i'm asking is that some notice of the SAME sort can be implemented in php5 when trying to access parent private members.
 [2003-11-22 10:26 UTC] abies@php.net
Actually, the main issue here is that PHP doesn't give a notice at all if you access an undefined property, whether it is a private property in a base class or not.


 [2003-11-22 18:57 UTC] drm at melp dot nl
You are right, i hadn't researched the problem that well, since i assumed php5 would treat properties the php4-style the same way as php4 itself. But you are right; the code sample above when ran in php5 doesn't give a notice, though php4 does.
 [2003-11-24 11:28 UTC] jay@php.net
Take your original example and edit it so it works in PHP 
4. It runs in both 4 and 5 without a notice. Based on your 
original example code, that isn't "just plain bs."  
 
Upon further inspection based on your second example, 
there is definitely something weird going on here. This is 
most likely related to #26182. 
 
J 
 
I'm not positive, but I think this may have something to 
do with #26182.  
 
J 
 [2003-11-26 11:07 UTC] drm at melp dot nl
J > Sorry i reacted that way, I misinterpreted your post. 

I cannot reproduce what you mean in PHP4. Can you give an example?

I tried some stuff, but all the versions i tried gave expected results. Changing "private $member" into "var $member" or removing that line completely results in:

-----
Member contains: Test constructor, though getMember() says: Test constructor?
Member contains: a, though getMember() says: a?
-----

which is logical, since the member will be public as soon as you introduce it, both with "var $member" and removing the line completely (and initializing it in the Test constructor). When removing the initialization in the Test constructor, the same notice as in the other codesample will be produced. (Notice: Undefined property: member in ....)

btw: i figure this hasn't got anything to do with the fact that I tested on WinXP, maybe that should be changed to OS: irrelevant?
 [2003-12-16 03:00 UTC] sniper@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5-win32-latest.zip

AFAICT, bug #26182 is fixed..so try the snapshot?

 [2003-12-17 12:06 UTC] drm at melp dot nl
sniper >

I tried the snapshot (labeled PHP/5.0.0b3-dev), but the problem persists.
 [2003-12-23 10:30 UTC] arjen at glas dot its dot tudelft dot nl
I've tested this with php5-200312222030 snapshot and I get two notices, when using this code (which is correct):
<?
error_reporting ( E_ALL );
class Test
{
    private $member = "member";
}

class DeriveTest extends Test
{
     function __toString()
     {
        return "Member: {$this->member}, nonexistent {$this->nonexistent}";
    }
}
$o = new DeriveTest ();
echo $o, '<br>';
highlight_file(__FILE__);
?>

It could, however, be done even better if it were a bit more explainatory notice. Like Java's error for instance:
DeriveTest.java:5: member2 has private access in Test
                return "Member contains: " + member2 + " and getMember sais: " + nonexistent;
                                             ^
DeriveTest.java:5: cannot resolve symbol
symbol  : variable nonexistent
location: class DeriveTest
                return "Member contains: " + member2 + " and getMember sais: " + nonexistent;
                                                                                 ^
2 errors

I.e. a distinction between nonexistent members and private members.
 [2003-12-23 11:40 UTC] helly@php.net
This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.

A derived class does not know *anything* about private members of a base class. Hence there cannot be a distinction. Hence the result is correct.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Oct 17 21:01:27 2024 UTC