Submit form values using controller and model in magento admin module - php

I am building an admin module and need to process a form but am having troubles getting the variables to POST and am just redirected to the dashboard. The form looks like this :
<form name="notes" action="<?php echo Mage::helper("adminhtml")->getUrl("foo/index/processnotes/");?>" method="post">
<input type="hidden" name="another_form_key" value="<? echo $this->getFormKey(); ?>" />
I am doing it that way because the secure keys are turned on for admin. It gives me a url like :
foo/index/processnotes/key/4745f5fbb9c168778958d5d4a4c2c0ef/
In the controller I have:
public function processnotesAction(){
$model = Mage::getModel('foo/process');
// I am not sure how I am supposed to send $_POST values here
}
and in Package/foo/Model/Process.php
I would hope to be able to process the POST variables from my form in here but I can not see what is wrong and I am just sent to dashboard.
<?php
class Package_foo_Model_Process extends Mage_Core_Model_Abstract
{
public function noteProcess() {
$test = $_POST['myValue'];
echo $test;
}
}
Update
After reading the answers I wanted to add a bit more of what my real code is doing and how I am using $_POST. I was setting up a simple example to just get the form to post but realizing there are probably many things I am doing wrong in Magento.
$query="INSERT INTO `notes_value` ( `color`, `the_id`, `the_value` ) VALUES ";
$sku = $_POST['color'];
array_pop($_POST);
foreach ($_POST AS $key => $value) {
$values[] = "('$sku', '$id', '$value')";
}
$query .= implode(', ', $values) . ';';
The dream is I could $resource->getConnection('core_write'); to actually insert this into the database but feeling less optimistic with how it is going so far.

Usually when you are getting redirected to the dashboard because your key is not recognised. I normally would use the following syntax
<input name="form_key" type="hidden" value="<?php echo Mage::getSingleton('core/session')->getFormKey() ?>" />
Also, I would be inclined to disable admin keys to verify whether that is your issue.
Next, never, ever use $_POST with Magento, all variables are accessible (cleanly and securely). POST information is accessible globally (not just in a controller), however you can still set variables in your model from the controller like this:
public function processnotesAction(){
$model = Mage::getSingleton('foo/process');
$model->setData('postdata', $this->getRequest()->getPost() );
}
Then accessing them from your model with:
$this->getData();
$this->getMyPostedField();
Or you could just use this in your Model
Mage::app()->getRequest()->getPost();
Mage::app()->getRequest()->getParam('myargument');
getPost can also take a parameter to fetch a single POST value - but it does not get GET values. getParam will return both GET and POST values alike.

Request params are accessible via the request object, Mage_Core_Controller_Request_Http. Example usage:
$request = $this->getRequest();
$params = $request->getParams();
$someParam = $request->getParam('param_key');
// or $params = $request->getPost();
You then need to set the data on your model and call $model->save().

If your controller extends ActionController, then the preDispatch() function is the one responsible for redirecting you to the dashboard (and checking for valid form key..).
I suggest you put Mage::log debug info into ActionController's preDispatch function, that might help identify what's going on?
I was gonna post a comment, but don't have high enough reputation.
(maybe update your post or comment on the answer that helped you, to see how you solved it (or not))

Related

Setting customer user data with CRUD object in Woocommerce

I'm trying to set a new value for the first_name for a user on woocommerce, i want to do this using the 'CRUD Objects in 3.0' present in the last documentation of woocommerce 3.0.
Só i'm definig the variable:
$wc_current_user = WC()->customer;
This return an instance of the class WC_Customer with has an array of $data with data about customer like $first_name, $last_name, $email, $billing_address array and so on...
i'm trying to rewrite the edit-account.php form and want to submit this data on this object, he provide the getters and setters to do this, but seems the setter ins't working, he is not saiving the data.
I'm doing this:
I have a form with takes the first name from the user, this is working fine, i'm using the ->get_first_name and is working fine.
<form class="woocommerce-account-information" action="" method="post">
<label>First Name</label>
<input type="text" name="first_name" value="<?php echo
$wc_current_user->get_first_name()?>"/>
<button type="submit">SAVE</button>
</form>
The Problema is here, when i try to submit this data using a setter, which in this case is 'object -> set_first_name' and 'object->save()', nothing happens, someone can help me?
Here is my code:
if( isset($_POST['first_name'] ) ){
$wc_current_user->set_first_name($_POST['first_name']);
$wc_current_user->save();
}
//THIS ^ DON'T WORK, do you know what is wrong?
I'm interested in knowing both the old and the new method, if anyone can help me, it will be a great help. Thank you!
You're using the correct method to set the user's first name.
set_first_name() won't permanently save a value on its own. When you've set all the properties you wish to update you need to call the save() method.
if ( isset( $_POST['first_name'] ) ) {
$wc_current_user->set_first_name( $_POST['first_name'] );
$wc_current_user->save();
}
https://woocommerce.wordpress.com/2016/10/27/the-new-crud-classes-in-woocommerce-2-7/
https://github.com/woocommerce/woocommerce/wiki/CRUD-Objects-in-3.0
I find a solution for this problem, when you use object like this you need to use the $object-save() method that Nathan has said plusthe $object->apply_changes(); to submit replace the data on data-base:
public function apply_changes() {
$this->data = array_replace_recursive( $this->data, $this->changes );
$this->changes = array();
}
My working code looks like this:
$wc_current_user = WC()->customer;
if ( isset($_POST['first_name']) ) {
$wc_current_user->set_first_name($_POST['first_name']);
$wc_current_user->save();
$wc_current_user->apply_changes();
}

Insert DB Value into Form Field

The Question: How do I insert values from a database table (#__mytable) into form text fields (motitle and modescription) which have been rendered from an XML file within the Joomla 3.0 platform?
-
I've been trying for days to solve this "easy" Joomla! based undocumented challenge.
I have followed Joomla!'s guide for Developing an MVC, read most of their out-of-date documentation and torn apart the com_content component but have still no idea how to populate my fields.
I've been playing with $this->form->bind($this->item);.
Below I have included some of my code to show the structure I am using. Please feel free to point out any issues you spot along the way.
Models\Forms\item.xml
<?xml version="1.0" encoding="UTF-8"?>
<form>
<fields name="groupOPTIONS">
<fieldset name="Options">
<field
type="text"
name="motitle"
id="motitle"
label="Title"
description="MY TEXT FIELD DESCRIPTION"
maxLength="255" />
<field
type="textarea"
name="modescription"
id="modescription"
label="Description"
description="MY TEXT FIELD DESCRIPTION"
rows="15"
cols="5"
maxLength="255" />
</fieldset>
</fields>
</form>
Models\item.php
jimport('joomla.application.component.modelitem');
class MagicObjectsModelItem extends JModelForm {
public function getForm($data = array(), $loadData = true) {
// Get the form 'items'
$form = $this->loadForm('com_magicobjects.item', 'item',
array('control' => 'jform', 'load_data' => $loadData));
if (empty($form)) {
return false;
}
return $form;
}
protected function loadFormData() {
// Check the session for previously entered form data.
$data = JFactory::getApplication()->getUserState('com_magicobjects.item.edit.data', array());
if (empty($data)) {
$data = $this->getDBItem(1);
}
return $data;
}
public function getDBItem($pk) {
//Obtain JDatabase static connection
$oDb = JFactory::getDbo();
$oQuery = $oDb->getQuery(true);
$sValueToMatch = $pk;
$oQuery
->select(array('mid', 'name', 'keyword', 'description'))
->from('#__mytable')
->where('mid = "' . $sValueToMatch . '"')
->order('mid ASC');
$oDb->setQuery($oQuery);
return $oDb->loadObjectList();
}
views\item\view.html.php
jimport('joomla.application.component.view');
function display($tpl = null) {
// Initialise variables.
$this->form = $this->get('Form');
$this->item = $this->get('Item');
//Display the view
parent::display($tpl);
}
Views\item\tmpl\default.php
foreach ($this->form->getFieldset('Options') as $field) {
echo $field->label;
echo $field->input;
}
By performing a print_r() on item I can see I have the data, but I need to insert the data into the fields shown.
In case this it's still a problem because the form definition is defining a <fields /> group.
This mean that the form fields will be output as follows:
input type="text" name="[groupOPTIONS][motitle]"
based on the example you give above. If you remove the fields grouping it will probably work. It's annoying though as certain JForm methods only work on groups...
You would probably need to change the way in which the data was being passed into the form if you wanted to keep the fields grouping (e.g. by overloading getItem).
Hope that makes sense...
In Joomla 3, the JForm::bind() method appears to accept either an object or associative array as a parameter. All of the object/array fields are then stored in a protected JRegistry type data member called JForm::$data.
When you're trying to display a form field (by calling JForm::getInput()), the call stack is as follows
JForm::getInput() -> JForm::getField() -> JForm::loadField() -> JForm::getValue()
JForm::getValue() returns a value from the (aforementioned JRegistry) JForm::$data data member. The JForm::loadField() method also passes the default value (defined by the form) to the JForm::getValue() method in case a value in the JForm::$data variable doesn't exist.
In terms of doing this inside a model, you might want to generate a object or assoc array from a database query or table (ensuring that the field names correspond with the field names defined in the form xml) and then pass it to JForm::bind() as a parameter. However, if you are using JModelForm, I think you should only override JModelForm::loadFormData() to pass the object/assoc array to the loaded form.
See : libraries/joomla/form/form.php
Hope that helps :)
Instead of $oDb->loadObjectList(); use $oDb->loadAssoc(); in your getDBItem() function.
Check this - http://docs.joomla.org/Accessing_the_database_using_JDatabase/1.5
Check this also - joomla loadformdata
Hope this will work.

Access post vars in the model or pass them through function calls in the view?

So while tinkering around with my own home built MVC framework I noticed something that looked in need of some refactoring.
If I have a function call in the view that calls a function residing in the model and that function takes session/post/get vars for parameters. Is it best to pass those vars as arguments in the function call or just access them in the function that's in the model?
Code in the view:
$model = $this->model; // Shortcut to the model
$vaildator = $this->model->validator; // Shortcut to the Validator object in the model
$btnPressed = $this->model->btnPressed; // Shortcut to the btnPressed flag var in the model
<label for="firstName">First Name: <span class="<?php echo $model->setReq($_POST['firstName'], 'First name'); // Set the class of the span tag the holds the 'required' text ?>">(required)</span></label>
<input type="text" name="firstName" id="firstName" title="First name" value="<?php echo htmlspecialchars($btnPressed ? $_POST['firstName'] : 'First name'); // Echo the user's entry or the default text ?>" maxlength="50" />
<?php if($btnPressed) $vaildator->valName($_POST['firstName'], true, true, 'First name'); // Check for errors and display msg if error is found ?>
Code in the model:
// If the field is empty or still contains the default text, highlight the 'required' error msg on the input field by changing the msg's class
// Note: used only for input fields that are required
public function setReq($postVar, $defaultText)
{
$className = 'required';
if($this->btnPressed)
{
$className = $postVar == '' || $postVar == $defaultText ? 'reqError' : 'required';
return htmlspecialchars($className);
}
else
{
return htmlspecialchars($className);
}
}
The reason I ask is because putting the arguments in the function calls in the view makes the view seem logic heavy but doing it the other way, accessing session/get/post vars in the model, seems a bit hacky and would make the code not very reusable. Thanks for any advice!
The solution is: decoupling.
Basically, pass the POST variables in the function call.
Why? Because the logic will stay separated (the controller will use whatever part of request it needs and then will call model), plus it will be a lot easier to test (you will be able to just pass fake arguments instead of faking $_POST and $_GET variables or doing some other fancy things). It will also be easier to debug.
In other words, decoupling will ease your work.

ZEND: Cannot Access Post Data

Greets.
{{Solved}}
In order to get POST data you MUST use $this->formHidden in order to hold all the data. Even though variables are inside the they don't get passed if they aren't in some sort of form item.
I am unable to access post data in ZEND.
Path of User -
START
INDEX PAGE
->Submit Page
->Pay Page
I created a controller, extended the Zend Controller, and added an action called payAction. The user can go from the Index Page to the Submit Page. After I have all their data inside variables, I used a form and a submit button to go to the "pay page". However, I cannot get any of the POST data.
public function payAction()
{
$data = $this->getRequest();
}
I have tried putting getRequest, getParam, getRawBody inside that controller function.
In the page itself I have tried.
echo 'Hello';
echo $request;
echo $data;
echo $_POST['payZip'];
echo $_POST['data'];
echo $_POST[$data];
echo $request;
echo $this->values['payZip'];
echo $payZip;
echo $this->values['shippingDone'];
echo $stuff;
Is there ANYTHING I can place in my controller or in my view in order to get my post data? I used a form method="post" and a button and it DOES allow me to get to the page. I can see Hello. But NONE of the post data is available.
Any assistance would be appreciated.
Thank you.
-- Update
$data = $this->getRequest();
$param = $this->_request->getParam('payZip');
if($this->getRequest()->isPost())
{
print_r($this->_getAllParams());
echo $param;
}
Doing that gives me -
HelloArray ( [controller] => wheel [action] => pay [module] => default [shipping] => UPS Ground [payPal] => Secure Payment System )
But I still can't print payZip... I did echo and nothing comes out.
To get parameters from Zend Framework you need to do this in the Action Controller:
$data = $this->_request->getParams();
You can also get individual params like this
$param = $this->_request->getParam('payZip');
What it appears your doing wrong is you're only getting the "request object". You need to then call that objects method to get the request data.
Here's some simple code I often use when testing parameters:
public function indexAction()
{
#::DEBUG::
echo '<pre>'; print_r($this->_request->getParams()); echo '</pre>';
#::DEBUG::
}
This will show all your parameters. What you will notice is that you will also get the names of the Module, Controller and Action with your params.
EDIT
Ps. If you're trying to use the parameter in the view script you need to do this:
echo $this->data['payZip'];
echo $this->param;
In your Action Controller, you save your data to the "view" object by doing this:
$this->view->myVariable = 'Hello';
But when you're in a view script, you are IN the view script, so $this represents $this->view from the action controller.
So, you access the variable like this:
echo $this->myVariable;
Wrapping everything into a bigger code chunk for understanding:
Your Controller
public function indexAction()
{
// get all parameters and pass them to the view
$this->view->params = $this->_request->getParams();
// get an individual parameter and pass it to the view
$this->view->payZip = $this->_request->getParam('payZip');
}
Your View Script
<!-- Dump all parameters -->
<pre><?php print_r($this->params); ?></pre>
<!-- Print payZip -->
<p>My PayZip is: <?php echo $this->payZip; ?></p>
<!-- Print payZip from full parameter array -->
<p>My PayZip (array) is: <?php echo $this->data['payZip']; ?></p>
I hope that helps!

Joomla PHP: Checkbox won't uncheck

Making a simple component. If I save a new record with the box checked, it saves fine. If I go back and uncheck a previously checked item it reverts back to checked. I thought it had something to do with a hidden field, played with putting one of those in manually but that didn't fix it either so took it out.
Here's where I'm at:
An xml snippet:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="1"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="1"
filter="intval"
/>
...
</fieldset>
The edit.php file:
<div class="width-45 fltlft">
<fieldset class="adminform">
<legend>Checkboxes</legend>
<ul class="adminformlist">
<?php foreach ($this->form->getFieldset('checks') as $field): ?>
<li>
<?php echo $field->label; ?>
<?php echo $field->input; ?>
</li>
<?php endforeach ?>
</ul>
</fieldset>
</div>
Also added this towards the end before the form.token:
<input type="hidden" name="task" id="task" value="completion.edit" />
I tried deleting the value="1" in the xml but then I had the opposite problem where the check wouldn't save at all.
Any ideas?
Thanks!
=============================
Edit:
Model:
<?php
defined( '_JEXEC' ) or die;
jimport('joomla.application.component.modeladmin');
class AssessModelCompletion extends JModelAdmin
{
//tells it what kind of record and the prefix
public function getTable($type = 'Completion', $prefix = 'AssessTable', $config = array())
{
return JTable::getInstance($type, $prefix, $config);
}
//Load the data into the edit form
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('com_assess.edit.completion.data', array()); //first try to get the data from the session, not db
if (empty($data)) {
$data = $this->getItem(); //this gets the data
}
return $data;
}
//Stores data in a session in case a field is missed
public function getForm($data = array(), $loadData = true)
{
$form = $this->loadForm('com_assess.completion', 'completion', array('control' => 'jform', 'load_data' => $loadData));
return $form;
}
}
And table:
<?php
defined ( '_JEXEC' ) or die;
class AssessTableCompletion extends JTable
{
public function __construct(&$db)
{
parent::__construct('#__tablename_completions', 'completion_id', $db);
}
}
======================================
References:
https://stackoverflow.com/questions/6964333/joomla-1-6-admin-form-processing-grouped-checkboxes-in-form
Tutorial code is not working any more in Joomla 2.5
http://docs.joomla.org/Developing_a_Model-View-Controller_%28MVC%29_Component_for_Joomla!1.7_-_Part_09#Adding_a_toolbar
So this is a kind of odd situation in that the documentation you list makes it seem that you would have to write no code to handle the checkbox (because as you point out a checkbox is different then checkboxes). But this does not seem to be the case because of the way that html checkboxes are submitted.
A quick overview of this issue and one solution can be found here: http://planetozh.com/blog/2008/09/posting-unchecked-checkboxes-in-html-forms/.
To use this, you would need to get the field's name out of the $field variable (which I'm not sure if it will be easy to access) and then place the <input type=hidden name='name' value=0> before <?php echo $field->input; ?>.
The other method to fix this would be to process the form data during save and override elements. Joomla has a prepareTable function that you could add to your model to edit data as necessary during save. The following example assumes that your form elements are wrapped in a jform array. (Confirm this by looking at the name fields in the html generated and they should be 'jform[checkbox1]')
protected function prepareTable(&$table)
{
$jform = JRequest::getVar('jform'); // load all submitted data
if (!isset($jform['checkbox1'])) { // see if the checkbox has been submitted
$table->checkbox1 = 0; // if it has not been submitted, mark the field unchecked
}
if (!isset($jform['checkbox2'])) { // likewise for other checkboxes
$table->checkbox2 = 0;
}
}
In this case, you would want to keep "value=1" in your xml fields file.
The problem ultimately is that Joomla loads the current data from the database during saving and then binds the posted data over the top of it. Because an unchecked box is not submitted in the post data, it does not overwrite the databases information and is thus not saved.
Although the documentation states that you do not have to do any manual handeling of the checkbox this is not true.
As no value is sent in the $_POST array when a checkbox is not checked the value is not overwritten and thus not saved which makes it impossible to uncheck the checkbox. To fix this you have to write special handling for your checkboxes in your table bind() function like this:
class YourcomponentTableYourview extends JTable
{
/**
* Constructor
*
* #param JDatabase A database connector object
*/
public function __construct(&$db)
{
parent::__construct('#__your_table_name', 'id', $db);
}
public function bind($array, $ignore = '')
{
if (!isset($array['name_of_field']))
$array['name_of_field'] = 0 ;
return parent::bind($array, $ignore);
}
}
As you don't have any model/table code showing, I think you may be mistaking JForm's purpose - it is purely for rendering of the form. You still have to have in your model/table something to handle the array that is returned for multivalued fields.
As Sam Moffat put it:
there is no coupling between the form definitions used to render the data and the models and table structures used to persist them
So I had a lot of fields and wanted to simply loop through them in my edit.php field to keep it clean. While all the answers offered were right they weren't easy to implement - got really messy really quickly, had trouble getting it to work, or couldn't figure out a cleaner way around it. I chewed on this for awhile and then today came across what is basically a field override.
The key:
The standard form field types are located in
joomla/libraries/joomla/form/fields/. You should not store custom
fields there, nor should you have to use this path in your own code,
but the standard types are usually good examples.
The custom field types that belong to your component are usually
located in administrator/components//models/fields. You can specify this or another path in your
code
So, I copied checkbox.php to models/fields. Then, towards the end of the file I added the empty field before the checkbox tag:
<input type="hidden" name="'.$this->name.'" id="'.$this->id.'" value="0" /><input type="checkbox" .....
Now, whenever I need a checkbox the empty field is also written. May not be the most efficient solution but simple to implement and can hopefully help someone else.
[Edit]
As a note, with every Joomla update you would probably need to compare the versions in the core in case there was a change.
I know this is an old question, but the official answer is long winded and I think I have a better solution.
Try setting the default value for the checkbox to 0 rather than 1 in your xml like so:
<fieldset name="checks">
<field name="checkbox1"
type="checkbox"
label="First Checkbox"
value="0"
filter="intval"
/>
<field name="checkbox2"
type="checkbox"
label="Second Checkbox"
value="0"
filter="intval"
/>
...
</fieldset>
I just came across your question and tried setting it to 0 as I didn't want to tamper with the core and hey presto it works.
My guess is that Joomla sees no value and thus sets the default instead.

Categories