I'm trying to solve this little problem.
I have a form that allows to modify datas to a db, but when I click on the submit button(even if it changes the values), it shows an error:
Some mandatory parameters are missing ("name") to generate a URL for route "update_page".
500 Internal Server Error - MissingMandatoryParametersException
Can anybody help me?
This is my controller:
class updateElementController extends Controller
{
public function updateAction($name)
{
$request = $this->get('request');
$ingrediente = $this->getDoctrine()
->getRepository('MyCrudBundle:Elements')
->findOneByName($name);
$em = $this->getDoctrine()->getManager();
$elementsmod = new Elements();
$formupdate = $this->createFormBuilder($elementsmod)
->add('name', 'text')
->add('quantity', 'text')
->add('Change element', 'submit')
->getForm();
$formupdate->handleRequest($request);
if ($formupdate->isValid()) {
$newval = $formupdate->getData();
// change "entity" / object values we want to edit
$namevalue= $newval->getName();
$quantityvalue= $newval->getQuantity();
$element->setName($namevalue);
$element->setQuantity($quantityvalue);
// call to flush that entity manager from which we create $item
$em->flush();
return new RedirectResponse($this->generateUrl('update_page'));
}
return $this->render('MyCrudBundle:Default:index.html.twig', array(
'form' => $formupdate->createView(),
));
}
}
And my route:
update_page:
pattern: /updatePage/{name}
defaults: { _controller: MyCrudBundle:updateElement:update }
(if you need other parts of code, just tell me, I'm a beginner and most certainly it's horribly written)
I suggest two options:
If the name is not mandatory in your routing you can change your routing as below
update_page:
pattern: /updatePage/{name}
defaults: { _controller: MyCrudBundle:updateElement:update, name: null }
If the name is mandatory for the generated url you need to pass the name as the pattern param
if ($formupdate->isValid()) {
$newval = $formupdate->getData();
$namevalue= $newval->getName();
$quantityvalue= $newval->getQuantity();
$element->setName($namevalue);
$element->setQuantity($quantityvalue);
$em->flush();
return new RedirectResponse($this->generateUrl('update_page', array('name' => $name)));
}
base on your query selection you have in your controller the $name is mandatory and I suggest to try the second one
Related
I am trying to use an optional parameter in one of my symfony 6 controllers but it just does not work.
I have a controller with a method/route to create a new item and one to edit an existing item. The route for the "new" method does not accept an item parameter but the one for the "edit" method does. As such:
#[Route('/new', name: 'new', methods: ['GET', 'POST'])]
public function new( Request $request ): Response ...
#[Route('/edit/{id}', name: 'edit', methods: ['GET', 'POST'])]
public function edit( Request $request, Item $item ): Response ...
Since both of the methods have a large amount of the same code in them, I decided to create a new "new_edit" method and route that is then called from the "new" and "edit" methods via "directToRoute".
#[Route('/new_edit/{id}', name: 'new_edit', defaults: ['id' => null], methods: ['GET', 'POST'])]
public function new_edit( Request $request, ?Item $item ) : Response ...
So far so good. When I select an existing item and elect to edit it, all works perfectly. However, when I elect to create a new item I constantly get and error message "Item object not found by the #ParamConverter annotation".
I have tried setting default values, etc. but I am just not able to get this working.
Does anyone have a solution to such a problem?
Many thanks,
Kristian.
It seems I have found the issue and it was not related directly to the optional parameter but to the priority in which the routes are evaluated.
I modified my route priorities and now all works as expected with the following configuration:
#[Route('/new', name: 'new', methods: ['GET', 'POST'])]
public function new(): Response
{
return $this->redirectToRoute( 'item.new_edit', [], Response::HTTP_SEE_OTHER );
}
#[Route('/edit/{id}', name: 'edit', methods: ['GET', 'POST'])]
public function edit( Item $item ): Response
{
return $this->redirectToRoute( 'item.new_edit', ['id' => $item->getId()], Response::HTTP_SEE_OTHER );
}
#[Route('/new_edit/{id}', name: 'new_edit', defaults: ['id' => null], methods: ['GET', 'POST'])]
public function new_edit( Request $request, ?Item $Item ) : Response
{
...
}
I hope that helps anyone who has the same issue.
Kristian
You can use several routes for one action. For the optional param you can define a default value for the PHP parameter ?Item $Item = null
#[
Route('/new', name: 'new', methods: ['GET', 'POST']),
Route('/edit/{id}', name: 'edit', methods: ['GET', 'POST'])
]
public function new_edit(Request $request, ?Item $item = null) : Response
{
}
For example simple controller:
/**
* #Route("/{identifier}", name="page")
*/
public function page(Request $request, string $identifier)
{
$page = $this->pageRepository->findOneBy(['identifier' => $identifier]);
if (!$page || !$page->getEnabled()) {
throw $this->createNotFoundException();
}
return $this->render('cms/index.html.twig', []);
}
And a have a bundle to manage images from admin page elfinder, which will enter the /elfinder link.
And instead of getting the bundle controller, my controller gets.
/{identifier} === /elfinder
How do people usually act in such situations?
I tried to set different priority, but it does not help
Try adding your controllers with the priority required in the annotations.yaml file. Thus, if you get a 404 in the first one, Symfony will try to open the route from the next controller
Add your controllers to config/routes/annotations.yaml
page:
resource: App\Controller\_YourFistController_
type: annotation
elfinder:
resource: FM\ElfinderBundle\Controller\ElFinderController
type: annotation
Or if this option does not suit you, then you can try the optional parameter priority. symfony doc
Add to config file config/routes.yaml:
elfinder:
path: /elfinder/{instance}/{homeFolder}
priority: 2
controller: FM\ElfinderBundle\Controller\ElFinderController::show
I tried to set the priority through the configuration file. But unfortunately it didn't work.
The only thing that helped was to create your own methods that will redirect
/**
* #Route("/elfinder", name="elfinder", priority=10)
*/
public function elfinder()
{
return $this->forward('FM\ElfinderBundle\Controller\ElFinderController::show', [
'homeFolder' => '',
'instance' => 'default',
]);
}
/**
* #Route("/efconnect", name="efconnect", priority=11)
*/
public function elfinderLoad(Request $request, SessionInterface $session, EventDispatcherInterface $dispatcher)
{
return $this->forward('FM\ElfinderBundle\Controller\ElFinderController::load', [
'session' => $session,
'eventDispatcher' => $dispatcher,
'request' => $request,
'homeFolder' => '',
'instance' => 'default',
]);
}
I'm pretty new on unit testing and I want to try to test my login page
my Goal for this unit are :
-> if it match in database -> redirect to route '/'
-> if not -> redirect to route '/login'
<?php
namespace Tests\Feature;
use App\Domain\Core\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Session;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class userTest extends TestCase
{
use DatabaseMigrations;
/**
* A basic test example.
*
* #return void
*/
public function testLoginTrue()
{
$credential = [
'email' => 'user#ad.com',
'password' => 'user'
];
$this->post('login',$credential)->assertRedirect('/');
}
public function testLoginFalse()
{
$credential = [
'email' => 'user#ad.com',
'password' => 'usera'
];
$this->post('login',$credential)->assertRedirect('/login');
}
}
when I test on TestLoginTrue , its successfully return to '/' But when i try the TestLoginFalse ... it return same like TestLoginTrue, it should be stayed on '/login' route,
Any Idea?
Plus I want to try to check if when I already login I couldn't access the login page so my initial idea is :
public function testLoginTrue()
{
$credential = [
'email' => 'user#ad.com',
'password' => 'user'
];
$this->post('login',$credential)
->assertRedirect('/')
->get('/login')
->assertRedirect('/');
}
but... it returns
1) Tests\Feature\userTest::testLoginTrue BadMethodCallException:
Method [get] does not exist on Redirect.
So how to do it correctly?
Thanks in advance
I am also a bit stuck with Laravel 5.4 testing follow redirects case.
As a workaround, you may check $response->assertSessionHasErrors(). This way it should work:
public function testLoginFalse()
{
$credential = [
'email' => 'user#ad.com',
'password' => 'incorrectpass'
];
$response = $this->post('login',$credential);
$response->assertSessionHasErrors();
}
Also, in testLoginTrue() you may check, that session missing errors:
$response = $this->post('login',$credential);
$response->assertSessionMissing('errors');
Hope this helps!
Here is the situation, I have a form:
public function buildForm(FormBuilderInterface $builder, array $options) {
foreach ($this->attributeGroupAttributes as $attribute) {
$builder->add('attribute-' . $attribute->getId(), $attribute->getType(), array(
'label' => $attribute->getName(),
));
}
}.
This form I'm using to validate data added dynamically to another form which was submitted.
This is the process how I do it:
I extract the data from the previous form.
I pass this data to another Action.
Here I get the attributeGroup.
I pass the Attributes in that group into the FormType and create a new form.
After which I put the data into the form via:
$form_validate->submit($normalizedData);
This is the controller:
public function createAction($formData) {
$itemService = $this->get('app.item');
$attributeGroupService = $this->get('app.attribute_group');
$attributeService = $this->get('app.attribute');
$attributeGroup = $attributeGroupService->getById($formData['attributeGroup']);
$attributeGroupAttributes = $attributeGroup->getAttributes();
$form_validate = $this->createForm(new \AppBundle\Form\ItemValidationType($attributeGroupAttributes));
$normalizedData = $itemService->normalizeDataForForm($formData);
$form_validate->submit($normalizedData);
if($form_validate->isValid()){
dump($form_validate->getData());
die();
}
die();
}
The error I get is:
-errors: array:1 [▼
0 => FormError {#855 ▼
-message: "The CSRF token is invalid. Please try to resubmit the form."
#messageTemplate: "The CSRF token is invalid. Please try to resubmit the form."
#messageParameters: []
#messagePluralization: null
-cause: null
-origin: Form {#836}
}
And that way ofcourse $form_validate->isValid() is false.
I am coming across some problems when trying to use ZF2's authentication services. I have to following Module.php getServiceConfig function:
<?php
public function getServiceConfig()
{
return array(
'factories' => array(
'Auth\Model\CustomerTable' => function($sm) {
$tableGateway = $sm->get('CustomerTableGateway');
$table = new CustomerTable($tableGateway);
return $table;
},
'CustomerTableGateway' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Customer()); // prototype pattern implemented.
return new TableGateway('customer', $dbAdapter, null, $resultSetPrototype);
},
'Auth\Model\AuthStorage' => function($sm){
return new \Auth\Model\AuthStorage('jamietech');
},
'AuthService' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$dbTableAuthAdapter = new DbTableAuthAdapter($dbAdapter,
'customer','username','password');
$authService = new AuthenticationService();
$authService->setAdapter($dbTableAuthAdapter);
$authService->setStorage($sm->get('Auth\Model\AuthStorage'));
return $authService;
},
),
);
}
The AuthStorage factory simply creates a new AuthStorage for us to keep track of the rememberMe function I have, and the AuthService factory creates a new Authentication Service for us. I can't see anything that I have done wrong but when running the following code in the AuthController.php:
<?php
public function loginAction()
{
//if already login, redirect to success page
if ($this->getAuthService()->hasIdentity()){
return $this->redirect()->toRoute('success');
}
$form = new LoginForm();
return array(
'form' => $form,
'messages' => $this->flashmessenger()->getMessages()
);
}
public function logoutAction()
{
$this->getSessionStorage()->forgetMe();
$this->getAuthService()->clearIdentity();
$this->flashmessenger()->addMessage("You have logged out successfully.");
return $this->redirect()->toRoute('auth', array('action'=>'login'));
}
PHPUnit encounters the following errors when running the PHPUnit command:
1: "testLoginActionCanBeAccessed - Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance of Zend\Db\Adapter\Adapter
1: "testLogoutActionCanBeAccessed - session_regenerate_id(): cannot regenerate session id - headers already sent.
And this error for both login and logout when the -process-isolation command is run:
"Serialization of closure is not allowed in: C;\Users\-----\AppData\Local\Temp\-----
If somebody could help that would be great. I am a ZF noob so try not to be too harsh.
EDIT: BTW THe global.php file includes the service_manager adapter factory illustrated in the ZF2 tutorial application.
Thank you!
Jamie Mclaughlan
did you check these:
autoload_classmap.php (for your module)
in your module.config.php
like this
service_manager' => array(
'aliases' => array(
'mymodule-ZendDbAdapter' => 'Zend\Db\Adapter\Adapter',
),
);
I hope it helps you to find the answer