-
Notifications
You must be signed in to change notification settings - Fork 651
WP_JSON_Controller POC #556
Conversation
They're intended to be overridden
plugin.php
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WP-API/amigos what's the best way to register the route to the server? how do we want to handle route attributes like arguments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WP-API/amigos what's the best way to register the route to the server? how do we want to handle route attributes like arguments?
We could move it to being a property on the server rather than just generated at runtime. I think we may have to.
Agreed on abstract here. |
|
If you guys and gals are cool with the general direction, I'd like to merge as is so we can continue to iterate on it |
|
Question, abstract public static function prepare_item_for_response( $item );I don't think this is valid, you can't define abstract static methods. abstract class Foo {
abstract public static function parse($data);
}
class Bar extends Foo {
public static function parse( $data ) {
var_dump($data);
}
}
Bar::parse("test");That gave me this error when testing on PHPTester Yeah when I test this locally I get a strict standards error. |
You are correct. Updated in 867a624 |
plugin.php
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems there is no state that is created with this instance, which may be a more general comment on WP_JSON_Taxonomy_Terms_Controller. It seems all those methods can be called statically, and therefore I'd say probably should be.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I figured you were going to say this. I feel like core typically strays away from static functions, but a quick ack says there are some uses.
@nacin do you have a preference?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I agree. You can call static functions as an instance if you want, you just have to make sure you use static / self instead of $this, which I think it technically nicer anyway, as it mean you can't "sneak" any state into the object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would the use case be for it being a static function?
Will it need to be used at sometime when we couldn't just create an instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@TimothyBJacobs You can call a static function as if it were a normal method on the class, but you can't do the other way around. The advantage is you don't need to create an instance if we make the method static. If you subclass any of these classes, you have the choice if you want to create instances and use state within that object, and the fact the parent methods are statically declared won't affect you at all. It's not the same if we make the base classes require state, and therefor all subclassing will require instantiation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if we can't define abstract static methods, we have no way of enforcing type.
That is true - if you are extending the base controller, extending anything else doesn't give you this enforcement anyway as the parent has implemented the method anyway. But yeah, I see what you are saying.
Further, I don't think using state would be as easy as you make it seem once those methods are static. If the API assumes that those methods are static, you'd have to do a lot of back twisting to introduce state within that object, without resorting to some sort of singleton pattern.
The API wouldn't be making that assumption. It's purely up to the callback (this class in this case) whether it chooses to pass an instantiated object or the class name the API registered route. The point is the API doesn't need anything to use as a route controller to have state - everything is passed to the specific method just as get_items that you need to handle the request.
I'm happy to go with using instantiation if that can practically make things easier - however we need to make sure cross calling Endpoint Controllers is easy - I don't want to have to instantiate a WP_JSON_Taxonomy_Controller and set up a bunch of stuff to re-use get_items, my idea with keeping the methods static would mean it would always be easier to cross call as it means you have to pass everything that's required to the method, as it's "not allowed" to use state. Maybe we can just be careful when writing the methods that it's still easy to re-use internally to solve that.
In all of this, I actually don't see any need for any state across the controller which is why maybe I am making it out to be easier than you think it would be to achieve this. I see the controller class as a means of wrapping up related callback handlers and giving us subclassing to give us some DRYness, but for most intents and purposes they are self contained functions rather than instance methods to act on the data of the object (ala OOP principles).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To achieve the same effect as abstract static, what if the base class methods returned HTTP 403 (Forbidden) or (405 Method Not Allowed) by default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielbachhuber I think that would depend what purpose we want abstract. If it's to enforce the developer to create the method, and therefor throw a fatal error if it hasn't been declared - we'd need static still.
If on the other hand we just want a response, then it would cover that use case. However, that also depends if just subclassing / instantiating the object would also register the endpoint. If you also have to register your endpoint manually anyway - you wouldn't add the methods you hadn't implemented anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're going stateless with static methods for now 0ffe9fa Endpoints shouldn't persist state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@danielbachhuber That would definitely solve the type enforcement, but extending would still be a bit difficult.
@joehoyle I see your point, in terms of the callback not needing to be part of the class structure, and just needs to be callable.
We could benefit, though, from having a class structure.
We could do something like this.
if callback is array AND object instance of base class
proceed like normal
otherwise
we can attach the passed callable function into a class called WP_JSON_Controller_Callable
This way we can store all of the routes easily inside of an array in the server, and call the correct methods depending on what request was passed.
Does that make sense?
Then it would also make perfect sense for the default for those methods to return a 403 or 405.
|
Dig it, nice job. Couple of notes, but I think this is very clear and the right direction. I'll let @rmccue chime in on the registering server portion. For the |
I'm split on this currently. I understand perceived improvement of not including For the immediate future, in the interest of simplicity, I think we should just proceed with including the namespace in the URL. We can loop back on this. |
|
Makes sense, I think either way we want want to register using the "wp" namespace, if we just didn't want it in the URL we could shortcut that in the regex building. |
Conceptually, this means routes are registered once, and not each time dispatch() is called
Endpoints aren't intended to persist state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For all of our errors, should we start passing them through translation? If so, we might want to use the same strings as core for those, e.g. __('Invalid taxonomy')?
|
Dropping this in so we can iterate on it. |
Use @joe_hoyle's proposal from #551 to register the new taxonomy terms controller introduced in #549