问题
I'm updating a PHP framework I've written. It used to just use a default behavior for routing. For example consider a case where the request goes to domain.com/package/controller/method
...
$url = ["package", "controller", "method"];
//Check if package exists...
//Check if controller exists in package...
//Check if method exists in controller...
This is all well and good, and works perfectly. However, I wanted to add some additional functionality to my router. That functionality being the ability to define custom routes, and pass an anonymous function which does whatever you want.
However, supposing that the request does not match any of the user-defined routes, I want to use the default functionality I have now to check if there are additional possible routes. That way I can update old projects with the new framework and not have them break, and additionally...I just like this default behavior because most of the time routes are not that complicated and defining routes feels like a violation of DRY to me.
The problem is that I don't want to pass the user-defined routes as an array to the object constructor. Rather, I want the user to call them as methods on the base application object similar to how laravel or express handles this.
The problem is that I want the default route checking to happen AFTER the user's defined routes have been checked not before. This quasi-code might help you understand what I mean...
class App
{
__construct
{
//Check Default Routing
}
private function get()
{
//Get Request
}
private function post()
{
//Post Request
}
private function put()
{
//Put Request
}
private function delete()
{
//Delete Request
}
}
app::get();
In the above case, the default routing would take place before the user-defined routes are called. I looked at the PHP consrtuctor/destructor page and learned about __destruct
. However, after reading this question I'm a little bit unsure this would work.
PHP.net says...
The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.
The first part of that explanation sounds like exactly what I want. I.E. as soon as all of the methods have been called on the application object, we'll run the __destruct
function which will check if the user-defined routes were fruitful, and if not, check if the default routing system yields any results.
The problem is that I'm not sure if this is bad practice, or simply won't work. Can I require a file, set my controller, and then call a method on that controller from within __destruct
? Are there limitations that would effect the code within these controllers? Supposing that there is a problem using __destruct
this way, what are my alternatives, keeping in mind I don't like either of these solutions...
- Having the user call the default routing as a method at the end of their script.
- Passing routes in as arrays to the constructor.
回答1:
I think you're confused here. Take note of this from the PHP Manual
The destructor method will be called as soon as there are no other references to a particular object, or in any order during the shutdown sequence.
To put this a different way, there's two reasons to call a destructor
- The class is being garbage collected. In other words, you've overwritten or
unset
all the references to the class instance. This means you can't directly call this class anymore - The PHP script has reached its end and the thread is shutting down.
In other words, there's nothing left for the class to do. But in your own statement you say this
The first part of that explanation sounds like exactly what I want. I.E. as soon as all of the methods have been called on the application object, we'll run the __destruct function which will check if the user-defined routes were fruitful, and if not, check if the default routing system yields any results.
There is no "and" here to work with. That's the point. In fact, there's very few places you would use this.
What you need is to think in layers. So you'd have a controller layer that you'd call to check the methods. In turn, that controller opens a new layer that checks user functions. That class or method should return something or throw an Exception
if it fails. On failure it can then try to use default methods. This is how you need to structure your program. Trying to use a destructor to do this would likely only confuse people. Make the data flow explicit, not implicit (which is what magic methods do).
来源:https://stackoverflow.com/questions/37802463/using-destruct-to-implement-default-routing