I am sure it is a small error but I cannot find it.
I am trying to follow the official doc and implement an event listener on the pre_serialize event.
My service declaration:
<service id="app.question_serializer_subscriber" class="AppBundle\Serializer\QuestionSerializerSubscriber">
<tag name="jms_serializer.event_subscriber"/>
</service>
My subscriber:
<?php
namespace AppBundle\Serializer;
use JMS\Serializer\EventDispatcher\EventSubscriberInterface;
use JMS\Serializer\EventDispatcher\ObjectEvent;
class QuestionSerializerSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.pre_serialize',
'method' => 'onPreSerialize',
)
);
}
public function onPreSerialize(ObjectEvent $event)
{
die('in event');
}
}
And my controller:
$question = $repo->findLastVersionByQuestionId((int) $questionId);
$serializer = SerializerBuilder::create()->build();
$context = new SerializationContext();
return new JsonResponse(json_decode(
$serializer->serialize(
$question,
'json',
$context
),
true
));
When I access the route my entity Question is serialized and displayed, but why does the die('in event'); is not displayed ?
Maybe it has a relation with the fact that my object is a Doctrine entity (issue 666 or PR 677 )
I finally find the issue. The problem is
$serializer = SerializerBuilder::create()->build();
This does not work but this does:
$serializer = $this->get('jms_serializer');
Try adding the class attribute, as example:
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.pre_serialize',
'class' => 'FQCN_class_name',
'method' => 'onPreSerialize',
)
);
}
Another difference regarding the doc is in the argument of the class method: you should use PreSerializeEvent instead of ObjectEvent:
So like this:
public function onPreSerialize(PreSerializeEvent $event)
{
// ...
}
Check your service is correctly load from the container as example with the console command:
php app/console debug:container --tag=jms_serializer.event_subscriber
Hope this help
Related
I made a search form in order to get events list. This form is displayed in front/search.html.twig. When I submit the search form, I'd like it leads me to front/events.html.twig.
When I submitted it, it says "category" doesn't exist. I don't have this problem when I replaced
return $this->redirectToRoute('events', $data);
with
return $this->render('front/events.html.twig', $data);
but I wish to use to route "events"...
This is my EventsController.php file :
<?php
namespace App\Controller\Front;
use App\Form\SearchType;
use App\Repository\EventsRepository;
use App\Repository\CategoriesRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class EventsController extends AbstractController
{
#[Route('/search', name: 'search')]
public function search(Request $request, SessionInterface $sessionInterface)
{
$data = $request->request->all();
$sessionSearchFormData = $sessionInterface->get('searchFormData');
$form = $this->createForm(SearchType::class, ['data' => $sessionSearchFormData]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
$sessionInterface->set('searchFormData', $data);
return $this->redirectToRoute('events', $data);
}
return $this->renderForm('front/search.html.twig', [
'form' => $form
]);
}
#[Route('/events', name: 'events')]
public function events(
EventsRepository $eventsRepository,
CategoriesRepository $categoriesRepository
){
$events = $eventsRepository->findAll();
$categories = $categoriesRepository->findAll();
return $this->render("front/events.html.twig", ['events' => $events, 'categories' => $categories]);
}
}
Bonjour Emilie,
Your route events does not have parameters. So you can't redirect it using parameters.
you can try something like this :
public function index($name)
{
return $this->redirectToRoute('events', ['max' => 10]);
}
You can forward to another Controller :
public function index($name)
{
$response = $this->forward('App\Controller\OtherController::fancy', [
'name' => $name,
'color' => 'green',
]);
// ... further modify the response or return it directly
return $response;
}
Regards,
hous has found the solution :
The second parameter must be an array :
return $this->redirectToRoute('events', [$data]);
I have a REST API and have an Entity Userwith field called Avatar, in DB I save name XXXX.jpg but when I return I want to add a url in this field Avatar, for example www.mylink.com/XXXX.jpg.
I'm trying with a service implements SubscribingHandlerInterfacebut I don't know how I can use it.
I have this method in this service:
class UrlManager implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
return array(
array(
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'json',
'type' => 'AppBundle/Entity/User',
'method' => 'serializeUrlAvatar',
),
);
}
public function serializeUrlAvatar(User $user)
{
$url = 'www.mylink.com';
return array(
"avatar" => $url . $user->getAvatar()
);
}
}
but how can I call this service to modify url when I serialize.
Now I do this:
$_format = 'json';
$json = $this->get('jms_serializer')->serialize($user, $_format);
return new Response($json, 200, ['Content-Type' => 'application/' . $_format]);
In service.yml:
app.url_converter_service:
class: AppBundle\Service\UrlManager
tags:
- { name: jms_serializer.subscribing_handler }
Update
In my controller I call this function like this:
$result = $this->get('app.url_converter_service')->serializeUrlAvatar($user);
$json = $this->get('jms_serializer')->serialize($result, $_format);
return new Response($json, 200, ['Content-Type' => 'application/' . $_format]);
So my question is, exists a way to remove the first line and serialize correctly (add the url) when I serialize?
Have you registered your service like this?
# app/config/services.yml
avatar_url_handler:
class: YourBundle\Serializer\Handler\AvatarUrlHandler
tags:
- { name: jms_serializer.subscribing_handler }
I found a solution. I create a service which implements EventSubscriberInterface like this:
class UserSerializeHandler implements EventSubscriberInterface
{
private $user_uploads;
public function __construct($user_uploads){
$this->user_uploads = $user_uploads;
}
public static function getSubscribedEvents()
{
return array(
array(
'event' => 'serializer.pre_serialize',
'class' => User::class,
'method' => 'onPreSerializeUser'
));
}
public function onPreSerializeUser(PreSerializeEvent $event)
{
/** #var User $user */
$user = $event->getObject();
$avatar = $user->getAvatar();
$user->setAvatar($this->user_uploads . "/" . $avatar);
}
}
In service.yml:
app.serializer_user_service:
class: AppBundle\Service\UserSerializeHandler
arguments: ['%user_uploads%']
tags:
- { name: jms_serializer.event_subscriber }
I have user_uploads in parameters.yml like this:
user_uploads: 'https://myUrl.com'
And in any Controller that I serialize a User, I add the url in the Avatar paramter.
$json = $this->get('jms_serializer')->serialize($user, $_format);
return new Response($json, 200, ['Content-Type' => 'application/' . $_format]);
I'm looking to create a twig extension but Symfony keeps telling me my function is unknown.
Here is my class:
<?php
namespace AppBundle\Twig\Extension;
use Twig_Extension;
use Twig_SimpleFunction;
class FormExtension extends Twig_Extension
{
public function getFonctions()
{
$twigClass = 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode';
$options = array(
'node_class' => $twigClass,
'is_safe' => ['html']
);
return array(
'form_color' => new Twig_SimpleFunction($this, null, $options)
);
}
public function getName()
{
return 'app_form_extension';
}
}
And here is the service declaration in AppBundle\Resources\config\services.yml
services:
app.form_extension:
class: AppBundle\Twig\Extension\FormExtension
tags:
- { name: twig.extension }
I'm probably missing somehing but I can't find out what. Please help!
Correct getFonctions to getFunctions
Try this way:...
return array(
new Twig_SimpleFunction('form_color', null, $options)
);
...
For me same error was when I added my function to getFilters() instead of getFunctions()
I am attempting to use a custom handler for JMS Serializer Bundle
class CustomHandler implements SubscribingHandlerInterface
{
public static function getSubscribingMethods()
{
return array(
array(
'direction' => GraphNavigator::DIRECTION_SERIALIZATION,
'format' => 'json',
'type' => 'integer',
'method' => 'serializeIntToJson',
),
);
}
public function serializeIntToJson(JsonSerializationVisitor $visitor, $int, array $type, Context $context)
{
die("GIVE ME SOMETHING");
}
}
This does nothing, and does not die. This is how I am registering the handler
$serializer = SerializerBuilder::create()
->configureHandlers(function(HandlerRegistry $registry) {
$registry->registerSubscribingHandler(new MyHandler());
})
->addDefaultHandlers()
->build();
$json = $serializer->serialize($obj, 'json');
My handler is never called and I cannot manipulate the data on serialisation.
You need to create a service for this handler:
custom_jms_handler:
class: MyBundle\Serializer\CustomHandler
tags:
- { name: jms_serializer.subscribing_handler }
Then make sure you use the registered JMS serializer service
$json = $this->get('jms_serializer')->serialize($obj, 'json');
I have this which works
$serializer = SerializerBuilder::create()
->configureListeners(function(EventDispatcher $dispatcher) {
$dispatcher->addSubscriber(new ProjectSubscriber($this->container));
$dispatcher->addSubscriber(new UserSubscriber($this->container));
})
->addDefaultListeners()
->addMetadataDir(realpath($this->get('kernel')->getRootDir()."/../") . '/src/Jake/NameOfBundle/Resources/config/serializer')
->build();
return $serializer->serialize($project, 'json');
$project is my entity.
You can omit this line if you don't have serializer configs
->addMetadataDir(realpath($this->get('kernel')->getRootDir()."/../") . '/src/Jake/NameOfBundle/Resources/config/serializer')
I think my main issue was this ->addDefaultListeners().
In config.yml I have
jms_serializer:
metadata:
auto_detection: true
directories:
NameOfBundle:
namespace_prefix: ""
path: "#JakeNameOfBundle/Resources/config/serializer"
I don't have anthing set up to make JMS a service.
I have a basic ZF2 InputFilter that I created. How exactly do I test it with PHPUnit without attaching it to a Form?
I can't find any sample on how this is done. Hope someone can help out.
I usually have a data provider to test my input filters.
Here's an example input filter with two really simple fields:
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Input;
use Zend\I18n\Validator\Alnum;
class MyInputFilter extends InputFilter
{
public function __construct()
{
$name = new Input('name');
$name->setRequired(false)->setAllowEmpty(true);
$this->add($name);
$nickname = new Input('nickname');
$nickname->getValidatorChain()->attach(new Alnum());
$this->add($nickname);
}
}
And here's a test class for it:
class MyInputFilterTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
$this->inputFilter = new MyInputFilter();
}
/** #dataProvider validatedDataProvider */
public function testValidation($data, $valid)
{
$this->inputFilter->setData($data);
$this->assertSame($valid, $this->inputFilter->isValid());
}
public function validatedDataProvider()
{
return array(
array(
array(),
false
),
array(
array('name' => '', 'nickname' => 'Ocramius'),
true
),
array(
array('name' => 'Test', 'nickname' => 'Ocramius'),
true
),
array(
array('name' => 'Test', 'nickname' => 'Hax$or'),
false
),
);
}
}
This is a very simple example, but I am basically throwing different datasets at the filter and checking what is relevant to me (in this case checking that data is valid or invalid).
If your filter applies transformations on the data, you may also want to check what the output of $inputFilter->getValues() is.
If the error messages are relevant to you, you can also check $inputFilter->getMessages().