Custom exception with fosrest bundle in symfony2 - symfony

Hi I am trying to add custom exception but it is not working
now my response is like:(also the breakdown debuger is not trigger that class)
{
"error": {
"code": 500,
"message": "Required Parameter Missing"
}
}
this is the default exception of fos rest
I added new class that wrapp the exception
class ExceptionWrapperHandler implements ExceptionWrapperHandlerInterface {
public function wrap($data)
{
$exception = $data['exception'];
$newException = array(
'success' => false,
'exception' => array(
'exceptionClass' => $exception->getClass(),
'message' => $data['status_text']
)
);
return $newException;
}
}
my config file:
fos_rest:
param_fetcher_listener: true
body_listener: true
format_listener: true
routing_loader:
default_format: json
view:
view_response_listener: force
formats:
json: true
xml: true
templating_formats:
html: false
# exception_wrapper_handler: CLASS path
exception:
enabled: true
service:
exception_handler: appname.exception_handler
serializer: jms_serializer.serializer
serializer:
serialize_null: true

You need to add your Exception class to the exception.messages array in your fos_rest config in your config.yml for it to show your custom message
fos_rest:
exception:
enabled: true
messages:
'AppBundle\ExpeptionHandler\ ExceptionWrapperHandler': true

Related

Symfony Easyadmin choice type field for roles

I use easyadmin, I wish for the field "role" display the choice of roles in a field type "radio" but an error (array to string conversion) of this type occurs (see image below):
Notice: Array to string conversion
here is my config:
easy_admin:
entities:
User:
class: AppBundle\Entity\User
form:
fields:
- { property: 'username' }
- { property: 'email' }
- { property: 'enabled' }
- property: 'plainPassword'
type: 'repeated'
type_options:
type: Symfony\Component\Form\Extension\Core\Type\PasswordType
required: false
first_options: { label: '%label.password%' }
second_options: { label: '%label.password_confirmation%' }
invalid_message: fos_user.password.mismatch
- property: 'roles'
type: 'choice'
type_options:
mapped: true
expanded: true
multiple: false
choices: { 'Conseiller': 'ROLE_USER', 'Administrateur': 'ROLE_ADMIN' }
Someone would have a solution to offer me so that I can display radio buttons with easyadmin?
thanks in advance
#johan-rm what you did was almost correct.
In fact you can't use radio buttons for roles because roles (see the s) is multiple choice field. You need to use check boxes (or a mulitple select).
In your code, the only thing that was wrong was this part: multiple: false.
If you try to map an array to a single choice field, you are trying to map an array to a string, hence the error.
Just change multiple: false to multiple: true.
This is the result:
easy_admin:
entities:
User:
class: AppBundle\Entity\User
form:
fields:
- { property: 'username' }
- { property: 'email' }
- { property: 'enabled' }
- property: 'plainPassword'
type: 'repeated'
type_options:
type: Symfony\Component\Form\Extension\Core\Type\PasswordType
required: false
first_options: { label: '%label.password%' }
second_options: { label: '%label.password_confirmation%' }
invalid_message: fos_user.password.mismatch
- property: 'roles'
type: 'choice'
type_options:
mapped: true
expanded: true
multiple: true
choices: { 'Conseiller': 'ROLE_USER', 'Administrateur': 'ROLE_ADMIN' }
Here's a solution in Symfony 3.4 to this (uses Yes/No dropdown) that might help:
in config.yml
imports:
...
- { resource: easyAdmin.yml }
in easyadmin.yml
fields:
...
- property: 'hasRoleAdmin'
label: 'Is admin?'
type: choice
type_options:
choices:
'No': 'No'
'Yes': 'Yes'
in User entity:
public function hasRoleAdmin()
{
return ($this->hasRole('ROLE_ADMIN')) ? 'Yes' : 'No';
}
public function setHasRoleAdmin($isAdmin)
{
if ('Yes' === $isAdmin && 'No' === $this->hasRole('ROLE_ADMIN')) {
$this->addRole('ROLE_ADMIN');
}
if ('No' === $isAdmin && 'Yes' == $this->hasRole('ROLE_ADMIN')) {
$this->removeRole('ROLE_ADMIN');
}
$this->isAdmin = $isAdmin;
}

MonologBundle FingerCrossedHandler: how to configure excluded_404s

I'm working on a Symfony 2.8.6 application and I tried to configure my Monolog as described here and here.
This is my Monolog config (bundle version 2.11.1):
monolog:
handlers:
main_critical:
type: fingers_crossed
action_level: error
handler: grouped
channels: ["!doctrine", "!event", "!php"]
excluded_404s:
- ^/
grouped:
type: group
members: [streamed, crash, buffered]
streamed:
type: rotating_file
max_files: 10
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: notice
crash:
type: rotating_file
max_files: 10
path: "%kernel.logs_dir%/%kernel.environment%.critical.log"
level: critical
buffered:
type: buffer
handler: swift
swift:
type: swift_mailer
from_email: noreply#xxxxxxx.com
to_email: user#xxxxx.com
subject: "[App] - Errore %kernel.environment%"
level: error
Monolog logs every 404 error, also missing assets like css and js.
How can avoid this?
Where I'm wrong?
Maybe the problem is related with my ExceptionListener?
/**
* #param GetResponseForExceptionEvent $event
*/
public function onKernelException(GetResponseForExceptionEvent $event)
{
//The logger object is my logger
$this->logger->log($event->getException(), $event->getRequest());
if (!$event->getRequest()->isXmlHttpRequest()) {
return;
}
$event->setResponse(new JsonResponse('message' => 'Ops. Houston we have a problem.'));
}
Thank you.
I post how I resolved. The problem isn't related with Monolog, but with my logger service.
Because I wrapped how to log exceptions, before I didn't pass the exception when I call
$logger->error('message error');
So when Monolog tries to enable the NotFoundActivationStrategy (file is located in /vendor/symfony/monolog-bundle/NotFoundActivationStrategy.php), this check fails:
public function isHandlerActivated(array $record)
{
$isActivated = parent::isHandlerActivated($record);
if (
$isActivated
&& $this->request
&& isset($record['context']['exception'])
&& $record['context']['exception'] instanceof HttpException
&& $record['context']['exception']->getStatusCode() == 404
) {
//blacklist is the pattern that you can set on config.yml at excluded_404s node
return !preg_match($this->blacklist, $this->request->getPathInfo());
}
return $isActivated;
}
So I resolved with
$this->logger->error('message', array('exception' => $exception));
Hope this helps someone.
You can filter errors in onKernelException method. See example below:
<?php
namespace AppBundle\Listener;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AppExceptionListener
{
private $logger;
public function __construct($logger)
{
$this->logger = $logger;
}
public function onKernelException(GetResponseForExceptionEvent $event)
{
$exception = $event->getException();
if(!$exception instanceof NotFoundHttpException)
{
$this->logger->info('Error');
}
}
}

Merge ParamConverter and BodyConverter objects on FOSRestBundle

I'm using the param converter to get object from url and body converter to get object form body.
This perfectly works for GET and POST methods, but I have to do it with a tricky way for an update (PUT):
/**
* #param PowerDNSDomain $domain
* #param PowerDNSRecord $record
* #param PowerDNSRecord $updatedRecord
* #param ConstraintViolationListInterface $validationErrors
*
* #ParamConverter("updatedRecordData", converter="fos_rest.request_body")
*
* #return View
*/
public function putAction(PowerDNSDomain $domain, PowerDNSRecord $record, PowerDNSRecord $updatedRecord, ConstraintViolationListInterface $validationErrors)
{
if ($validationErrors->count() > 0) {
return $this->handleBodyValidationErrorsView($validationErrors);
}
$record->setName($updatedRecord->getName().'.'.$domain->getName())
->setContent($updatedRecord->getContent())
->setTtl($updatedRecord->getTtl())
->setPrio($updatedRecord->getPrio());
$this->get('manager.dns')->saveRecord($record);
return $this->view($record);
}
In a nutshell, I have to retrieve two PowerDNSDomain object (one from the URL, one from the body) and update each fields manually.
This is overkill, isn't it?
The preferred way would be to have a method signature like this:
public function putAction(PowerDNSDomain $domain, ConstraintViolationListInterface $validationErrors)
Where the PowerDNSDomain $domain would be the result of the body converter object merged into the param converter one.
In this case, I will just have to get validation errors and save the object.
How can I make this possible ? :-)
Related configuration:
fos_rest:
routing_loader:
default_format: json
body_converter:
enabled: true
validate: true
serializer:
serialize_null: true
view:
formats:
xml: false
json: true
rss: false
yml: true
view_response_listener: force
param_fetcher_listener: force
format_listener:
rules:
- { path: '^/api/', priorities: ['json', 'yml'], fallback_format: json, prefer_extension: true }
- { path: '^/', stop: true } # FOSRest should not handle other routes than API
media_type:
enabled: true
Possibly related issue: https://github.com/FriendsOfSymfony/FOSRestBundle/issues/1238

Can't call a custom respository methode symfony2

I've followed every step in the book, but I can't get to work any entity custom repository.
The problem her is that i have been trying to call the method filtrerExperienceTotal but The code completion shortcut (Ctrl-Space) can't find the method, please help
For example, I have my User entity:
<?php
namespace MTO\CrowdRiseBundle\Controller;
use MTO\CrowdRiseBundle\Entity\UserRepository;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use MTO\CrowdRiseBundle\Entity\User;
class ProfilsController extends Controller
{
public function filtrerExperienceTotal(){
$em = $this->getDoctrine()->getManager();
$req = $this->get('request');
if ($req->getMethod() == 'POST') {
$rechexperienceTot = $req->get('rechexperienceTotname');
$Users = $em->getRepository('MTOCrowdRiseBundle:User')->filtrerExperienceTotal(0,99);
if (!($Users == null)) {
return $this->render('MTOCrowdRiseBundle:Profils:profils.html.twig', array('users' => $Users));
} else {
return $this->render('MTOCrowdRiseBundle:Profils:profils.html.twig', array('users' => NUll));
}
}
return ($this->redirectToRoute('mto_crowd_rise_profils'));
}
and the repository class
class UserRepository extends EntityRepository
{
public function chercherNom($nom){
$qb = $this->getEntityManager()->createQueryBuilder('p')
->where('p.nom LIKE :nom')
->orWhere('p.prenom LIKE :nom')
->orWhere('p.username LIKE :nom')
->setParameter('nom', $nom)
->getQuery()->getResult();
return $qb;
}
public function filtrerExperienceTotal($experiencemin,$experiencemax){
$qb = $this->getEntityManager()->createQueryBuilder('p')
->select('p ')
->where('p.experienceTot between :parm1 and :param2')
->setParameter('param1', $experiencemin)
->setParameter('param2', $experiencemax)
->getQuery()->getResult();
return $qb;
}
}
final the user.orm.yml
MTO\CrowdRiseBundle\Entity\User:
type: entity
table: user
repositoryClass: MTO\CrowdRiseBundle\Entity\UserRepository
id:
id:
type: integer
nullable: false
unsigned: false
comment: ''
id: true
generator:
strategy: IDENTITY
fields:
nom:
type: string
nullable: false
length: 40
fixed: false
comment: ''
prenom:
type: string
nullable: false
length: 40
fixed: false
comment: ''
datenaissance:
type: date
nullable: false
comment: ''
column: dateNaissance
situationprof:
type: string
nullable: false
length: null
fixed: false
comment: ''
column: situationProf
secteur:
type: string
nullable: false
length: null
fixed: false
comment: ''
experiencetot:
type: integer
nullable: false
unsigned: false
comment: ''
column: experienceTot
solde:
type: integer
nullable: false
unsigned: false
comment: ''
column: solde
paysnatal:
type: string
nullable: false
length: 40
fixed: false
comment: ''
column: paysNatal
image:
type: text
nullable: false
length: null
fixed: false
comment: ''
role:
type: string
nullable: false
length: null
fixed: false
comment: ''
etat:
type: string
nullable: false
length: null
fixed: false
comment: ''
sexe:
type: string
nullable: false
length: null
fixed: false
comment: ''
lifecycleCallbacks: { }
please guys i do really need a help
Well at the end, the probleme was from the IDE, all i need it is to force it and write manually the name of the method, it work fine, Thanks alot

FOSRestBundle annotations not working

FOSRestBundle annotations are not working for me somehow.
use FOS\RestBundle\Controller\Annotations as Rest;
// ...
/**
* #Rest\RequestParam(name="email")
*/
public function someAction(Request $request)
{
// some code
}
Here's my config:
fos_rest:
param_fetcher_listener: true
body_listener: true
format_listener: false
routing_loader:
default_format: json
view:
view_response_listener: 'force'
formats:
xml: false
json : true
default_engine: none
templating_formats:
html: true
access_denied_listener:
json: true
allowed_methods_listener: true
Requests to this action ignores annotation and just executes method's code. It seems that listener that should resolve these annotations is not running. Any suggestions?
change param_fetcher_listener: true to param_fetcher_listener: force and move code to:
use FOS\RestBundle\Request\ParamFetcher
/**
* #Rest\RequestParam(name="email")
*/
public function someAction(ParamFetcher $paramFetcher) {
$email = $paramFetcher->get('email');
}
Note: Request parameter must be passed as POST

Resources