there is no default value + symfony2 + crud - symfony

sf 2.8.4 with sylius 0.17
i had generated a controller and routes with generate:doctrine:crud
i can list all datas, but on show and edit, always got this error:
Controller "St\AppBundle\Controller\TranslationDomainController::showAction()" requires that you provide a value for the "$translationdomain" argument (because there is no default value or because there is a non optional argument after this one).
here the show action
public function showAction(TranslationDomain $translationdomain)
{
$deleteForm = $this->createDeleteForm($translationdomain->getId(), 'administration_translations_domain_delete');
return $this->render('StAppBundle:TranslationDomain:show.html.twig', array(
'translationdomain' => $translationdomain,
'delete_form' => $deleteForm->createView(), ));
}
and the route
administration_translations_domain_show:
pattern: /{id}/show
defaults: { _controller: "StAppBundle:TranslationDomain:show", id : 1 }
requirements:
id : \d+
_method : get

You are using a param converter
http://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html
You have to disable the auto-conversion of type-hinted method arguments feature by setting the auto_convert flag to false.
Look at:
# app/config/config.yml
sensio_framework_extra:
request:
converters: true
auto_convert: false
Change to:
sensio_framework_extra:
request:
converters: true
auto_convert: true
At the end you should always request for an object identifier. It's safe and semantic correct. You want to 'show/edit/update/delete' concrete entity.
If you really wants to have a default show for your set of entities create route like a '/show/default' and use this route with 'show/choose default' link.

Related

Symfony CMF Dynamic Router no contentDocument

Following the Dynamic Router doc, I can:
Create a route linked to my content (Page entity)
Persist it with ORM
Load my controller matching the route
But as my controller should expect the $contentDocument parameter, I have nothing.
Here's how I create my route and my entity:
$page = new Page();
$page->setTitle('My Content')
->setBackground(1)
->setDescription('My description')
->setContent('<h1>Hello</h1>');
$manager->persist($page);
$manager->flush(); // flush to be able to use the generated id
$contentRepository = $this->container->get('cmf_routing.content_repository');
$route = new Route();
$route->setName('my-content');
$route->setStaticPrefix('/my-content');
$route->setDefault(RouteObjectInterface::CONTENT_ID, $contentRepository->getContentId($page));
$route->setContent($page);
$page->addRoute($route); // Create the backlink from content to route
$manager->persist($page);
$manager->flush();
Here's my config section:
cmf_routing:
chain:
routers_by_id:
router.default: 200
cmf_routing.dynamic_router: 100
dynamic:
enabled: true
persistence:
orm:
enabled: true
generic_controller: AppBundle:Default:showPage
templates_by_class:
AppBundle\Entity\Page: AppBundle:Default:index.html.twig
My controller:
public function showPageAction($page)
{
return $this->render('default/index.html.twig');
}
And the error:
Controller "AppBundle\Controller\DefaultController::showPageAction()" requires that you provide a value for the "$page" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.
Dynamic routing puts the content document into the request with the name "contentDocument". You need to explicitly use that name:
public function showPageAction($contentDocument)
{
return $this->render('default/index.html.twig');
}
if you do not need to do anything in your controller, you don't need to specify the generic_controller. template_by_class will make the bundle provided controller render that template with the page instance found in $contentDocument.

Using custom Repository in Sylius Resource grid

I have generated a Grid with CRUD actions for my Labellisation entity on Sylius.
The grid is displayed well, but I would like to get associated elements too (the defaultAdresse of the -> customer of the -> current labellisation), so I need to use a custom repository method.
I tried to do this with this conf :
labellisation_grid:
resource: |
alias: grid.label
criteria:
valide: true
except: ['create', 'delete', 'update']
grid: public_labels
templates: LabelBundle:public/Crud
type: sylius.resource
defaults:
_sylius:
repository:
method: findAllValides
(adding all the defaults block), but I have an error because the method findAllValides is not defined. I do have a findAllValides method in my LabellisationRepository.
Debugging the ResourcesResolver, I saw in the getResource that the $repository passed to this function has a customRepositoryClassName = LabelBundle\Repository\LabellisationRepository (this path is the good one to my LabellisationRepository).
Is there something wrong with my code ?

Symfony redirect to route passing url slug

I've searched this on SO previously, but it seems that the only answers given are when parameters are passed as a query string, which is not what I want.
I have a page in my Symfony 3 CRM with a route app_litter. There is a required URL slug called litter_id which needs to be passed to the route in order to determine which litter data to show, as follows:
/litter/1
My route definiton in the routing file is:
app_view_litter:
path: /litter/{id}
defaults: { _controller: AppBundle:Litter:view, id: null }
requirements:
id: \d+
There is a function which allows a user to add puppies to their litter, which is a form outside of this page - once the puppies are successfully saved, I want to redirect the user back to the litter in question, so I did this:
return $this->redirectToRoute('app_litter', array('litter_id' => $litter->getId()));
Where $litter is the object retrieved from Symfony. However, this redirects to:
/litter?litter_id=1
Which does not work, as it expects a slug. Is it possible to use redirectToRoute() (or any other method) to render the route with a slug instead of a query string?
Because your route definition is:
app_view_litter:
path: /litter/{id}
defaults: { _controller: AppBundle:Litter:view, id: null }
requirements:
id: \d+
When using the route generator you need to provide an associated array with keys corresponding to the name of your placeholders which is in your case id.
Therefore, it must be:
$this->redirectToRoute('app_litter', array('id' => $litter->getId()));
If you want to use a slug, and there something which not only composed of digits (\d+), you have to either define a new route or modify the existing.
app_view_litter_using_slug:
path: /litter/{slug}
defaults: { _controller: AppBundle:Litter:view, slug: null }
requirements:
id: .*
And you something like:
$this->redirectToRoute('app_litter_using_slug', array('slug' => $litter->getSlug()));
Could it be that you are using the wrong route? Try using app_view_litter instead of app_litter:
return $this->redirectToRoute('app_view_litter', array('id' => $litter->getId()));

symfony routing, use value from Request as default

I've got the following route definition
my_route:
path: /actual-path/
defaults:
_controller: MyBundle:MyController:detail
id: application_id
requirements:
methods: GET
id: \d+
The controller requires a parameter called $id.
But I don't want to use the $id in the url, I want to use a value that is available in $request->attributes->get('application_id')
There is a listener that will inject two parameters (application_id and application) into the request object as attributes prior to the routing process, so this value is in there. (It would be easy to also inject it into the RequestContext).
Is there a way I can use attributes values from the Request or RequestContext object in my routing as defaults?
Now I could simply do $request->attributes->get('application_id') in my controller. But this controller will be used in several cases. In other cases the $id is to be passed through the url. I find it cleaner to set the id in the routing than build a if-else clause in the controller somewhere.
It appears not to be possible to do "mapping" between variables in the request object and the parameters you need to be required in your route/controller-action. I think this would be a good thing, as it would become quite complex otherwise.
I went with the solution to extend the controller and build in a small switch there.
Basically, if the route specifies id === null, it will do a fallback to application_id that is in the Request object. Otherwise it will use the value provided. I just need to set a requirement on id on the routes that must not use the fallback.
All without running an additional Listener which might be a bit "expensive" in processing time (for each request).
Example of routes:
my_route:
path: /actual-path/
defaults:
_controller: MyBundle:MyController:detail
id: null
requirements:
methods: GET
my_other_route:
path: /other-path/{id}
defaults:
_controller: MyBundle:MyController:detail
requirements:
methods: GET
id: \d+
And how to handle this in your controller:
// fallback to system id
if ($id === null) {
$id = $request->attributes->get('administration_id', null);
}
Because you extend the controller/action, you could also change the name of the parameter in the action (as long as the type does not change).
I did not do this, as I could quite easily put the switch between the provided id and the fallback from the listener in another method.

Payum omnipay and Skrill

I'm trying to implement payment in my app using Payum 1.0, Payum Bundle 1.0 and Omnipay bridge with omnipay-skrill bundle as skrill is not supported out-of-the-box.
payum.yml
payum:
security:
token_storage:
XXX\PaymentBundle\Entity\PaymentToken: { doctrine: orm }
storages:
XXX\PaymentBundle\Entity\Payment: { doctrine: orm }
gateways:
skrill:
omnipay:
type: Skrill
options:
email: me#me.net
notifyUrl: /payment/skrill
testMode: true
This is my controller prepare action:
public function prepareAction()
{
$paymentName = 'skrill';
$storage = $this->get('payum')->getStorage('XXX\PaymentBundle\Entity\Payment');
$payment = $storage->create();
$payment->setNumber(uniqid($this->container->getParameter('shoppingCart')));
$payment->setCurrencyCode('EUR');
$payment->setTotalAmount($this->container->getParameter('price_of_xxx'));
$payment->setDescription('desc');
$payment->setClientId($this->getUser()->getId());
$payment->setClientEmail($this->getUser()->getEmail());
$payment->setLanguage('EN');
$storage->update($payment);
$captureToken = $this->get('payum.security.token_factory')->createCaptureToken(
$paymentName,
$payment,
'xxx_buy_premium_done' // the route to redirect after capture
);
return $this->redirect($captureToken->getTargetUrl());
}
So, when i visit the link associated with prepare action i get the Payum credit card form. But when i enter all data as response i get an error saying language parameter must be provided. I can't figure out why is it happening since i tried putting the language parameter in config file and setting payment language field. I suppose it has to be sent in form data as hidden field.
Is it possible to redirect user to https://pay.skrill.com/app/?sid=
with parameters and get response from Skrill servers to captureDoneAction?
Try to set language to the details like this:
$payment->setDetails(array(
'language' => 'EN',
));

Resources