Zend framework session data to form fields - php

I'm working on a multistep form and also there are previous buttons in that. When a user clicks the previous button they go a step back as expected, but the form is not filled with the data that is already filled in that step.
The data is stored in a session, so i thaught this wil work (in the controller):
if($this->getRequest()->isPost()) {
if ($this->getRequest()->getPost('previous')){
$data = $this->sessionContainer->PlaatsenAdvertentie;
}
else{
$data = $this->params()->fromPost();
}
$form->setData($data);
$viewModel = new ViewModel([
'form' => $form
]);
return $viewModel;
}
But no...

I made a function inside the form class:
public function populate($step,$data)
{
foreach($data['step'.$step] as $field => $value){
//uitgezond de submit en vorigestap buttons
if ($field != 'submit' && $field != 'vorigestap'){
$this->get($field)->setValue($value);
}
}
return $this;
}

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
}

Avoid similar controller actions

I am building a bundle for private messages between my users.
Here is my inbox action from my controller. What it does is fetches the current user's messages, it passes the query to KNPpaginator to display a part of them. I also save how many results to be displayed on the page in the database. One form is a dropdown that sends how many results to display per page. The other form is made of checkboxes and a dropdown with actions. Based on which action was selected, I pass the id's of the messages(selected checkboxes id's) to another function called markAction(which is also a page that can mark one single message by going to the specific url)
public function inboxAction(Request $request)
{
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$mymsg = $messages->findMyMessages($this->getUser());
$message_settings = $this->getDoctrine()->getRepository('PrivateMessageBundle:MessageSettings');
$perpage = $message_settings->findOneBy(array('user' => $this->getUser()));
$pagerform = $this->createForm(new MessageSettingsType(), $perpage);
$pagerform->handleRequest($request);
if ($pagerform->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($perpage);
$em->flush();
}
$paginator = $this->get('knp_paginator');
$pagination = $paginator->paginate(
$mymsg,
$request->query->get('page', 1)/*page number*/,
$perpage ? $perpage->getResPerPage() : 10/*limit per page*/,
array('defaultSortFieldName' => 'a.sentAt', 'defaultSortDirection' => 'desc')
);
$form = $this
->createForm(
new ActionsType(),
$mymsg->execute()
);
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
$ids = array();
foreach ($data['checkboxes'] as $checkbox) {
$ids[] = $checkbox->getId();
}
$action = $data['inboxactions'];
$this->markAction($action, $ids);
return $this->redirectToRoute('private_message_inbox');
}
return $this->render(
'#PrivateMessage/inbox.html.twig',
array(
'messageList' => $pagination,
'form' => $form->createView(),
'pagerform' => $pagerform->createView(),
)
);
}
And the mark action user in my inbox controller. Based on one parameter, I apply the respective action to the second parameter, which is one message if the page was called through routing, and can be an array of messages if called through my inboxAction. I do a few consistency checks, and then mark my message.
public function markAction($action, $msgs)
{
if (!$msgs) {
$this->addFlash(
'error',
'Select at least one message!'
);
return;
} else {
if (!$action) {
$this->addFlash(
'error',
'Select one action to apply to your items!'
);
return;
} else {
$messages = $this->getDoctrine()->getRepository('PrivateMessageBundle:Message');
$em = $this->getDoctrine()->getManager();
$msg = $messages->findBy(array('receiver' => $this->getUser(), 'id' => $msgs));
$good = 0;
foreach ($msg as $isforme) {
$good++;
switch ($action) {
case 'spam': {
if ($isforme->getIsSpam() == false) {
$isforme->setIsSpam(true);
if (!$isforme->getSeenAt()) {
$isforme->setSeenAt(new \DateTime('now'));
}
$em->persist($isforme);
}
break;
}
case 'unspam': {
if ($isforme->getIsSpam() == true) {
$isforme->setIsSpam(false);
$em->persist($isforme);
}
break;
}
case 'viewed': {
if ($isforme->getSeenAt() == false) {
$isforme->setSeenAt(new \DateTime('now'));
$em->persist($isforme);
}
break;
}
case 'unviewed': {
if ($isforme->getSeenAt() != false) {
$isforme->setSeenAt(null);
$em->persist($isforme);
}
break;
}
default: {
$this->addFlash(
'error',
'There was an error!'
);
return;
}
}
$em->flush();
}
$this->addFlash(
'notice',
$good.' message'.($good == 1 ? '' : 's').' changed!'
);
}
}
if ($action == 'unspam') {
return $this->redirectToRoute('private_message_spam');
} else {
return $this->redirectToRoute('private_message_inbox');
}
}
Being kind of new to symfony, I'm not sure how good my markAction function is. I feel like it can be simplier, but I'm not sure how to make it.
Now, my actual question. How can I render other pages of my bundle, like Sent or Spam messages? The only lines from the inboxAction that I have to change are
$mymsg = $messages->findMyMessages($this->getUser());
to have it return spam or sent messages by the user, for instance.
and
return $this->render(
'#PrivateMessage/inbox.html.twig',...
so I actually return the respective page's view. I have already made the other pages and copied the code in the other actions, but I think I can make it so I write this code a single time, but don't know how.
Everything else is EXACTLY the same. How can I not copy and paste this code in all of the other actions and make it a bit more reusable?
You could strart to change your routing more dynamic:
# app/config/routing.yml
mailclient:
path: /mailclient/{page}
defaults: { _controller: AppBundle:Mailclient:index, page: "inbox" }
Resulting that this routes:
/mailclient
/mailclient/inbox
/mailclient/sent
/mailclient/trash
will all call the same action.
Now your method (Action) will get an extra parameter:
public function indexAction($page, Request $request)
{
// ...
}
Through this parameter you know what the user likes to see. Now you can start to write your code more dynamic. You can consider to add some private functions to your controller class that you can call from the indexAction or
you could simply create your own classes too.

before save in Yii2

I have a form with multi-select fields named "city" form in Yii2. When I submit form
the post data show me the following:
$_POST['city'] = array('0'=>'City A','1'=>'City B','2'=>'City C')
But I want to save the array in serialize form like:
a:3:{i:0;s:6:"City A";i:1;s:6:"City B";i:2;s:6:"City C";}
But I don't know how to modify data before save function in Yii2. Followin is my code:
if(Yii::$app->request->post()){
$_POST['Adpackage']['Page'] = serialize($_POST['Adpackage']['Page']);
$_POST['Adpackage']['fixer_type'] = serialize($_POST['Adpackage']['fixer_type']);
}
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model
]);
}
Please help me.
Thanks all for your effort. I have solved the issue. here is the code :
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
$this->Page = serialize($_POST['Adpackage']['Page']);
$this->fixer_type = serialize($_POST['Adpackage']['fixer_type']);
return true;
} else {
return false;
}
}
Just put this code in model and its working
It's because Yii::$app->request->post() is different than $_POST at this stage. Try to change your code to:
$post = Yii::$app->request->post();
$post['Adpackage']['Page'] = serialize($post['Adpackage']['Page']);
$post['Adpackage']['fixer_type'] = serialize($post['Adpackage']['fixer_type']);
$model->load($post);
Update:
Also it would be better to do it on ActiveRecord beforeSave() method.

cakephp form action link

i am developing with cakephp (2.4.7) and i have a problem with a form action link.
I'm having a usersController with edit action.
public function edit($id = null, $slug = null) {
if (!$id) {
throw new NotFoundException(__('Invalid User'));
}
$user = $this->User->findById($id);
if (!$user) {
throw new NotFoundException(__('Invalid User'));
}
if ($this->request->is(array('post', 'put'))) {
// Do stuff here
}
// Fill the form
if (!$this->request->data) {
$this->request->data = $user;
}
}
with this code the form ($this->create->('User')); in the edit view get filled correctly. But i have another form in the edit view.
Like:
echo $this->Form->create(null, array(
'url' => array('controller' => 'useraddresses', 'action' => 'add')
));
echo $this->Form->input('searchvalue');
echo $this->Form->hidden('country');
echo $this->Form->hidden('city');
echo $this->Form->end('save');
When i click the send button from this form, the page links to /useraddresses/add/2 (2 is the id of the user)
I have debuged the form with firebug and in the action parameter is also /useraddresses/add/2.
How can i get arround this? I will to send the form to /useraddresses/add without any parameters.
If i delete this piece of code in my edit action, the action link is correctly but my first form does not get filled.
// Fill the form
if (!$this->request->data) {
$this->request->data = $user;
}
Use following
if(empty($this->data) )
{
if (!$this->request->data) {
$this->request->data = $user;
}
}
Instead of ur
if (!$this->request->data) {
$this->request->data = $user;
}

Submit Two forms in one controller

How can I make sure that, that second form elements go to the database cause when I check there the is no data but its been inputted by the user, if both forms are called from one controller
$form = new Form_Form1();
$this->view->form = $form;
$form2 = new Form_Form2();
$this->view->form2 = $form2;
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
Try this:
if ($form->isValid($formData) && $form2->isValid($formData)) {...

Categories