I've written a Controller and a corresponding Action for a Symfony 2.8 project, that does the following:
- handles a list of favorite items of a user
- the ids of the favorites are stored in the session
- multiple entites can be favorized
- possible actions on the favorite list are [add|remove]
- the controller's action is called via AJAX and returns a JSON object
My questions are:
- Can the PHP Code be optimized?
- Is this code DRY?
- Is this code safe?
- Is this too much logic for one action?
- Is it too much or not enough or even wrongly documented?
A few notes:
$this->getRepositoryName()
is a custom function from theAbstracController
base class that returns the correct repository name for a given entity- the returned JSON object is more then just the state of
success
, so the JavaScript can see, what exactly failed, if one ore more properties come back empty - I only need the favorites in the session for a filter later, they are not going to be stored or tracked using a database
class FavoritesController extends AbstractController
{
private $validEntites = ['entityA', 'entityB'];
private $validActions = ['add', 'remove'];
/**
* Can add or remove favorites to/from the list in the session.
*
* @Route("/handle-favorites", name="handle_favorites")
*
* @param Request $request
* @return \Symfony\Component\HttpFoundation\JsonResponse
*/
public function handleFavoritesAction(Request $request)
{
// initiate return value, will be send as JSON
$result = [
'success' => true,
'entity' => null,
'count' => null,
'id' => null,
'action' => null,
];
// test for XHR request
if(!$request->isXmlHttpRequest()) {
$result['success'] = false;
return new JsonResponse($result);
}
// retrieve values from session and create favorites array if necessary
$session = $request->getSession();
$favorites = $session->get('favorites');
if (!$favorites) {
$favorites = [];
foreach ($this->validEntites as $value) {
$favorites[$value] = [];
}
}
// get and test request parameters
$entity = $request->get('entity');
$id = $request->get('id');
$action = $request->get('action');
if (in_array($entity, $this->validEntites)) {
$result['entity'] = $entity;
} else {
$result['success'] = false;
}
if (in_array($action, $this->validActions)) {
$result['action'] = $action;
} else {
$result['success'] = false;
}
if (false !== filter_var($id, FILTER_VALIDATE_INT, array('options' => array('min_range'=> 1)))) {
$result['id'] = $id;
} else {
$result['success'] = false;
}
// add or remove item
if ($result['success']) {
if ('remove' === $action) {
$favorites[$entity] = array_diff($favorites[$entity], [$id]);
}
if ('add' === $action && !in_array($id, $favorites[$entity])) {
$repository = $this->getDoctrine()->getRepository($this->getRepositoryName(ucfirst($entity)));
$object = $repository->find($id);
if ($object) {
$favorites[$entity][] = $id;
} else {
$result['success'] = false;
$id = null;
$result['id'] = $id;
}
}
// update session
$session->set('favorites', $favorites);
}
// update count
$result['count'] = count($favorites[$entity]);
return new JsonResponse($result);
}
}