Insert DB Value into Form Field - php

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.

Related

Should I use set_value() to repopulate a form in CodeIgniter

My question is whether I should use set_value() at all to re-populate a form. It might seem odd to say that, however I am creating a shared controller function and view which can be used to either add a new record or edit an existing one. It seems to make sense to do this since the functionality is so incredibly alike.
As such, if we call up an existing record to edit I do this:
$data['fields'] = $this->customer_model->get_customer($id);
If the form is submitted to save the record, or if we're adding a record for the first time, the form has the potential to reload if the user makes a mistake so I populate $data['fields'] this way instead:
$data['fields'] = array(
'company' => $this->input->post('company') ?: '',
'website' => $this->input->post('website') ?: '',
'credit_limit' => $this->input->post('credit_limit') ?: ''
);
My form element looks like this:
<input type="text" name="company" value="<?php echo set_value('company', $fields['company']); ?>" />
But I'm thinking it may as well look like this:
<input type="text" name="company" value="<?php echo escape_html($fields['company']); ?>" />
Since the form data could come from either user input (when adding or saving) or from the database (when retrieving a record to edit) I cannot rely entirely on post() or set_value() without the 2nd parameter. Furthermore, the second parameter for set_value() will always exist ($fields['company'] in this example) because it's initialized from the start, which is why I am thinking of just using it directly.
Is there a problem with this approach?
If you want to populate form fields on FALSE return of Form Validation or insert data for editing operations, I suggest you to use following helper:
Usage
<input type="text" name="last_name" value="<?=vset_value('last_name','',$rs);?>">
Explanation
$rs here is the $db data for record (if you are sending it to view). To stay at the safe side please include $this->data['rs'] = false; at your controller. If $rs is set and true, helper take results from it and display it. Otherwise it displays if the key exist in $_POST. If both don't exists, it display default value.
Helper
/**
* vayes_helper::vset_value
*
* Retains state of INPUT text after Form Validation
*
* #access public
* #param string name of INPUT tag
* #param string default value for INPUT tag
* #param mixed DB Result (array or object)
* #return string
*/
if(!function_exists('vset_value')) {
function vset_value ($name_of_input,$default_state='',$db_result_array='') {
$CI = &get_instance();
$render_state = $default_state;
if($CI->input->post()) {
$render_state = $CI->input->post($name_of_input);
} else {
if(is_object($db_result_array) && isset($db_result_array->$name_of_input)) {
$render_state = (isset($db_result_array->$name_of_input)) ? $db_result_array->$name_of_input : $default_state;
} else if($db_result_array != '' && array_key_exists($name_of_input,$db_result_array)) {
$render_state = (isset($db_result_array[$name_of_input])) ? $db_result_array[$name_of_input] : $default_state;
}
}
return $render_state;
}
}
If you like the way, let me know. I can supply for more form input type like select, checkbox, etc.
The approach is correct, as mentioned in the CodeIgniter docs. In fact, you don't need to include the second parameter in set_value.
set_value definition:
string set_value(string $field = '', string $default = '')
//$field: If there is a submitted field with this name, its value is returned.
//$default: If there is no matching submitted field, this value is returned.
Yes,You should.
set_value() is used to re-populate a form has failed validation.
There is no additional filtering on it, so it faster.
But, I prefer some times to use $this->input->post() for the secure.

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 framework text fields with same name but with different belongings

I have a problem with zend form, where i need to built a form where field name are same but with different belongings. Here is the input fields that i wanted inside my form.
Currently i am getting with straight html but because of this i am missing validation.
<input type="text" name="travel_guide_tab[4][title]">
<input type="text" name="travel_guide_tab[4][description]">
<input type="text" name="travel_guide_tab[6][title]">
<input type="text" name="travel_guide_tab[6][description]">
In Zend Form the element names must be unique (in some way) or else they will overwrite. However you can continue using your html form and simply filter and validate in the controller using Zend_Filter_Input. The filter and validation classes are the same ones used by Zend_Form you just pass the data in a different way.
Simple example, partial:
public function someAction() {
//set filters and validators for Zend_Filter_Input
$filters = array(
'nameOfInput' => array('HtmlEntities', 'StripTags')
);
$validators = array(
'nameOfInput' => array('NotEmpty', 'Int')
);
//assign Input
$input = new Zend_Filter_Input($filters, $validators);//can also pass the data in constructor (optional)
$input->setData($this->getRequest()->getParams());
//check input is valid and is specifically posted as 'Delete Selected'
if ($input->isValid()) {
//do some stuff
}
Good Luck.

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.

Submit form values using controller and model in magento admin module

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))

Categories