14/06/2015 - SYMFONY
Bu örnekte symfony ile API şeklinde olan temel bir proje oluşturmayı göreceğiz. Bu tarz genelde AJAX kullanan projeler için idealdir. Json istek gelir, json sonuç geri verilir. İsteklerin doğrulanma kuralları, model class içinde belirtilmiştir. Form type kullanılmamaktadır. Json serialisation ve deserialisation işlemi, abstract controller içinde, JMS serialiser bundle yardımı ile yapılır. Serialise edilmiş olan classın propertyleri, Doctrine_Inflector ile "tableise" haline getirilir (örnek: $fullName => full_name).
namespace Application\BackendBundle\Controller;
use Doctrine\Common\Inflector\Inflector;
use JMS\Serializer\SerializationContext;
use JMS\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
abstract class AbstractController
{
protected $serializer;
protected $validator;
protected $inflector;
public function __construct(
SerializerInterface $serializer,
ValidatorInterface $validator,
Inflector $inflector
) {
$this->serializer = $serializer;
$this->validator = $validator;
$this->inflector = $inflector;
}
/**
* @param string $responseData
* @param int $status
*
* @return Response
*/
protected function createJsonResponse($responseData = '', $status = 200)
{
$context = new SerializationContext();
$context->setSerializeNull(false);
$jsonResponse = $this->serializer->serialize($responseData, 'json', $context);
return (new Response(
$jsonResponse,
$status,
['Content-Type' => 'application/json']
));
}
/**
* @param $errors
* @param int $status
*
* @return Response
*/
protected function createJsonErrorResponse($errors, $status = 400)
{
$errorData = ['errors' => []];
foreach ($errors as $error) {
if ($error instanceof ConstraintViolationInterface) {
$preparedError = $this->getErrorFromValidation($error, $errorData);
} else {
$preparedError = ['key' => count($errorData['errors']), 'value' => $error];
}
$errorData['errors'][$preparedError['key']] = $preparedError['value'];
}
return $this->createJsonResponse($errorData, $status);
}
/**
* @param string $content
* @param string $class
*
* @return mixed|Response
*/
protected function validate($content, $class)
{
$content = $this->serializer->deserialize(
$content,
$class,
'json'
);
$errors = $this->validator->validate($content);
if (count($errors)) {
return $this->createJsonErrorResponse($errors);
}
return $content;
}
/**
* @param ConstraintViolationInterface $error
*
* @return mixed
*/
private function getErrorFromValidation($error)
{
$properties = $this->inflector->tableize($error->getPropertyPath());
return ['key' => $properties, 'value' => $error->getMessage()];
}
}
namespace Application\BackendBundle\Controller;
use Application\BackendBundle\Service\UserServiceInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use JMS\Serializer\SerializerInterface;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Doctrine\Common\Inflector\Inflector;
/**
* @Route("user", service="application_backend.controller.user")
*/
class UserController extends AbstractController
{
const ROUTER_PREFIX = 'application_backend_user_';
private $router;
private $userService;
public function __construct(
SerializerInterface $serializer,
ValidatorInterface $validator,
Inflector $inflector,
RouterInterface $router,
UserServiceInterface $userService
) {
parent::__construct($serializer, $validator, $inflector);
$this->router = $router;
$this->userService = $userService;
}
/**
* @param Request $request
*
* @Route("")
* @Method({"GET"})
*
* @return Response
*/
public function listAction(Request $request)
{
$page = $request->query->get('page', 1);
$limit = $request->query->get('limit', 2);
return $this->createJsonResponse("USER list: $page - $limit");
}
/**
* @param Request $request
*
* @Route("")
* @Method({"POST"})
*
* @return Response
*/
public function createAction(Request $request)
{
$user = $this->validate(
$request->getContent(),
'Application\BackendBundle\Model\User\Create'
);
if ($user instanceof Response) {
return $user;
}
return $this->createJsonResponse("USER create");
}
}
services:
doctrine_common_inflector:
class: Doctrine\Common\Inflector\Inflector
services:
application_backend.controller.abstract:
class: Application\BackendBundle\Controller\AbstractController
abstract: true # Abstract enabled
arguments:
- @serializer # Enabled by JMS Serializer Bundle
- @validator # Enabled by the application by default
- @doctrine_common_inflector # Enabled by user
application_backend.controller.user:
class: Application\BackendBundle\Controller\UserController
parent: application_backend.controller.abstract # Parent abstract class
arguments:
- @router # Compulsory for urls
- @application_backend.service.user # User service
Install "jms/serializer-bundle": "0.13.0"
ve new JMS\SerializerBundle\JMSSerializerBundle()
satırını AppKernel.php dosyası içindeki $bundles
arrayına ekleyin.
namespace Application\BackendBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
/**
* @ORM\Entity(repositoryClass="Application\BackendBundle\Repository\UserRepository")
* @ORM\Table(name="user")
* @UniqueEntity(fields="username", message="Username is already in use.")
*/
class User
{
/**
* @var int
*
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(name="username", type="string", length=20, unique=true)
*/
protected $username;
/**
* @ORM\Column(name="password", type="string", length=40)
*/
protected $password;
}
namespace Application\BackendBundle\Model\User;
use JMS\Serializer\Annotation as Serializer;
use Symfony\Component\Validator\Constraints as Assert;
class Create
{
/**
* @var string
*
* @Assert\NotBlank(message="Username is required")
* @Assert\Length(
* min="6", minMessage="Username cannot be less than {{ limit }} characters.",
* max="20", maxMessage="Username cannot be longer than {{ limit }} characters."
* )
*
* @Serializer\Type("string")
*/
public $username;
/**
* @var string
*
* @Assert\NotBlank(message="Password is required")
*
* @Serializer\Type("string")
*/
public $password;
}
Postman browser extension kullanarak aynı testleri yapabilirsiniz.