silex passing form data to another page? - php

I'm really new to silex and symfony. This is my first foray into silex. I've got code that created my form in my app.php file from a little hacking and copying and pasting from documentation.
Now how do i pass this data to another page?
I would like to create a page that just dumps the post/get array to give me an idea how to pass around get/post variables.
Here's part of my app file:
<?php
/** /src/app.php */
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Register new application
*/
$app = new Application();
// skip to the form part ...
$app->match('/', function (Request $request) use ($app) {
// some default data for when the form is displayed the first time
$data = array(
'name' => 'Your name',
'email' => 'Your email',
);
$form = $app['form.factory']->createBuilder('form', $data)
->add('name')
->add('email')
->add('gender', 'choice', array(
'choices' => array(1 => 'male', 2 => 'female'),
'expanded' => true,
))
->getForm();
if ('POST' == $request->getMethod()) {
$form->bindRequest($request);
if ($form->isValid()) {
$data = $form->getData();
// do something with the data
// redirect somewhere
return $app->redirect('completed');
}
}
// display the form
return $app['twig']->render('index.html', array('form' => $form->createView()));
});
Would i then create a page like so?
<?php // app.php
$app->match('complete') use function ($app) {
// sorry psuedocode
foreach ($REQUEST as $key=> $var) {
echo "$key: $var";
}
}

You could try using a forward. http://silex.sensiolabs.org/doc/usage.html#fowards
// where params is the values from your POST
$subRequest = Request::create('/otherpage', 'GET', $params);
return $app->handle($subRequest, HttpKernelInterface::SUB_REQUEST);

Related

PHP - Zend3, Jquery, Ajax (post)

I have built a website using php and the zend framework. In one of the pages I have a zend form and a table. The user can fill in the form, click the search button(page refresh occurs) and then get the corresponding results in the table.
What I am trying to do is to implement the same functionality using Ajax so the page won't have to refresh or ask for re-submission when reloaded.
From my controller I pass the data I want to display to view.phtml.
When the page first opens all the data from database gets displayed in the table. Somehow after the user clicks search :
the ajax post data should be retrieved in the controller
compared to the rest of the data to see if there are any matches
return the data matched
public function searchAction(): ViewModel
{
$persons = $this->personsService->getAllPersons();
$form = $this->personsForm;
if ($this->getRequest()->isPost()) {
$formData = $this->params()->fromPost();
$form->setData($formData);
if ($form->isValid()) {
$validFilteredData = $form->getData();
$persons = $this->personsService->getPersonsAfterSearch($validFilteredData);
}
}
return new ViewModel([
'persons' => $persons,
'form' => $form,
]);
}
I would like any suggestions on how to implement ajax since I am a beginner in web development and I don't experience working with ajax.
Thanks in advance.
Before you do this:
return new ViewModel([
'persons' => $persons,
'form' => $form,
]);
Add this:
if ($this->getRequest()->isXmlHttpRequest()) {
return new \Zend\View\Model\JsonModel(
[
'persons' => $persons,
'form' => $form,
]
);
}
Note: you've tagged "zend-framework" but mentioned "zend3". Above solution works for ZF2 and ZF3, don't know about ZF1.
Update due to comments:
Full function would be:
public function searchAction() : ViewModel
{
$persons = $this->personsService->getAllPersons();
$form = $this->personsForm;
if ($this->getRequest()->isPost()) {
$formData = $this->params()->fromPost();
$form->setData($formData);
if ($form->isValid()) {
$validFilteredData = $form->getData();
$persons = $this->personsService->getPersonsAfterSearch($validFilteredData);
}
}
$data = [
'persons' => $persons,
'form' => $form,
];
// AJAX response
if ($this->getRequest()->isXmlHttpRequest()) {
return new \Zend\View\Model\JsonModel($data);
}
return $data; // No need to return "new ViewModel", handled via ZF magic
}

Search filter with method get doesn't found results [symfony2]

I have a search form that works with the method POST, but the method POST doesn't display the requested data in the url.
With method POST the url look like this:
/search_flight
with the method GET no results found, the url look like this:
/search_flight?from=Cape+Town%2C+International+CPT&to=Johannesburg%2C+O.R.+Tambo+International+JNB&departuredate=2016%2F01%2F08&arrivaldate=2016%2F10%2F04&price=57.5%2C1000
I also noticed that with the method GET the data is reset in each input of the form.
routing.yml
searchFlight:
path: /search_flight
defaults: { _controller: FLYBookingsBundle:Post:searchtabflightResult }
requirements:
_method: GET|POST
controller
This method send the requested data to the method searchtabflightResultAction that will handle the query.
public function searchtabflightAction()
{
//$form = $this->createForm(new SearchflightType(),null, array('action' => $this->generateUrl('searchFlight'),'method' => 'GET',));
$form = $this->get('form.factory')->createNamed(null, new SearchflightType());
return $this->render('FLYBookingsBundle:Post:searchtabflight.html.twig', array(
'form' => $form->createView(),
));
}
.
<form action="{{ path ('searchFlight') }}" method="GET">
{# here I have my forms #}
</form>
.
public function searchtabflightResultAction(Request $request)
{
//$form = $this->createForm(new SearchflightType());
$form = $this->get('form.factory')->createNamed(null, new SearchflightType());
$form->handleRequest($request);
$em = $this->getDoctrine()->getManager();
$airport1 = $form["to"]->getData();
$airport = $form["from"]->getData();
$departureDateObj = $form["departuredate"]->getData();
$arrivalDateObj = $form["arrivaldate"]->getData();
$price = $form["price"]->getData();
$entities = $em->getRepository('FLYBookingsBundle:Post')->searchflight($airport1,$airport,$departureDateObj,$arrivalDateObj,$price);
return $this->render('FLYBookingsBundle:Post:searchtabflightResult.html.twig', array(
'entities' => $entities,
'form' => $form->createView(),
));
}
How can I make my search filter works with method get ?
Everything should be done within two actions, the basic concept is:
SearchFlightType has with/wo price option:
class SearchFlightType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('from', FormType\TextType::class)
->add('to', FormType\TextType::class)
->add('departuredate', FormType\TextType::class)
->add('arrivaldate', FormType\TextType::class);
if ($options['price']) {
$builder->add( 'price', FormType\TextType::class );
}
$builder
->add('submit', FormType\SubmitType::class);
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'price' => false,
));
}
}
Controller.php
class PostController extends Controller
{
/**
* #Route("/index", name="index")
*/
public function indexAction(Request $request)
{
$defaultData = array();
$form = $this->createForm(SearchFlightType::class, $defaultData, array(
// action is set to the specific route, so the form will
// redirect it's submission there
'action' => $this->generateUrl('search_flight_result'),
// method is set to desired GET, so the data will be send
//via URL params
'method' => 'GET',
));
return $this->render('Post/searchtabflight.html.twig', array(
'form' => $form->createView(),
));
}
/**
* #Route("/search_flight_result", name="search_flight_result")
*/
public function searchTabFlightResultAction(Request $request)
{
$defaultData = array();
$entities = null;
$form = $this->createForm(SearchFlightType::class, $defaultData, array(
// again GET method for data via URL params
'method' => 'GET',
// option for price form field present
'price' => true,
));
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// get data from form
$data = $form->getData();
// process the data and get result
$em = $this->getDoctrine()->getManager();
$entities = $em->getRepository('FLYBookingsBundle:Post')->searchflight($data['from'], $data['to'], ...);
}
return $this->render('Post/searchtabflight.html.twig', array(
'form' => $form->createView(),
// present the result
'entities' => $entites,
));
}
}

ZF2, pass variable to custom element from controller

In ZF2, I have a custom form element factory. It creates a custom MultiCheckbox and fills the checkbox values and labels from a db query.
class MyMultiCheckboxFactory
{
public function __invoke(FormElementManager $formElementManager)
{
$multiCheck = new \Zend\Form\Element\MultiCheckbox();
$serviceManager = $formElementManager->getServiceLocator();
$mapper = $serviceManager->get('Path\To\Mapper\To\Query\DB');
$descriptions = $mapper->findDescriptions($id);
// some processing to prepare $value_options array
$multiCheck->setOptions([
'label' => 'blah-blah',
'value_options' => $value_options
]);
return $multiCheck;
}
}
My problem is as follows. The method findDescriptions($id) depends on the $id which I can get from the route. But when I use MyMultiCheckbox in the form like this:
public function init()
{
$this->add([
'type' => 'Path\To\MyMultiCheckbox',
'name' => 'someName'
]);
}
I don't know how to pass the $id into the MyMultiCheckbox.
Could anyone help pleeeeeeeeeease?
You can fetch the id via the 'route match' instance inside the factory.
$event = $serviceManager->get('Application')->getMvcEvent();
$id = $event->getRouteMatch()->getParam('id', false);
if (empty($id)) {
throw new ServiceNotCreatedException('id not set!');
}
$descriptions = $mapper->findDescriptions($id);

populate select field on another select's "change" event in symfony2 and make it OK for submission

Using Symfony2.3.4 and PHP5.6.3
People, I've been looking for this issue for a while now and yes, I've found some similar ones and even found this in the Cookbook.
Now you'd say, "This guy is pretty slow", bingo, I am. Please help me out because I can't seem to get this or any other example I've encountered to help me in my own problem.
What I need is to populate a select field when the user selects an item from another select field. All this happens in a standard-CRUDgenerated-Symfony2 form. Both selects stand for an entity collection each(Zone and UEB), being Zone the independent one.
Community: Stop talking and give me the code!
Me: OK, here is what I have so far:
//ReferenceController.php
public function newAction() {
$entity = new Reference();
$form = $this->createCreateForm($entity);
return $this->render('CCBundle:Reference:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
public function createAction(Request $request) {
$entity = new Reference();
$form = $this->createCreateForm($entity);
$form->bind($request);
/*
var_dump($form->get('UEB')->getData());
var_dump($form->get('UEB')->getNormData());
var_dump($form->get('UEB')->getViewData());
die();
*/
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($entity);
$em->flush();
return $this->redirect($this->generateUrl('reference_show', array('id' => $entity->getId())));
}
return $this->render('CCBundle:Reference:new.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
private function createCreateForm(Reference $entity) {
$form = $this->createForm(new ReferenceType(), $entity, array(
'action' => $this->generateUrl('reference_create'),
'method' => 'POST',
));
return $form;
}
And
//ReferenceType.php
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('suffix')
->add('zone', null, array(
'required' => true,
))
;
//What follows is for populating UEB field accordingly,
//whether it's a "createForm" or an "editForm"
if ($options['data']->getId() !== null) {
$formModifier = function (FormInterface $form, Zone $zone = null) {
$UEBs = null === $zone ? array() : $zone->getUEBs();
$form->add('UEB', 'entity', array(
'required' => true,
'label' => 'UEB',
'class' => 'CCBundle:UEB',
// 'empty_value' => '',
'choices' => $UEBs,
));
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
$formModifier($event->getForm(), $data->getZone());
});
} else {
$formModifier = function (FormInterface $form) {
$form->add('UEB', 'entity', array(
'required' => true,
'label' => 'UEB',
'class' => 'CCBundle:UEB',
'query_builder' =>
function(EntityRepository $er) {
return $er->createQueryBuilder('u')
->where('u.zone = :zone')
->setParameter('zone', $er->findFirstZone());
}
)
);
};
$builder->addEventListener(
FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) {
$formModifier($event->getForm());
});
}
And
//base.js
var goalURL = "" + window.location;
if (goalURL.slice(-13) === 'reference/new' || goalURL.match(/reference\/\d+\/edit$/))
{
//case new reference
goalURL = goalURL.replace('reference/new', 'reference/update_uebs/');
//case edit reference
goalURL = goalURL.replace(/reference\/\d+\/edit/, 'reference/update_uebs/');
//this is the function run every time the "new" or "edit" view is loaded
//and every time the Zone select field is changed
var runUpdateUEBs = function() {
$.getJSON(goalURL, {id: $('#cc_ccbundle_reference_zone').val()}, function(response) {
$('#cc_ccbundle_reference_UEB').children('option').remove();
var non_selected_options = [];
var index = 0;
$.each(response, function(key, val) {
var option = $('<option selected="selected"></option>');
option.text(val);
option.val(key);
option.prop('selected', 'selected');
option.appendTo($('#cc_ccbundle_reference_UEB'));
non_selected_options[index++] = $(option);
});
var amount = non_selected_options.length;
if (amount > 1)
$.each(non_selected_options, function(key, val) {
if (amount - 1 === key)
val.attr('selected', false);
});
});
};
runUpdateUEBs();
$('#cc_ccbundle_reference_zone').bind({
change: runUpdateUEBs
});
}
And
//ReferenceController.php
//this is where "goalURL" goes
function updateUEBsAction() {
$id = $this->getRequest()->get('id');
$em = $this->getDoctrine()->getManager();
$uebs = $em->getRepository('CCBundle:UEB')->findBy(array('zone' => $id));
$ids_and_names = array();
foreach ($uebs as $u) {
$ids_and_names[$u->getId()] = $u->getName();
}
return new \Symfony\Component\HttpFoundation\Response(json_encode($ids_and_names));
}
With this I can load the UEBs corresponding the Zone being shown at the moment and every time a new Zone is selected alright, but only visually, not internally, hence:
the select populates fine but when I submit the form it doesn't go through with it and outputs "This value is not valid" on the UEB field and the
var_dump($form->get('UEB')->getData());
var_dump($form->get('UEB')->getNormData());
var_dump($form->get('UEB')->getViewData());
die();
from above outputs
null
null
string <the_value_of_the_option_tag> (length=1)
I need to know how to populate the select AND the internal data to be submitted too.
Thanks for bearing with this simple explanation.
I'm listening(reading).
Here is the answer I was looking for, it looks a lot like the one in the cookbook but somehow I understood this one better and I was able to apply it to my own problem, it only needed a few tweaks in the ajax call and the corresponding action, but only regarding my own problem.
thanks to all who cared to read my question and special thanks to Joshua Thijssen for his post.

How to create a step by step form with Phalcon in PHP

I'm currently working on a project using the Phalcon Framework that has pages with complex forms and a lot of inputs, to break it down nicely I'm dividing the forms into a step-by-step process.
How would one validate the form on each step before going to the next step and then save the whole form on the final step?
I can't seem to find anything documented about this sort of process as it likes to validate the form in it's entirety if I use the form builder.
Simple, just create a custom methods in your form class to validate any step, and the posted data from some step save into message class and store it into session by "stepX", when posted data is not valid just set defaults from post. When valid save it into session as i describe above.
For example how i mean "controller"
<?php
class MyController extends BaseController {
public function processStep1Action(){
$form = new MyForm();
if($this->request->isPost()){//im using my custom request class
if(!$form->isValid($this->request->getPost()){
//error messages goes here
$form->setDefaultsFromRequest($this->request); // it will set the filled data
}
else {
$messageClass = new MyMessageContainer();
$messageClass->setData($this->request);//inside parse requested data into message class, or parse it as $messageClass->name = $this->request->getPost('name');
$this->session->save('step1',$messageClass); //maybe it would be want to serialize it
//then redirect to the step 2 or x
}
}
}
}
So in the next step you can access data from sessions $this->session->get('step1'); so you can in final step load all posted data and store it into DB.
I hope this helps! :)
here is my form maybe it can be helpful for you.
<?php
namespace Manager\Library\Forms\User;
use Phalcon\Forms\Form,
Phalcon\Forms\Element\Email,
Phalcon\Forms\Element\Select,
Phalcon\Forms\Element\Password,
Phalcon\Forms\Element\Check,
Phalcon\Validation\Validator\Confirmation,
Phalcon\Validation\Validator\StringLength,
Phalcon\Forms\Element\Submit,
Phalcon\Validation\Validator\PresenceOf,
Model\Group;
class AddUser extends Form {
public function initialize()
{
$email = new Email('email');
$email->addValidators(array(
new \Phalcon\Validation\Validator\Email(array(
'message' => 'Nezadali jste email nebo má nesprávny tvar(email#domena.tld).'
))
));
$this->add($email);
$this->initGroupElement();
$password = new Password('password');
$password
->addValidator(new StringLength(array('min' => 6,'messageMinimum' => 'Nezadali jste heslo nebo je příliš krátke, minimální počet znaků je 6.')))
->addValidator(new Confirmation(array('with' => 'password-again',"message" => "Zadané hesla se neshodují.")));
$this->add($password);
$repeatPassword = new Password('password-again');
$this->add($repeatPassword);
$this->initializeProfileElements();
$active = new Check('active',array('value' => 1));
$this->add($active);
$this->add( new Submit('save') );
\Phalcon\Tag::setDefault('password', '');
\Phalcon\Tag::setDefault('password-again', '');
}
public function initializeEdit(){
$email = new Email('email');
$email->addValidators(array(
new \Phalcon\Validation\Validator\Email(array(
'message' => 'Nezadali jste email nebo má nesprávny tvar(email#domena.tld).'
))
));
$this->add($email);
$this->initGroupElement();
$password = new Password('password');
$this->add($password);
$repeatPassword = new Password('password-again');
$this->add($repeatPassword);
$this->initializeProfileElements();
$active = new Check('active',array('value' => 1));
$this->add($active);
$this->add( new Submit('save') );
\Phalcon\Tag::setDefault('password', '');
\Phalcon\Tag::setDefault('password-again', '');
}
protected function initGroupElement(){
$auth = \Core\Auth::getIdentity();
$groups = new Group();
// $groups->addColumns(array('id','name'));
//set global condition about Super Admin
$groups->addFilter('id', 1,'<>');
if($auth){
//set restrictions for main groups
if((int)$auth->group_id === 1){ //super admingroup
//no filter
}
else if((int)$auth->group_id === 2){ //admin group
$groups->addFilter('id', 1,'>');
}
else if((int)$auth->group_id === 6){//Provozovatel group
$groups->addFilter('id',array(3,6,7));
$groups->addFilter('public', 1,'=',true);
}
else { // other groups
$groups->addFilter('public', 1);
}
}
$groups = $groups->findFiltered();
$groupElement = new Select('group');
foreach($groups as $group){
$groupElement->addOption(array($group->id => $group->name));
}
$this->add($groupElement);
}
protected function initializeProfileElements(){
$forename = new \Phalcon\Forms\Element\Text('forename');
$this->add($forename);
$surname = new \Phalcon\Forms\Element\Text('surname');
$this->add($surname);
$street = new \Phalcon\Forms\Element\Text('street');
$this->add($street);
$postal = new \Phalcon\Forms\Element\Text('postal');
$this->add($postal);
$city = new \Phalcon\Forms\Element\Text('city');
$this->add($city);
$ic = new \Phalcon\Forms\Element\Text('ic');
$this->add($ic);
$dic = new \Phalcon\Forms\Element\Text('dic');
$this->add($dic);
}
public function setDefault($fieldName,$value){
\Phalcon\Tag::setDefault($fieldName, $value);
}
public function setDefaults($object){
if($object instanceof \Model\User){
$this->setDefaultsFromObject($object);
}
else if($object instanceof \Phalcon\Http\Request){
$this->setDefaultsFromRequest($object);
}
}
protected function setDefaultsFromObject(\Model\User $user){
$profile = $user->getRelated('\Model\Profile');
\Phalcon\Tag::setDefaults(array(
'email' => $user->email,
'group' => $user->group_id,
'active' => $user->active,
'forename' => $profile->forename,
'surname' => $profile->surname,
'street' => $profile->street,
'city' => $profile->city,
'postal' => $profile->postal,
'ic' => $profile->IC,
'dic' => $profile->DIC
));
}
protected function setDefaultsFromRequest(\Phalcon\Http\Request $request){
\Phalcon\Tag::setDefaults(array(
'email' => $request->getPost('email'),
'group' => $request->getPost('group'),
'active' => $request->getPost('active')
));
\Phalcon\Tag::setDefaults(array(
'forename' => $request->getPost('forename'),
'surname' => $request->getPost('surname'),
'street' => $request->getPost('street'),
'city' => $request->getPost('city'),
'postal' => $request->getPost('postal'),
'ic' => $request->getPost('ic'),
'dic' => $request->getPost('dic')
));
}
}
In addition to Kamil's answer, another option to consider is to use Javascript on the front-end to handle your multi-step form. This will add some complexity as you will need to have the javascript to handle the form steps and do preliminary validation, but it only requires a single submit where you can validate content within a single method.

Categories