Rendering Zend Form in Slim3 - php

I am using Slim3 with Zend Forms 2.6 (https://packagist.org/packages/zendframework/zend-form). I am trying to render the form but I get an error:
Fatal error: Call to undefined method QuizApp\Forms\QuizForm::render() in /var/www/QuizApp/Routes/SurveyRoutes.php on line 25
I have added my form as a service within Slim3:
$container['QuizForm'] = function() use ($app) {
return new \QuizApp\Forms\QuizForm($app->SurveyServices);
};
Here is my form:
class QuizForm extends \Zend\Form\Form
{
private $survey_services;
public function __construct(SurveyServices $survey_services, $name = null)
{
$this->survey_services = $survey_services;
parent::__construct($name);
}
public function init()
{
/*
* Set form method to POST
*/
$this->setMethod('POST');
/*
* Add submit button to the form
*/
$this->add(array(
'name' => 'submit',
'type' => 'Submit',
'attributes' => array(
'value' => 'Get Quiz Results'
),
));
}
}
I am attempting to render the form within one of my routes (eventually I will pass this to my view, but I'm testing):
$form = $this->QuizForm;
# Doesn't work
print $form;
# Doesn't work
print $form->render()
What's confusing me is the docs say printing the form should work: http://framework.zend.com/manual/1.12/en/zend.form.quickstart.html#zend.form.quickstart.render
I am not using the Zend Framework. I am only using the Form component.
How do I render the form?

You're looking at wrong place. That's documentation for Zend's version 1.12.
You are using newest version, so take a look here.
According to that doc resource, before rendering, you should call
$form->prepare();
Also you probably should use Form View Helpers if you want to make rendering forms easy.

It looks like you don't have a proper DI setup, if you can't dump the form like so...
php
var_dump($this->QuizForm);
Then that object is not in the context of this.
I suspect that you might be missing injecting it into the class where you are calling this. But your problem currently is that you need to inject the quiz into your object where you are trying to render it.

Related

How to invoke a service after pressing submit in Drupal

I am very new to Drupal and I am asked to create form with a submit button and a service that makes a get request to an API with the values from the form. The API is a simple API that the user can enter a country and it will return a response with the correct greeting from that country.
This is my routing file:
hello_world.salutation:
path: '/hello'
defaults:
_controller: Drupal\hello_world\Controller\HelloWorldSalutation::salutation
_form: Drupal\hello_world\Form\GreetingForm
_title: 'Get a greeting from a different language'
requirements:
_permission: 'administer site configuration'
First problem is that I do not know how to make the form and the controller in the same routing,
and second is that I do not know how to invoke that service when the user has entered submit.
Here is my services file:
services:
hello_world.salutation:
class: Drupal\hello_world\HelloWorldSalutation
arguments: [ '#config.factory' ,'#tempstore.private']
cache.nameofbin:
class: Drupal\Core\Cache\CacheBackendInterface
tags:
- { name: cache.bin }
factory: [ '#cache_factory', 'get' ]
arguments: [ nameofbin ]
I will skip some lines from the GreetingFrom class to keep it simple, but I can add them if it is required.
Here is the submitForm function from the GreetingForm class. The idea is to put the input in a global tempstore so I cal access the values from the controller I guess.
public function submitForm(array &$form, FormStateInterface $form_state)
{
$search_str = $form_state->getValue('greeting');
// check the input
$params['items'] = $form_state->getValue('greeting');
// 2. Create a PrivateTempStore object with the collection 'greetingForm_values'.
$tempstore = $this->tempStoreFactory->get('greetingForm_values');
// 3. Store the $params array with the key 'params'.
try {
$tempstore->set('params', $params);
} catch (\Exception $error) {
// dump the error for now, read error, --fix this!
dpm($error);
}
}
And the salutation function from the controller looks like this:
public function salutation()
{
$tempstore = $this->tempStoreFactory->get('greetingForm_values');
$params = $tempstore->get('params'); // this value should come from the search form
return [
'#markup' => $this->salutation->getGreeting($params),
];
}
Any help is greatly appreciated, and please ask for more information if it is needed.
Routing file
In your use case I believe you can stick to the use of a Form. Please discard the Controller specification from your hello_world.salutation route, because it should be either _form or _controller, not both for a single route.
Service method invocation
For your service definition, you can do this by either statically calling the service as:
$salutation_service = \Drupal::service('hello_world.salutation');
$salutation_service->somePublicMethodCall();
or via Dependency Injection which I assume you are already doing when I look at this->salutation->getGreeting($params)?
Form x Controller
From the provided details, I can't really tell why you need the Controller, but if you need to redirect to the Controller, then you could create a separate route for your HelloWorldSalutation::salutation() method and redirect to it from GreetingForm ::submitForm() via the $form_state object:
$url = \Drupal\Core\Url::fromRoute('hello_world.salutation');
$form_state->setRedirectUrl($url);

The controller is not allowed by this plugin

I try to add a new controller which has one action called confirmAgbAction.
<?php
namespace Eddcapone\MyExtension\Controller;
/**
* CustomController
*/
class CustomController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
/**
* action list
*
* #return void
*/
public function confirmAgbAction()
{
echo "<p>HALLO WELT</p>";
}
}
I even added it to ext_localconf.php
<?php
if (!defined('TYPO3_MODE')) {
die('Access denied.');
}
\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
'Eddcapone.' . $_EXTKEY,
'Myfilelist',
array(
'Category' => 'list,show',
'File' => 'show',
'Download' => 'download',
'Custom' => 'confirmAgb'
),
// non-cacheable actions
array(
'Category' => 'list,show',
'File' => 'topFive',
'Download' => 'download',
'Custom' => 'confirmAgb'
)
);
This is how I call the action in the template:
<f:link.action controller="Custom" action="confirmAgb" pluginName="Myfilelist" class="mbButton">Download</f:link.action>
However, i always get:
#1313855173: The controller "Custom" is not allowed by this plugin. Please check for TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin() in your ext_localconf.php.
There are two common possibilities for your error:
You use a flexform to embed your plugin. Either you have not added Custom->confirmAgb to the allowed calls in your flexform or you have added it but did not update the plugin (plugin configuration only updates when you save the plugin/tt_content element)
You have two plugins on the page and the error is triggered by the other plugin because there the controller->action combination is not allowed.
PS: try adding this to your TS (setup.txt) and the plugins now should pick the default action if the given one is not found:
plugin.tx_yourextensionmvc.callDefaultActionIfActionCantBeResolved = 1
There could be more uncommon cases
You should absolutely avoid using $_EXTKEY in configurePlugin and other Extbase contexts. Extbase requires the Vendor.ExtensionName format - $_EXTKEY is in the lowercase_underscored format. Defining those parameters as hardcoded values should solve your problem with resolving controllers for your given plugin.
To be precise: use Eddcapone.Myextension as extension name parameter in your command(s) to register/configure plugins.

Symfony2: Create two controllers one to display a form and other to handle the submission

Hi I am a new to the Symfony2 MVC framework. What I have achieved so far is rendering a form in a twig template using the twig template. What I want to do next is create second (separate) controller to deal with form submission. Can you share with me how to achieve this.
I have read the symfony2 documentation however, it is not working.
Many thanks:)
You need to set an action on the form you are generating like so:
public function generateSearchBarAction()
{
$form = $this->createFormBuilder()
//This is where we are defining the target route
->setAction($this->generateUrl('route_to_catch_the_request'))
->setMethod('POST')
->add('keyword')
->getForm()
;
return $this->render('search_bar.html.twig', array(
'form' => $form->createView()
));
}
The controller that is provided at route_to_catch_the_request can then catch the request.
public function showSearchKeywordsAction(Request $request)
{
$form->handleRequest($request);
if ($form->isValid()) {
//do whatever...
}
}

Symfony2 - How to render a view from another controller

I have two controllers, homepage and Security.
In the homepage, I am displaying one view and in the security, I am doing some things, and one of them is the email address validation.
What I would like is that when the email validation code is not valid, display the homepage with a flash message. For that, I will have to render the indexAction of the HomepageController, from the Security controller, by giving him as parameter the flash message.
How can this be done? Can I render a route or an action from another controleller?
Thank you in advance.
I believe the checking should not be done in the Security controller. Right place in my opinion is a separate validator service or right in the entity which uses the email address.
But to your question, you can call another controller's action with $this->forward() method:
public function indexAction($name)
{
$response = $this->forward('AcmeHelloBundle:Hello:fancy', array(
'name' => $name,
'color' => 'green',
));
return $response;
}
The sample comes from symfony2 documentation on: http://symfony.com/doc/2.0/book/controller.html#forwarding
I have found the solution, simply use the forward function by specifying the controller and the action nanme:
return $this->forward('MerrinMainBundle:Homepage:Index', array('flash_message'=>$flash_message));
redirectToRoute : Just a recap with current symfony versions (as of 2016/11/25 with v2.3+)
public function genericAction(Request $request)
{
if ($this->evalSomething())
{
$request->getSession()->getFlashBag()
->add('warning', 'some.flash.message');
$response = $this->redirectToRoute('app_index', [
'flash_message' => $request->getSession()->getFlashBag(),
]);
} else {
//... other logic
}
return $response;
}

Zend: Issues setting up editAction(), please advise

I am experiencing some difficulty setting up the functionality for an admin to edit an items values. I have created the editAction() function in the AdminItemController class. This is contained within a module called catalog. My routing is configured as the following:
resources.router.routes.admin-catalog-edit.route = "/admin/catalog/item/edit/:id"
resources.router.routes.admin-catalog-edit.defaults.module = "catalog"
resources.router.routes.admin-catalog-edit.defaults.controller = "admin.item"
resources.router.routes.admin-catalog-edit.defaults.action = "edit"
I have created a custom Zend_Form class and within this class I set the action and method for the form:
class My_Form_ItemAdd extends Zend_Form
{
public function init()
{
$this->setAction('/admin/catalog/item/edit')
->setMethod('post');
...
Within my controller action I have instantiated the form and pass it to the view to be rendered. I also test if it's a POST (if so validate and save to database), otherwise, test for GET (if so, extract ID and populate()):
class Catalog_AdminItemController extends Zend_Controller_Action
{
...
public function editAction()
{
$form = new My_Form_ItemEdit();
$this->view->form = $form;
...
The form loads just fine in the browser when I supply an ID at the end for GET request... however, when I submit the form an exception is thrown with the following request parameters:
array (
'controller' => 'admin',
'action' => 'catalog',
'item' => 'edit',
'module' => 'default',
...
I have no idea why the it would be doing this... is there something I'm not seeing??? Any advice would be much appreciated!
The problem lies in your route. The default behavior for /admin/catalog/item/edit/:id is to process it like /controller/action/:param/:param/:param which puts both item and edit as parameters instead of your intended purpose. Try adding something like this to your bootstrap:
protected function _initRoutes()
{
// Get front controller
$front = Zend_Controller_Front::getInstance();
// Get router
$router = $front->getRouter();
// Add route
$router->addRoute(
'admin_item_edit',
new Zend_Controller_Router_Route('admin/catalog/item/edit/:id',
array('controller' => 'item',
'action' => 'edit'))
);
}
This allows you to define the specific controller and action from the route.

Categories