decioalex Posted August 15, 2007 Share Posted August 15, 2007 Hi, expanding a little on this post: http://www.phpfreaks.com/forums/index.php/topic,154922.0.html, I have a problem with knowing where my properties are being called from. What I am trying to do is setting a way to declare strong typed fields within a class, and setting it as private, protected or public and as readonly, writeonly or both. For this to work, I am using the __get and __set magic methods to receive the call for an unset property (with the same "base" name as the ones declared inside the class, and check if it should be pointing to a "strong typed" declared property. So far so good and everything is working perfectly. The problem is that the __get and __set methods (expectedly) does not inform me if the call is being done from within the class, its children or from outside it, so I can't check for visibility. That is why I am looking for a possible way to make sure from where that property was called, so I can trigger the visibility check methods. ??? Any help is appreciated. Thanks! Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/ Share on other sites More sharing options...
Daniel0 Posted August 15, 2007 Share Posted August 15, 2007 AFAIK you can't. If you want to enforce visibility, then you'll have to declare it using e.g. public $whatever;. Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-324888 Share on other sites More sharing options...
decioalex Posted August 15, 2007 Author Share Posted August 15, 2007 AFAIK you can't. If you want to enforce visibility, then you'll have to declare it using e.g. public $whatever;. Oh.. :'( Isn't there any way to catch how or when PHP triggers the visibility check? Or a way to know where the call for that property came from? Are the debug tools using the PHP internal parser to know where the call came from so it can trigger an error if accessing a hidden member? :'( Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-324929 Share on other sites More sharing options...
Daniel0 Posted August 15, 2007 Share Posted August 15, 2007 xdebug has xdebug_get_function_stack(). That might be able to do it. http://xdebug.org/docs/stack_trace Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-324932 Share on other sites More sharing options...
decioalex Posted August 15, 2007 Author Share Posted August 15, 2007 Humm.. you gave me a good idea and I just found out about the debug_backtrace functions as of PHP 4.3.0. I am taking a look at it and I think that with some tweaking I can get it to work as I expected Thanks! Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-324969 Share on other sites More sharing options...
emehrkay Posted August 15, 2007 Share Posted August 15, 2007 reread my solution and look at the wikipedia page linked by keeB in the first post. the answer is there. Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-325219 Share on other sites More sharing options...
decioalex Posted August 16, 2007 Author Share Posted August 16, 2007 reread my solution and look at the wikipedia page linked by keeB in the first post. the answer is there. Hi! Thanks for the reply. I went over the abstract Factory solution. But I can't see how this can help. I will try to give examples here, since I don't have the script in here to post. What I am trying to do is something like this: [pre]class X { public $strSomeString; private $arrSomeArray; protected $bolSomeBoolean; public function __construct() { $this->strSomeString = "Some value"; $this->arrSomeArray = array("value1", "value2", "etc."); $this->bolSomeBoolean = true; } public function __get($var) { TypeChecker::GetProperty($var); } public function __set($var, $value) { TypeChecker::SetProperty($var, $value); } } $obj1 = new X(); echo $obj1->SomeString; var_dump($obj1->SomeArray); echo $obj1->SomeBoolean; [/pre] So all the calls above would be to the "name" of the property, NOT its prefix+name. Then the get and set methods would call the TypeChecker class, which would in turn check for the existence of that property and chek to see if the correct type was passed (in case of the set method). It then would need to check the visibility of the property t make sure it can be called form where it is being called. That is why I need to know where the calling came (if fro minside the same class, its children or outside it). Maybe your solution can help me with this, but since I am still no familiar with Patterns, I couln't understand how it would apply. As I posted, I thought about the debug_baktrace option and about parsing it to make sure I know where it is being called from. But since, so far the tests I've run can not really trace the called property back to the origin of the call. So if I have a class A and a class B that instantiates class A, if I call $this->SomeNewVar (from inside class A) or $classB->classAInstance->SomeNewVar, the debug_backtrace array shows me the same object as the source of the call. The only way to use it would be to set that each class has its own file, so if I am inside the same file it wouls allow the call. if not, it would chek if the other class is a child of the first one, to see if the property can be called. The problem with this is really making sure no one using the classes I am developing will instanciate the object inside the same file or in a different, not class file. Well, still searching... Thanks! Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-325355 Share on other sites More sharing options...
keeB Posted August 16, 2007 Share Posted August 16, 2007 I really, really don't understand what you're trying to accomplish. I can't think of any time where I'd want an object to care how or from where it's being called from. Can you please explain the overall goal of the exercise? I think you're trying to make this much harder than it really should be. Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-325432 Share on other sites More sharing options...
emehrkay Posted August 16, 2007 Share Posted August 16, 2007 when you extend a class, the child has access to all of the public/protected methods and properties class a{ protected $_var = 'hi, i'm from a'; public function test(){} } class b extends a{ protected $_varb = 'im from b'; public function testB(){} } $x = new b(); echo $x->_var; //hi, im from a echo $x->-varb; //im from b now with the factory, it doesnt need to be abstract, you're doing the same thing except you're calling the parent and beign returned a child class a{ public fucntion __construct($class){ switch($class){ case 'b': return new b(); break; case 'c': return new c(); break; } } public function someBaseFunctionAllChildenWouldUse(){} } class b extends a{ //class b only functions } class c extends a{ //class c only functions } $x = new a('b'); //x is returned with all of b's methods/properties as well as a's $y = new a('c'); //$y has all of c's methods/properties and a's its hard becuase we do not know exactly what you're trying to accomplish. but fromw hat you've told us, this seems to be a solution that i would take Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-325811 Share on other sites More sharing options...
decioalex Posted August 16, 2007 Author Share Posted August 16, 2007 when you extend a class, the child has access to all of the public/protected methods and properties its hard becuase we do not know exactly what you're trying to accomplish. but fromw hat you've told us, this seems to be a solution that i would take I am sorry for not being too clear before. Just now I realized that in my first post I failed to post de sources to my idea. I was going through these two websites about a proposal for sort of a TypeChecker class that would enforce strong typing (type safe or type hinting) properties: http://jan.kneschke.de/2007/2/19/typesafe-objects-in-php http://www.cstruter.com/replyblog.php?ContentID=44 So I tried to come up with another solution where it would be based on this: 1. All field declarations would be done with a prefix, which would point to the type of the field (like $strSomeString, $arrSomeArray and so on). 2. Every class I wanted to work with this strong typed approuch would have a __get and a __set methods which would in turn call the TypeChecker class. 3. Since the magic methods are only called for non declared properties, every property I tried to access would have the syntax ignore the prefix (like if I have a field for class A declared as $strSomeString, I would call it as $objA->SomeString). 4. Since those properties were not declared, the magic methods would handle them, calling the TypeChecker class, which would in turn: 4.1. check for the existence of a Field with the same Syntax (case sensitive would still work in this case), and any prefix and call an "property not declared" exception if it don't. 4.2. store in a static variable these fields and the values, for future compare. 4.3. for a set method, check for type of the value being passed and if it matches the prefix of the field we are trying to set. If not, rises an exception. 4.4. The big problem: Check if the visibility of the field allows me to access it and rise an exception if don't. 4.5. If all goes ok, returns me the existing field ($strSomeString, for example). So the problem is #4.4. This, as I found out, I can only do if I know from where that property is being called. I will post again the first example. class TestX { public $strSomeString; private $arrSomeArray; protected $bolSomeBoolean; public function __construct() { $this->SomeString = "Some value"; // calls a new $SomeString and NOT $strSomeString $this->SomeArray = array("value1", "value2", "etc."); // calls a new $SomeArray and NOT $strSomeArray $this->SomeBoolean = true; // calls a new $SomeBoolean and NOT $strSomeBoolean } public function __get($var) { TypeChecker::GetProperty($var); // calls the class I created to "type safe" the property } public function __set($var, $value) { TypeChecker::SetProperty($var, $value); // calls the class I created to "type safe" the property } } $obj1 = new TestX(); echo $obj1->SomeString; var_dump($obj1->SomeArray); echo $obj1->SomeBoolean; Note in here that all fields use the prefix to hint its type. But the calls to the properties don't. So they trigger the magic methods which in turn check if everything is ok. The problem is that if I don't know whether "SomeString" is being called from inside the class, its children or outside it, I can't have the TypeChecker class make sure the property can be accessed. Humm.. I hope it is clearer now. Actually this is kind of a hobby for me, but it's helping me learn heaps about OO in PHP and a lot more, as well as deepen my knowledge of it. My goal is that only by using the more or less traditional type hinting prefix to the properties and a snippet for all classes, forgetting about the prefix when we call'em (a bit like we do already when we are careless about the type) with the magic methods above, as well as an include to the TypeChecker class (all and all, not too much) I can have a bit of a strong typed php framework to work with But this is depending on the knowing where something was called from, which got me stuck. Thanks for all the help you gave me so far. It's really helping me learn. Decio Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-325908 Share on other sites More sharing options...
keeB Posted August 16, 2007 Share Posted August 16, 2007 <?php function TypeChecker($var) { if(is_array($var)) return "array"; if(is_string($var)) return "string"; if(is_int($var)) return "string" if(is_float($var)) return "float"; // ??????? } Your problem still makes no sense to me Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-326200 Share on other sites More sharing options...
decioalex Posted August 17, 2007 Author Share Posted August 17, 2007 Hi Keeb, May I AM really making this more difficult than it should be The problem with your approuch as I see, is that for every property mutator (set) I would have to call the TypeChecker Class or function, and it would also occur with every acessor (get), to check if the property was already declared. I could certainly do that kind fo thorough check for my could but it would be a hardwired solution, which would failed to help if in any place or class I already use, I didn't place that TypeChecker function call like you did for every property What I am trying to do is 1. make use of the magic methods to help me with not needing to specify or create get and set methods for every property, 2. have a class do all the work of checking the type of each property and if it exists or not, as well as if I can have access to it from where I am calling it or not, 3. prevent that this kind of StrongTyped coding that would done from now one changed too much the general practices we may already have (like type hinting the type of the declared property with prefixes - in this case, only the calls to the properties would be left without the prefixes to trigger the type checking), 4. garantee I don't have to change too much in the classes I already have and use, which I would only need to place the magic __get and __set methods with the call to the Type Checker class. Actually I didn't go too far off from the idea of the people in those articles, one with the solution of using arrays in a child class to declare the properties and their type, and the other doing this with doc comments. I just came up with another solution, but the problem still remains and that is that by triggering the magic methods I am considering the propertiesof my class as public and that ruins the idea of encapsulation. If there is any way of really capture the call to the property class and where it is being called from, we could solve this problem. I hope this made my idea more clear. Please let me know if it didn't help. And anyway, thanks for all the help so far. Like I say, I may be making this more difficult than it should be, but I couldn't see other way to do this. Decio Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-326565 Share on other sites More sharing options...
emehrkay Posted August 17, 2007 Share Posted August 17, 2007 you knwo, there is a profiler built into php that would give you exactly what you're looking for. I just dont know the name of it right now. Ill check back Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-326644 Share on other sites More sharing options...
decioalex Posted August 17, 2007 Author Share Posted August 17, 2007 Humm... profiler? You mean PEARL profilers? I just run a quick search in the official site for it and it returned mainly PERL profilers... But I've never heard of'em. Decio Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-326874 Share on other sites More sharing options...
emehrkay Posted August 17, 2007 Share Posted August 17, 2007 i was thinking of the reflection method. i hope you can use this http://us3.php.net/manual/en/language.oop5.reflection.php Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-327087 Share on other sites More sharing options...
decioalex Posted August 21, 2007 Author Share Posted August 21, 2007 i was thinking of the reflection method. i hope you can use this http://us3.php.net/manual/en/language.oop5.reflection.php Hi, sorry for the late reply. Yes, I was going over it and, in fact, I am using it on the Type Checker class. But it doesn't provide anything to track at real time the calling of a property (as far as I saw). I am playing right now with the debug_backtrace function since it's the only one so far that has provided anything close to what I need and I'm doing some tests to understand it's behavior on many different situations where I would call a property to see how I can parse it. Unfortunatelly, I couldn't do many tests on this since saturday, but as soon as I find anything usefull I will post here. Thanks for all the help emehrkay and keeB! Quote Link to comment https://forums.phpfreaks.com/topic/65071-where-am-i-being-called-from/#findComment-329806 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.