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;
}
Related
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;
}
I have players in pages. I'm for instance on page 13. Here I click on the edit function to edit a player. Now after the edit I want to get back to that page 13 but It stays at the edit page.
edit action :
public function admin_edit($id = null) {
if (!$this->Player->exists($id)) {
throw new NotFoundException(__('Invalid player'));
}
if ($this->request->is(array('post', 'put'))) {
$data = $this->request->data['Player'];
if(!$data['player_image']['name']){
unset($data['player_image']);
}
if ($this->Player->save($data)) {
$this->Session->setFlash(__('The player has been saved.'));
$this->redirect($this->referer());
} else {
$this->Session->setFlash(__('The player could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('Player.' . $this->Player->primaryKey => $id));
$this->request->data = $this->Player->find('first', $options);
}
$videos = $this->Player->Video->find('list');
$this->set(compact('videos'));
}
view action :
public function admin_view($id = null) {
if (!$this->Player->exists($id)) {
throw new NotFoundException(__('Invalid player'));
}
$options = array('conditions' => array('Player.' . $this->Player->primaryKey => $id));
$this->set('player', $this->Player->find('first', $options));
}
You can save the referring page in the else section of the if/else structure of the edit function. Then use that stored value in the if (i.e., $this->request->is(array('post', 'put')) = TRUE section.
So your code would look something like:
public function admin_edit($id = null) {
if ($this->request->is(array('post', 'put'))) {
/* your other code */
$sendback = $this->Session->read('referer');
$this->Session->delete('referer');
$this->redirect($sendback);
} else {
/* your other code */
$this->Session->write('referer', $this->referer());
}
}
So can someone explain this to me?
I'm trying to write an edit action and am a bit unsure of why the following does not work:
public function edit($id = null) {
if (!$id) {
throw new NotFoundException('NO ID HAS BEEN SUPPLIED');
}
$data = $this->User->findById($id);
if(!$this->request->is('post')) { $this->request->data = $data; }
if($this->request->is('post') || $this->request->is('put')) {
$this->User->id = $id;
$this->User->save($this->request->data);
$this->redirect(array('action'=>'index'));
}
}
And by not working, I mean, that while it does pre-populate the form with data gathered from findById($id).. it doesn't update the database with the new inputs after the form has been sent.
I have replaced this:
if(!$this->request->is('post'))
With the following:
if($this->request->is('get'))
And suddenly, it works fine. It updates the row with the new values gathered from the post. However, I do not understand what's happening here. Why is it that !$this->request->is('post), does NOT work, while $this->request->is('get') DOES work?
Surely, when the action is first called it is called using a GET request? Doesn't that request qualify as !$this->request->is('post')?
EDIT:
below is the ctp: app/View/Users/edit.ctp
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend><?php echo __('edit User'); ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->input('role');
// echo $this->Form->input('role', array(
// 'options' => array('admin' => 'Admin', 'regular' => 'Regular')
//));//
?>
</fieldset> <?php echo $this->Form->end(__('Submit')); ?>
By default Cake uses 'PUT' method for 'edit' action and 'POST' for 'add'. so you need to check $this->request->isPut() (or $this->request->is('put')). Look for a hiiden field *_method* that automatically generated by $this->Form->create() method in your view.
If 'id' property is set in data passed to view Cake creates 'edit' form and 'add' if no 'id'.
Do it this way
public function edit() {
$id = $this->params['id'];
if (!$id) {
throw new NotFoundException('NO ID HAS BEEN SUPPLIED'); }
$data = $this->User->findById($id);
if(!$this->request->is('post')) { $this->request->data = $data; }
if($this->request->is('post') || $this->request->is('put')) {
$this->User->id = $id;
$this->User->save($this->request->data);
$this->redirect(array('action'=>'index'));}
passing id to edit from url is not safe way... $this->params['id'] will have your post id so
with it $this->request->is('put') will work.
I have file (ProfileController.php) which contains the following code:
public function editAction() {
if (Zend_Auth::getInstance()->hasIdentity()) {
try {
$form = new Application_Form_NewStory();
$request = $this->getRequest();
$story = new Application_Model_DbTable_Story();
$result = $story->find($request->getParam('id'));
// $values = array(
// 'names' => $result->names,
// 'password' => $result->password,
// );
if ($this->getRequest()->isPost()) {
if ($form->isValid($request->getPost())) {
$data = array(
'names' => $form->getValue("names"),
'password' => $form->getValue("password"),
);
$form->populate($data->toArray());
$where = array(
'id' => $request->getParam('id'),
);
$story->update($data, $where);
}
}
$this->view->form = $form;
$this->view->titleS= $result->title;
$this->view->storyS= $result->story;
} catch (Exception $e) {
echo $e;
}
} else {
$this->_helper->redirector->goToRoute(array(
'controller' => 'auth',
'action' => 'index'
));
}
}
and another file (edit.phtml) with following code:
<?php
try
{
$tmp = $this->form->setAction($this->url());
//$tmp->titleS=$this->title;
//$tmp->storyS=$this->story;
//echo $tmp->title = "aaaaa";
}
catch(Exception $e)
{
echo $e;
}
?>
I would like the users to be able to edit their Username and password. How do I go about it?
First: move the Zend_Auth stuff up to init() or preDispatch(), that way Auth will run against any or all actions in the controller.
The trick in getting more then one submit button to work is to give the buttons different names so that getParam('') has something to work with.
Normally I only do this sort of thing when doing deletes, for edit's or update's I just submit the whole array back to the database. I typically use the Zend_Db_Table_Row save() method instead of Zend_Db_Table's insert() or update() so the mechanism is a little different.
I just use a simple form to perform an update, here is the controller code (the view just echo's the form):
//update album information
public function updatealbumAction()
{ //get page number from session
$session = new Zend_Session_Namespace('page');
//get album id
$id = $this->getRequest()->getParam('id');
$model = new Music_Model_Mapper_Album();
//fetch the album database record
$album = $model->findById($id);
$form = new Admin_Form_Album();
//this form is used elsewhere so set the form action to this action
$form->setAction('/admin/music/updatealbum/');
if ($this->getRequest()->isPost()) {
if ($form->isValid($this->getRequest()->getPost())) {
$data = $form->getValues();//get valid and filtered form values
$newAlbum = new Music_Model_Album($data);//create new entity object
$update = $model->saveAlbum($newAlbum);//save/update album info
$this->message->addMessage("Update of Album '$update->name' complete!");//generate flash message
$this->getHelper('Redirector')->gotoSimple('update', null, null, array('page' => $session->page));//redirect back to the page the request came from
}
} else {
$form->populate($album->toArray());
$this->view->form = $form;
}
}
This is a pretty common update action.
Now here is how you might use different request parameters to perform an action on a record. I use this to delete database records but anything is possible.
public function deleteAction()
{
$session = new Zend_Session_Namespace('page');
$request = $this->getRequest()->getParams();
try {
switch ($request) {
//if
case isset($request['trackId']):
$id = $request['trackId'];
$model = new Music_Model_Mapper_Track();
$model->deleteTrack($id);
$this->message->addMessage("Track Deleted!");
break;
case isset($request['albumId']):
$id = $request['albumId'];
$model = new Music_Model_Mapper_Album();
$model->deletealbum($id);
$this->message->addMessage("Album Deleted!");
break;
case isset($request['artistId']):
$id = $request['artistId'];
$model = new Music_Model_Mapper_Artist();
$model->deleteArtist($id);
$this->message->addMessage("Artist Deleted!");
break;
default:
break;
}
$this->getHelper('Redirector')->gotoSimple('update', null, null, array('page' => $session->page));
} catch (Exception $e) {
$this->message->addMessage($e->getMessage());
$this->getHelper('Redirector')->gotoSimple('update', null, null, array('page' => $session->page));
}
}
you can pass the request parameters as submit button labels or as urls or whatever works for you.
Good Luck!
I've noticed that their is many different ways to pass an ID to a form when editing a database entry. So for example for a edit user profile form I have the following code:
function edit($id = null)
{
$this->layout = 'page';
// this line isn't needed?
//$this->User->id = $id;
if (empty($this->data))
{
$this->data = $this->User->read();
}
else
{
if ($this->User->save($this->data))
{
$this->Session->setFlash('Your profile has been updated', 'flash', array('header' => 'Announcement', 'myclass' => 'success'));
$this->redirect(array('controller' => 'users', 'action' => 'view', $id));
}
}
}
Now the function expects an id passing in the url e.g. /users/edit/2 But let's say I wanted it to be something more user friendly like /profile/edit (rewrote by routing) I would no longer be passing in the ID as part of the url. As you can see in my code I have a line I have commented out because it isn't needed?
Also in the form I ALSO Need <?php echo $this->Form->input('id', array('type' => 'hidden')); ?> why?
Basically this is more of what are the options available to me to build various types of edit forms and passing data to the form. And what is the need for the hidden field in the form if the data is being passed either via the URL or some other way
I've also noticed on some sites that they have things like Form Keys and the username stored in meta tags in the page header???
EDIT:
public function beforeFilter()
{
$this->set('authUser', $this->Auth->user());
//
$user = $this->Auth->user();
if (!empty($user))
{
Configure::write('User', $user[$this->Auth->getModel()->alias]);
}
}
public function beforeRender()
{
$user = $this->Auth->user();
if (!empty($user))
{
$user = $user[$this->Auth->getModel()->alias];
}
$this->set(compact('user'));
}
// NEW VERSION
function settings()
{
$this->layout = 'page';
$this->set('title_for_layout', 'Edit Profile');
$this->User->id = $user['id'];
if (empty($this->data))
{
$this->data = $this->User->read();
}
else
{
if ($this->User->save($this->data))
{
$this->Session->setFlash('Your settings have been updated', 'flash', array('myclass' => 'success'));
$this->redirect(array('controller' => 'users', 'action' => 'settings'));
}
}
}
Also in the form I ALSO Need Form->input('id',
array('type' => 'hidden')); ?> why?
Having the id hidden in the form removes the need for your controller action to grab the $id from the uri (aka passed as parameter). When in the form, it will automatically be placed into your $data array.
what is the need for the hidden field
in the form if the data is being
passed either via the URL or some
other way
It's not needed in the form if it's available from the uri. You'd simply grab the $id and assign it to the User model (as the commented out code does).
let's say I wanted it to be something
more user friendly like /profile/edit
I assume that would be when the user is editing his own profile. In that case, your system should be able to retrieve the user's id via the session.