Richard Quadling
2014-07-22 08:58:51 UTC
Hi.
I'm developing a versioned REST-based API.
So. endpoints like ...
api.site.com/v1/controller/method/id/param1/param2/param3
api.site.com/v2/controller/method/id/param1/param2/param3
api.site.com/v3/controller/method/id/param1/param2/param3
Simple enough.
Internally, the code is structured such that the appropriate versioned
models are injected into the controller.
There is code that is specific to the version and code that is more
general, so, internally, there are namespaces ...
api\common
api\v1
api\v2
api\v3
In many cases (probably 60%), the version specific elements are nothing
more than wrappers for the common layer.
In some cases there is code in a version specific layer that requires a
version specific model...
namespace api\v1;
class ItemController extends api\Common\ItemController {
public function store(Item $o_Item) {
\\ Do store for v1.
\\...
\\ Let the parent have its say.
parent::store($o_Item);
}
}
Now the signature for the parent cannot have api\Common\Item or nothing as
the type hint.
And this is SO frustrating.
Basically, the common layer wants to know that the incoming objects match
(at least) the common layer.
And at the same time the version specific layer wants the incoming objects
to match (at least) the version specific layer.
Can I swap a v1 for a v2 at the version specific layer? No, of course not.
But at the common layer, certainly. As long as the version specific element
is based upon the common element.
What am I supposed to do to write common code AND be able to extend that
common code to version specificness and enforce that the appropriate types
are supplied?
The only way I can see is to create dummy interfaces and use them.
So, my base/common item implements iBaseItem and then no matter how this
gets extended, I can pass it through the layers and still have it enforced
appropriately.
In trying to understand why my code is NOT working I read this ...
I'm developing a versioned REST-based API.
So. endpoints like ...
api.site.com/v1/controller/method/id/param1/param2/param3
api.site.com/v2/controller/method/id/param1/param2/param3
api.site.com/v3/controller/method/id/param1/param2/param3
Simple enough.
Internally, the code is structured such that the appropriate versioned
models are injected into the controller.
There is code that is specific to the version and code that is more
general, so, internally, there are namespaces ...
api\common
api\v1
api\v2
api\v3
In many cases (probably 60%), the version specific elements are nothing
more than wrappers for the common layer.
In some cases there is code in a version specific layer that requires a
version specific model...
namespace api\v1;
class ItemController extends api\Common\ItemController {
public function store(Item $o_Item) {
\\ Do store for v1.
\\...
\\ Let the parent have its say.
parent::store($o_Item);
}
}
Now the signature for the parent cannot have api\Common\Item or nothing as
the type hint.
And this is SO frustrating.
Basically, the common layer wants to know that the incoming objects match
(at least) the common layer.
And at the same time the version specific layer wants the incoming objects
to match (at least) the version specific layer.
Can I swap a v1 for a v2 at the version specific layer? No, of course not.
But at the common layer, certainly. As long as the version specific element
is based upon the common element.
What am I supposed to do to write common code AND be able to extend that
common code to version specificness and enforce that the appropriate types
are supplied?
The only way I can see is to create dummy interfaces and use them.
So, my base/common item implements iBaseItem and then no matter how this
gets extended, I can pass it through the layers and still have it enforced
appropriately.
In trying to understand why my code is NOT working I read this ...
--
Richard Quadling
Richard Quadling