Liquid Fire Posted March 22, 2008 Share Posted March 22, 2008 As i am building my framework and using it at work, one of my co-workers asked if there way a way to extend the core functionality without having to modify the core file, or what he called hooking. now you could ofcourse and classes the extends form existing one but if someone wanted to add something to the, lets say base_model class, they would have to edit the file itself and that would mess up with upgrading the framework. is there a way to extend the allow people to extends the frameowrk core classes without having them edit the actual file? Quote Link to comment Share on other sites More sharing options...
dbo Posted March 22, 2008 Share Posted March 22, 2008 Personally I'm not a big fan of this concept. I believe in exposing what ever input/output capability you want via a quasi webservice API type deal. In my opinion it really helps keep the additional components as isolated pieces. I think its cleaner and minimizes dependencies. Quote Link to comment Share on other sites More sharing options...
Liquid Fire Posted March 23, 2008 Author Share Posted March 23, 2008 The only reason I would use web services is if i am offering a application but not the source code. If given a choose between using services or direct code, I would always choose direct code. Maybe i misunderstood what you meant but that sound like you say i should offer my framework functionality with service, is that wrong assumption? Quote Link to comment Share on other sites More sharing options...
dbo Posted March 23, 2008 Share Posted March 23, 2008 Thats the absolute right assumption. By making it available via webservices you are making people play by your rules. If you give them the core and they decide to change it you break your update path, etc. It's really the same type of logic used with input validation. Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted March 23, 2008 Share Posted March 23, 2008 Check out the observer pattern. Something like this: <?php class SomeClass { const STATUS_ZERO = 0; const STATUS_ONE = 1; const STATUS_TWO = 2; private $observers = array(); private $status; public function __construct() { $this->status = self::STATUS_ZERO; } public function getStatus() { return $this->status; } public function attach(SomeClass_Observer $observer) { if (!in_array($observer, $this->observers)) { $this->observers[] = $observer; } return $this; } public function detach(SomeClass_Observer $observer) { $numObservers = count($observers); for ($i = 0; $i <= $numObservers; $i++) { if ($this->observers[$i] === $observer) { unset($this->observers[$i]); break; } } return $this; } private function notify() { foreach ($this->observers as $observer) { $observer->hook($this); } } public function doSomething() { echo 'do something in ' . __METHOD__ . '()' . PHP_EOL; $this->status = self::STATUS_ONE; $this->notify(); echo 'do something else in ' . __METHOD__ . '()' . PHP_EOL; $this->status = self::STATUS_TWO; $this->notify(); } } interface SomeClass_Observer { public function hook(SomeClass $someClass); } class SomeClass_Observer_AnObserver implements SomeClass_Observer { public function hook(SomeClass $someClass) { switch ($someClass->getStatus()) { case SomeClass::STATUS_ONE: echo '[status 1] doing something in ' . __METHOD__ . '()' . PHP_EOL; break; case SomeClass::STATUS_TWO: echo '[status 2] doing something else in ' . __METHOD__ . '()' . PHP_EOL; break; } } } class SomeClass_Observer_AnotherObserver implements SomeClass_Observer { public function hook(SomeClass $someClass) { if ($someClass->getStatus() == SomeClass::STATUS_ONE) { echo '[status 1] doing something in ' . __METHOD__ . '()' . PHP_EOL; } } } $someClass = new SomeClass(); $someClass->attach(new SomeClass_Observer_AnObserver()) ->attach(new SomeClass_Observer_AnotherObserver()); $someClass->doSomething(); ?> Output: do something in SomeClass::doSomething() [status 1] doing something in SomeClass_Observer_AnObserver::hook() [status 1] doing something in SomeClass_Observer_AnotherObserver::hook() do something else in SomeClass::doSomething() [status 2] doing something else in SomeClass_Observer_AnObserver::hook() Quote Link to comment Share on other sites More sharing options...
Liquid Fire Posted March 23, 2008 Author Share Posted March 23, 2008 Thats the absolute right assumption. By making it available via webservices you are making people play by your rules. If you give them the core and they decide to change it you break your update path, etc. It's really the same type of logic used with input validation. maybe it is just mean but that is not the point of web services. The point of web services is to give other people access to data that they don't have direct access to(like amazon). The model related classes(2 of them) are the only thing that directly deals with data, everything else is need access to a server. I mean I don't know any other framework(RoR, Codeignitor, PHPCake) that don't offer the framework source but only off the functions of the framework through service but if there is any,. please let me know. I have have a look at the observer pattern. Quote Link to comment Share on other sites More sharing options...
dbo Posted March 23, 2008 Share Posted March 23, 2008 That's because its opensource, everything is available. I've used webservices for all kinds of stuff though. Yes it involves data but sometimes it's doing a calculations, etc not just granting access to some data. Quote Link to comment Share on other sites More sharing options...
Liquid Fire Posted March 23, 2008 Author Share Posted March 23, 2008 looking at the observer, it seems it would allow somethings but not exactly what i am looking for, it seems i can only extend functionality of existing functions but not add totally new functionality which is what i am looking for. for example I have a url_helper class and my boss wants a breadcrumb functionality for the site. Now while a breadcrumb is cool and all, i don't like it should be part of the core code. What i would like to be able to do it load a class that will allow me to do $url_helper->get_breadcrumb() without having to add inside the core url_helper class the method breadcrumb(). This way if I update the url_helper, they can update it without having to worry about added the function back in after the update. Is this possible? Quote Link to comment Share on other sites More sharing options...
maexus Posted March 23, 2008 Share Posted March 23, 2008 You are basicly talking about appending the class functionality without modifying the original class file? I could be off base but I don't believe this is possible in PHP Quote Link to comment Share on other sites More sharing options...
Liquid Fire Posted March 23, 2008 Author Share Posted March 23, 2008 basically yes, that it was i am looking for, i did not think it was directly possible but there might be some solution that simulates it. the only thing i can think of it <?php class url_helper { public function __call($function, $parameter) { //this allow plugin calls try { $class = get_class($this) . '_' . $function; $plugin = new $class(); //make all plugin have the object the are adding the plugin to as first parameter $parameters = array_merge(array($this), $parameters); call_user_func_array(array($plugin, 'invoke'), $parameters); unset($plugin); } catch(Exception $exception) { //not able to find plugin, should i throw exception or continue as normal? } } //class code } class url_helper_get_breadcrumbs { public function __construct() { } public function invoke() { //breadcrumb code } } $url_helper = new url_helper(); //this should call the url_helper_get_breadcrumbs->invoke function $url_helper->get_breadcrumbs(); ?> but not sure if it is the best way to do it. Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted March 24, 2008 Share Posted March 24, 2008 In that case, why couldn't the user of your framework not just extend the url_helper class? <?php class my_url_helper extends url_helper { function get_breadcrumbs() {} } ?> Quote Link to comment Share on other sites More sharing options...
Liquid Fire Posted March 24, 2008 Author Share Posted March 24, 2008 the reason is that the page controllers already have an instances of url_helper in them from the base class and the url_hepler is a singleton class so they would have to rewrite the way the instance is stored so it stores the new class and not the base class. I don't think this is going to be much of an issue, I don't think there should be wanting to add much to the core framework, only extend it with new classes. Quote Link to comment Share on other sites More sharing options...
Daniel0 Posted March 24, 2008 Share Posted March 24, 2008 I don't know if you're one of the people I've discussed the usage of singletons with, but this clearly shows how unneeded usage of the singleton pattern can transform from what seemed to be a convenience to an inconvenience. As you have uncovered yourself, the usage of a singleton has coupled your classes too tightly. Had your "base class" accepted an instance of url_helper passed to it by argument and ensured that it was an url_helper instance by using type hinting, then a child class (e.g. something like my_url_helper like I said above) would have been compatible with your framework/base class. For solving your problem, you could classes which would take an instance of url_helper and use url_helper::get_links() or whatever to generate the breadcrumbs or some other kind of extended functionality based on that of url_helper. Quote Link to comment Share on other sites More sharing options...
keeB Posted March 29, 2008 Share Posted March 29, 2008 I now understand the theme of your questions, Liquid Fire, and what you're trying to accomplish. I don't know if there's an equivalent in PHP, but I use Spring ( http://www.springframework.org/ ) in my professional life quite a bit. It's pretty amazing, albeit a bit verbose. Let's take the URL Helper mentioned above. As long as you have an interface URLHelper and a concrete implementation MyURLHelper , you should be able to rip MyURLHelperImpl out completely and make LiquidsURLHelperImpl which implements URLHelper without breaking anything. The process of 'swapping' would have to be handled via configuration files (the Spring way,) or some other method (your way) Quote Link to comment Share on other sites More sharing options...
Xeoncross Posted April 6, 2008 Share Posted April 6, 2008 You might also consider "plugin" calls at certain points in your code so that data can be access/updated from outside your classes without ever needing to change the core code. As a matter of fact, wordpress calls it's plugin calls "hooks". Quote Link to comment 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.