I am using FOSElasticaBundle with symfony2 and doctrine 2.
I have trouble understanding how to retrieve actual doctrine objets from a search result. I am under the impression that it is the default behaviour but I get this kind of result :
object(Elastica\Result)[1239]
protected '_hit' =>
array (size=5)
'_index' => string 'foodmeup' (length=8)
'_type' => string 'recipes' (length=7)
'_id' => string '2' (length=1)
'_score' => float 2.2963967
'_source' =>
array (size=5)
'name' => string 'Bavaroise vanille' (length=17)
'nickName' => string 'Bavaroise vanille' (length=17)
'content' => null
'userRecipes' =>
array (size=1)
...
'tags' =>
array (size=0)
Here is my FOSElasticaBundle configuration:
#Elastic Search
fos_elastica:
default_manager: orm
clients:
default: { host: localhost, port: 9200 }
indexes:
search:
client: default
index_name: foodmeup
types:
recipes:
mappings:
name: { type: string, boost: 5}
nickName: { type: string }
content: { type: string }
userRecipes:
type: "nested"
properties:
name: { type: string }
content: { type: string }
tags:
type: "nested"
boost: 5
properties:
name: { type: string }
persistence:
driver: orm
model: AppBundle\Entity\FoodAnalytics\Recipe
repository: AppBundle\Repository\FoodAnalytics\RecipeRepository
provider: ~
finder: ~
listener: ~ # by default, listens to "insert", "update" and "delete"
And the code in my controller :
public function searchAction(Request $request)
{
$search = $request->query->get('search');
$finder = $this->get('fos_elastica.index.search.recipes');
$results = $finder->search($search)->getResults();
return array(
'search' => $search,
'results' => $results
);
}
I understood I could use a custom repository method to get the objects, but before I reach that point, what is the default way to get objects ? (Here I want a Recipe Object, an instance of my model).
Thanks a lot !
Got it!
I called the wrong service. The correct controller code to retrieve directly object instances is:
public function searchAction(Request $request)
{
$search = $request->query->get('search');
$finder = $this->get('fos_elastica.finder.search.recipes');
$results = $finder->find($search);
return array(
'search' => $search,
'results' => $results
);
}
Related
I want intercept all errors of Symfony after that show them in JSON.
In friendsofsymfony/rest-bundle v2 I can set parameters
fos_rest:
exception:
enabled: true
exception_controller: 'App\Controller\ExceptionController::showAction'
...
But in V3 the parameter exception_controller is deleted.
My current config of FOS REST:
fos_rest:
view:
formats:
xml: false
json: true
view_response_listener: force
serializer:
groups: ['Default']
serialize_null: true
format_listener:
rules:
- { path: ^/api/v1, priorities: [ json ], fallback_format: json, prefer_extension: true }
exception:
enabled: true
Official manual say that should use handlers in JMS.
https://symfony.com/doc/current/bundles/FOSRestBundle/4-exception-controller-support.html
But it does not contain explanation how config set in yaml.
You can intercept all errors by a symfony subscriber
<?php
declare(strict_types=1);
namespace App\Util\Serializer\Normalizer;
use JMS\Serializer\Context;
use JMS\Serializer\GraphNavigatorInterface;
use JMS\Serializer\Handler\SubscribingHandlerInterface;
use JMS\Serializer\JsonSerializationVisitor;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
class CustomExceptionHandler implements SubscribingHandlerInterface
{
private bool $debug;
public function __construct(bool $kernelDebug)
{
$this->debug = $kernelDebug;
}
public static function getSubscribingMethods(): array
{
return [
[
'direction' => GraphNavigatorInterface::DIRECTION_SERIALIZATION,
'format' => JsonEncoder::FORMAT,
'type' => \Exception::class,
'method' => 'serializeToJson',
'priority' => -1,
],
];
}
public function serializeToJson(
JsonSerializationVisitor $visitor,
\Exception $exception,
array $type,
Context $context
) {
$data = $this->convertToArray($exception, $context);
return $visitor->visitArray($data, $type);
}
/**
* #return array<string, mixed>
*/
protected function convertToArray(\Exception $exception, Context $context): array
{
$statusCode = null;
if ($context->hasAttribute('template_data')) {
$templateData = $context->getAttribute('template_data');
if (array_key_exists('status_code', $templateData)) {
$statusCode = $templateData['status_code'];
}
}
$data['error'] = $this->getMessageFromThrowable($exception, $statusCode);
return $data;
}
protected function getMessageFromThrowable(\Throwable $throwable, ?int $statusCode): string
{
if ($this->debug) {
return $throwable->getMessage();
}
return array_key_exists($statusCode, Response::$statusTexts) ? Response::$statusTexts[$statusCode] : 'error';
}
}
services.yaml
App\Utils\Serializer\Normalizer\CustomExceptionHandler:
$kernelDebug: '%kernel.debug%'
I use Elasticsearch with Foselasticabundle to search in my Symfony app, but it returns empty results.
This is my config and search method:
foselasticbunde.yml:
indexes:
search:
finder: ~
client: default
types:
course:
mappings:
id: ~
title: ~
persistence:
driver: orm
model: AppBundle\Entity\Course
finder: ~
provider: ~
listener: ~
SearchController.php
public function elasticSearchAction(Request $request)
{
$query = $request->get('q');
$finder = $this->container->get('fos_elastica.finder.search.course');
$results = $finder->find($query);
return new JsonResponse($results);
}
But it returns this empty results:
[{},{},{},{},{},{},{},{},{},{}]
Whats the problem and how can I fix it?
Results is an array of objects, I changed my code:
public function elaSearchAction(Request $request)
{
$query = $request->get('q');
$finder = $this->container->get('fos_elastica.finder.search.course');
$results = $finder->find($query);
$data = array();
foreach ($results as $course){
$data[] = array(
'id' => $course->getId(),
'title' => $course->getTitle(),
'description' => $course->getDescription(),
);
}
return new JsonResponse($data);
}
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 am trying to generate CRUD of the entities but i have a few questions, i don't know if it's a normal comportment or an error.
I apply the command :
I am adding the route in routing.yml like asking.
Now, when i am testing this crud , just create party work.
Update doesn't working, it's updateAction :
public function updateAction(Request $request, $id)
{
$em = $this->getDoctrine()->getManager();
$entity = $em->getRepository('IFppoGestionPersonnelBundle:TableTest')->find($id);
if (!$entity) {
throw $this->createNotFoundException('Unable to find TableTest entity.');
}
$deleteForm = $this->createDeleteForm($id);
$editForm = $this->createEditForm($entity);
$editForm->handleRequest($request);
if ($editForm->isValid()) {
$em->flush();
return $this->redirect($this->generateUrl('tabletest_edit', array('id' => $id)));
}
return $this->render('IFppoGestionPersonnelBundle:TableTest:edit.html.twig', array(
'entity' => $entity,
'edit_form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
I don't know why it doesn't add "em->persist($entity)", but if i add this line , it does not update ...
I have same errors with deleteAction.
And when i am creating a new tuple, and back to list , the last tuple is not displaying.
It's maybe an error to the class :
IFppo\GestionPersonnelBundle\Entity\TableTest:
type: entity
table: tabletest
fields:
id:
type: integer
id: true
generator:
strategy: AUTO
nom:
type: string
length: 255
column: nom
prenom:
type: string
length: 255
column: prenom
lifecycleCallbacks: { }
In log, i don't have any trace of update ...
[EDIT] When writing to the log for any errors, return an empty array with $editForm->getErrors() and with $editForm->getErrorsAsString() return :
nom: No errors prenom: No errors submit: No errors [] []
Thanks a lot.
I'm trying turn off translator cache by this way:
app/config/config.yml
services:
translator.default:
class: %translator.class%
arguments: [ #service_container, #translator.selector, {}, { cache_dir: null, debug: %kernel.debug% }, #?session ]
The cached code in cache/dev/appDevDebugProjectContainer.php should be:
protected function getTranslator_DefaultService()
{
$this->services['translator.default'] = $instance = new \Symfony\Bundle\FrameworkBundle\Translation\Translator($this, new \Symfony\Component\Translation\MessageSelector(), array('translation.loader.php' => 'php', 'translation.loader.yml' => 'yml', 'translation.loader.xliff' => 'xliff'), array('cache_dir' => NULL, 'debug' => true), $this->get('session'));
... resources ...
return $instance;
}
But i get followed code:
protected function getTranslator_DefaultService()
{
return $this->services['translator.default'] = new \Symfony\Bundle\FrameworkBundle\Translation\Translator($this, new \Symfony\Component\Translation\MessageSelector(), array('translation.loader.db' => 'db', 'translation.loader.php' => 'php', 'translation.loader.yml' => 'yml', 'translation.loader.xliff' => 'xliff'), array('cache_dir' => NULL, 'debug' => true), $this->get('session'));
}
So translator resources is empty.
One way to do this is:
Edit symfony/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php and add a method:
public function setOption($option, $value)
{
$this->options[$option] = $value;
}
In your AppKernel.php override a method:
public function boot()
{
parent::boot();
$this->container->get('translator')->setOption('cache_dir', null);
}