Skip to content

Commit

Permalink
Add more doc
Browse files Browse the repository at this point in the history
  • Loading branch information
bakura10 committed Dec 22, 2013
1 parent 0376fc9 commit 58a83e3
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 20 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ On the other hand, Apigility comes with a graphical user interface, versioning s
HAL, content negotiation... ZfrRest will never provide **all** those functionalities, so if you need them, just go
with Apigility.

The truth is that I actually don't really like Apigility's architecture, and it does not integrate *that* well with
Doctrine, so that's why I've created ZfrRest. Its scope is much more limited (although I'd really like to add support
for versioning and links), but I really think it's a nice product too. So give it a try to both products, and choose
the one you prefer!
ZfrRest's scope is much more limited (although I'd really like to add support for versioning and links), but I
really think it's a nice product too. So give it a try to both products, and choose the one you prefer!

## Documentation

Expand Down
35 changes: 19 additions & 16 deletions docs/02. Quick Start.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,16 @@ is a single item. For instance, if you reach the URL `/users/1`, what you actual
ZfrRest will therefore dispatch it to the controller defined in the `Resource` annotation (in this case,
`Application\Controller\UserController`).

On the other whant, when you reach the URL `/users`, you retrieve a **collection** of users, and ZfrRest uses the
On the other hand, when you reach the URL `/users`, you retrieve a **collection** of users, and ZfrRest uses the
info defined in the `Collection` annotation.

This difference is important and you must be confident with it.

The input filter (which can currently only be defined on the `Resource` annotation) is used whenever ZfrRest needs
to validate data. This typically occurs on POST and PUT operations.
to validate data, and is pulled from input filter plugin manager. This typically occurs on POST and PUT operations.

Finally, the hydrator is used for both creating an entity from POST/PUT data, and extracting entities to return the
payload to the client.
Finally, the hydrator (which is pulled from the hydrator plugin manager) is used for both creating an entity from
POST/PUT data, and extracting entities to return the payload to the client.

## Adding a route

Expand All @@ -132,21 +132,21 @@ return [
```

This code says to ZfrRest that we have an entry point whose URL is `/users`, and that the initial resource is a
Doctrine object repository (in this case, a User repository). Internally, ZfrRest uses the Doctrine Criteria API
to traverse the hierarchy, that's why we need an object that implements the `Doctrine\Common\Collections\Selectable`
interface.
Doctrine object repository. This service is pulled from the global servie manager. Internally, ZfrRest uses the
Doctrine Criteria API to traverse the hierarchy, that's why we need an object that implements
the `Doctrine\Common\Collections\Selectable` interface.

Add the following config, so that ZfrRest can properly retrieve the object repository:

```php
return [
'service_manager' => [
'factories' => array(
'factories' => [
'UserObjectRepository' => function($sm) {
$objectManager = $sm->get('doctrine.entitymanager.orm_default');
return $objectManager->getRepository('Application\Entity\User');
}
)
]
]
];
```
Expand All @@ -157,7 +157,8 @@ the scope of this quick start.
## Adding controllers

In our user mapping, we defined two controllers: `Application\Controller\UserController` and
`Application\Controller\UsersController`. Let's create them, and add them to your config:
`Application\Controller\UsersController` (remember that controllers are different for single resources and
collection resources!). Let's create them, and add them to your config:

```php
return [
Expand Down Expand Up @@ -232,21 +233,23 @@ class UserController extends AbstractRestfulController
}
```

One important thing to note: all ZfrRest controllers **must** extend `ZfrRest\Mvc\Controller\AbstractRestfulController`.
Note that ZfrRest controllers extend `ZfrRest\Mvc\Controller\AbstractRestfulController` (of course, nothing prevent
you from using a normal ZF2 controller for some actions).

As you can guess, each "action" is named after the corresponding HTTP method. ZfrRest is flexible enough that you can
add custom HTTP verbs.
add custom HTTP verbs by adding specific method handlers and more public methods in your controller.

The interesting thing is that, contrary to traditional ZF2 controllers, you receive a parameter in each method: the
actual resource (in this case, a User). You have nothing to do, this is done automatically by ZfrRest, so that your
controller is really clean. The only thing you need to do is passing the resource to the service for your business logic.
controller is really clean. The only thing you need to do is **passing the resource to the service for your
business logic**.

For the `put` method, you don't even need to manually validate the user data, because it has already been validated
using the input filter you specified in the mapping. If data would have been invalid, it would have returned a
400 Bad Request error, with the various error messages under the `errors` key.

Note that you should also return the `$user` object. If you return nothing, ZfrRest will just return a 200 status
code, but with an empty body.
Note that you should also return the `$user` object if you want ZfrRest extract the data. If you return nothing,
ZfrRest will just return a 200 status code, but with an empty body.

Now, let's see the `Application\Controller\UsersController` controller:

Expand Down Expand Up @@ -275,7 +278,7 @@ class UsersController extends AbstractRestfulController

public function get(Paginator $users)
{
$users->setCurrentPageNumber($this->params()->fromQuery('page'));
$users->setCurrentPageNumber($this->params()->fromQuery('page', 1));

return $users;
}
Expand Down
39 changes: 39 additions & 0 deletions docs/07. Cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,42 @@ may want to not return the `password` property.

All of this is done through the use of hydrators. You can use built-in ZF2 hydrators like `Zend\Stdlib\Hydrator\ClassMethods`,
but for most complex use cases, the best way is to simply create a custom hydrator, and personalize it.

## How to specify a custom hydrator?

ZfrRest uses hydrators both to hydrate incoming data (for example from POST and PUT requests) and to extract
data. For most advanced cases, you will likely need to define your own hydrators. ZfrRest pulls all the hydrators
from the ZF2 hydrator plugin manager.

Once your hydrator is defined, add it to the hydrator plugin manager using the following config:

```php
return [
'hydrators' => [
'invokables' => [
'Application\Hydrator\UserHydrator' => 'Application\Hydrator\UserHydrator'
]
]
];
```

## How to specify a custom input filter?

ZfrRest uses input filters to validate data when POSTing and PUTing data. ZfrRest pulls all the input filters from
the ZF2 input filter plugin manager.

Once your input filter is defined, add it to the input filter plugin manager using the following config:

```php
return [
'input_filters' => [
'invokables' => [
'Application\InputFilter\UserInputFilter' => 'Application\InputFilter\UserInputFilter'
]
]
];
```

## How to filter a collection using query params?

TBD
36 changes: 36 additions & 0 deletions docs/08. Mapping reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Mapping reference

## Annotations

To use annotations in your entities, you must import the `ZfrRest\Resource\Metadata\Annotation` namespace:

```php
use ZfrRest\Resource\Metadata\Annotation as REST;
```

### Resource

Allow to define mapping when a resource is accessed as a single resource.

Attributes:

* `controller`: FQCN of the controller (pulled from the controller plugin manager)
* `inputFilter`: FQCN of the input filter (pulled from the input filter plugin manager)
* `hydrator`: FQCN of the hydrator (pulled from the hydrator plugin manager).

### Collection

Allow to define mapping when a resource is accessed as a collection.

Attributes:

* `controller`: FQCN of the controller (pulled from the controller plugin manager)
* `hydrator`: FQCN of the hydrator (pulled from the hydrator plugin manager).

### Association

Only allowed at property level. It allows to make an association traversable.

Attributes:

* `path`: allow to customize the URI from which the association is accessible (default to the property's name)
6 changes: 6 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,9 @@ If you are looking for some information that is not listed in the documentation,
7. Cookbook
1. How to implement the OPTIONS method?
2. How to customize the payload?
3. How to specify a custom hydrator?
4. How to specify a custom input filter?
5. How to filter a collection using query params?

8. Mapping reference
1. Annotations

0 comments on commit 58a83e3

Please sign in to comment.