-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
parent::$foo with parent class after child class #8
Comments
I'm really not sure how this should be approached. This certainly can't be solved at compile time, so this will need to be done at runtime. But as the static property accesses don't have a read/write/exists separation I don't know how this should be done. One could add a special set of opcodes for |
By the way, this is obviously not limited to the class order example above. It happens whenever the parent class is not in the class table at the time of compilation of the child class. E.g. if the class B would go in a different file and be included before the A class, then it would still fail (because the inclusion happens at runtime). Similarly if B would be autoloaded it wouldn't work either. |
This should be solvable for the non-static paradigm because I think the parent:: issue you are running into will not be a problem On 12/29/2012 12:36 PM, nikic wrote:
-Clint |
@cpriest I'm not sure I see what you mean. As |
What I mean is this: function __construct() { Since this already works, there's no reason a parent::__getFoo(); On 12/29/2012 4:58 PM, nikic wrote:
|
@cpriest |
I think we're on different pages... For non-static accessors there is In any case, there is a conflict there b/w does the user want the On 12/30/2012 9:26 AM, nikic wrote:
|
That's exactly the problem I see, that we can't distinguish between <?php
class C extends P {
public function doFoo() {
parent::$foo = 'test';
}
}
/* Case 1: Parent has an accessor with this name */
class P {
public $foo {
set { ... }
}
}
/* Case 2: */
class P {
public static $foo;
} Here there could be two cases what the Because we can't know at compile time we also can't do the Not sure whether this clarifies what I mean ^^ |
I see what you mean, the normal, pre-accessor engine code converts parent::$foo to a static property access at compile time, is that right? I think our only course of action then is to prevent, at compile time, this ambiguity by not allowing an accessor to be defined where a static property in the class chain exists. Then this ambiguity would be prevented, no? Should we post this issue to the list and have them chime in here? Could create a lot of stalemate though. |
@cpriest The issue is that we can't check the class chain at compile time. If we could, we could also directly check whether it is an accessor and not have the problem in the first place. |
What can we do about this then? Are you saying that at no point before the end of compilation this can be checked? That can't be right because the following code won't compile: #!/usr/bin/phpd
<?php
class B extends A {
private $foo;
}
class A {
public $foo;
} Fatal error: Access level to B::$foo must be public (as in class A) in /opt/php-core/git/trunk-accessor/cpriest/php/quick2.php on line 4 So at some point this should be resolvable. Let me get the static code that I've put in pulled out and we can see what we can do at that point. I plan to locate the code which early-set the parent ce and remove that, it was just a few lines of code and I believe it was in the function that begins a class declaration. |
@cpriest Those checks happen at run-time, not at compile time. |
Alright, I've found the code which does early-fetch and set of new_class_entry->parent and I don't see any real problem in leaving the code in, thought I'd get your opinion on that: /* Locate parent_class_name and parent_class_entry to assign */
fetch_class = find_previous_op(ZEND_FETCH_CLASS TSRMLS_CC);
if(fetch_class != NULL && fetch_class->op2_type == IS_CONST) {
zend_class_entry **parent_cepp = NULL;
zval *parent_class_zv = &CG(active_op_array)->literals[fetch_class->op2.constant].constant;
char *lc_parent_class = zend_str_tolower_dup(Z_STRVAL_P(parent_class_zv), Z_STRLEN_P(parent_class_zv));
if (zend_hash_find(CG(class_table), lc_parent_class, strlen(lc_parent_class)+1, (void **) &parent_cepp)==SUCCESS) {
new_class_entry->parent = *parent_cepp;
}
efree(lc_parent_class);
} from d003093:5693 If it doesn't find a class by the given name it doesn't set it, so if it's available then it will be available earlier than before. |
@cpriest If we don't need the code anymore it should be removed (as it can't be used in the general case anyway). Otherwise people will think that the parent CE is available, even though it really isn't. |
Alright, I'll remove it. One thing though, the error mentioned in a previous comment by me with "Fatal error: Access level to B::$foo must be public " is done at compile time, so we could disallow a static property w/ the same name during the compilation phase. I'm going to go forward with the idea that we will disallow a conflict b/w static $foo and accessor $foo throughout the inheritance chain. |
@cpriest The check throws a compile error but does not actually happen at compile time. But that's not really important here, because for this purpose it doesn't matter when the check is done. I agree that we should check for this as it really doesn't make sense to override static with non-static or the other way around. But I fail to see how this will fix the |
Well you probably know the code better than I do, but I see that Alternatively we could do it the other way and make it a function call referencing the parent. I guess a 3rd option might possibly be to introduce a new opcode? |
Really need to decide on a solution to this, @smalyshev could you chime in here, could use some help from another expert. :) One other possible solution is: https://gist.github.com/4420904 |
Stas suggested parent->$foo which I think is perfect, I'll post this to the list and see what others think. |
parent->$foo is not quite right - it means $foo is variable name, not foo. Yes, I know it's a mismatch between statics and dynamics, it's a problem :( |
oh right, duh. you wouldn't do $this->$foo... brain fart. On 1/4/2013 12:05 AM, Stanislav Malyshev wrote:
|
I'm good with parent->foo, there doesn't seem to be many complaints about it, nor alternatives posted. |
RFC Updated with Nikita's suggestion which met with no resistence. (new ReflectionPropertyAccessor(CLASS, 'Milliseconds'))->setValue($this, $value); |
Currently the implementation needs the
->parent
CE of theactive_class_entry
to implementparent::$foo
accesses. Normally this information is not available until runtime. To avoid it the implementation scans the opcodes for theZEND_CLASS_FETCH
instruction, extracts its name and looks it up in the class entry table.This procedure fails if the extended class is only defined after the child class, as the following example shows:
In this case an error is thrown:
Even though static accessors won't be supported, this still has to be solved, because
parent::$foo
is used for normal properties as well.The text was updated successfully, but these errors were encountered: