Fetching and saving data to database at backend of Joomla 3.x component
Files to create / update
update breed.php /administrator/tables/breed.php
update breed.php /administrator/models/breed.php
File Details
/administrator/tables/breed.php
public function check()
{
if (property_exists($this, 'ordering') && $this->id == 0)
{
$this->ordering = self::getNextOrder();
}
// Support multi file field: pic
$app = JFactory::getApplication();
$files = $app->input->files->get('jform', array(), 'raw');
$array = $app->input->get('jform', array(), 'ARRAY');
if (!empty($files['pic']))
{
$this->pic = "";
foreach ($files['pic'] as $singleFile )
{
jimport('joomla.filesystem.file');
// Check if the server found any error.
$fileError = $singleFile['error'];
$message = '';
if ($fileError > 0 && $fileError != 4)
{
switch ($fileError)
{
case 1:
$message = JText::_('File size exceeds allowed by the server');
break;
case 2:
$message = JText::_('File size exceeds allowed by the html form');
break;
case 3:
$message = JText::_('Partial upload error');
break;
}
if ($message != '')
{
$app->enqueueMessage($message, 'warning');
return false;
}
}
elseif ($fileError == 4)
{
if (isset($array['pic']))
{
$this->pic = $array['pic'];
}
}
else
{
// Check for filesize
$fileSize = $file['size'];
if ($fileSize > 10485760)
{
$app->enqueueMessage('File bigger than 10MB', 'warning');
return false;
}
jimport('joomla.filesystem.file');
$filename = JFile::stripExt($singleFile['name']);
$extension = JFile::getExt($singleFile['name']);
$filename = preg_replace("/[^A-Za-z0-9]/i", "-", $filename);
$filename = $filename . '.' . $extension;
$uploadPath = JPATH_ROOT . '/components/com_breed/breedpic/' . $filename;
$fileTemp = $singleFile['tmp_name'];
if (!JFile::exists($uploadPath))
{
if (!JFile::upload($fileTemp, $uploadPath))
{
$app->enqueueMessage('Error moving file', 'warning');
return false;
}
}
$this->pic .= (!empty($this->pic)) ? "," : "";
$this->pic .= $filename;
}
}
}
return parent::check();
}
protected function _getAssetName()
{
$k = $this->_tbl_key;
return 'com_breed.breed.' . (int) $this->$k;
}
protected function _getAssetParentId(JTable $table = null, $id = null)
{
$assetParent = JTable::getInstance('Asset');
$assetParentId = $assetParent->getRootId();
$assetParent->loadByName('com_breed');
if ($assetParent->id)
{
$assetParentId = $assetParent->id;
}
return $assetParentId;
}
public function bind($array, $ignore = '')
{
$input = JFactory::getApplication()->input;
$task = $input->getString('task', '');
if (($task == 'save' || $task == 'apply') && (!JFactory::getUser()->authorise('core.edit.state', 'com_breed.breed.'.$array['id']) && $array['state'] == 1))
{
$array['state'] = 0;
}
if ($array['id'] == 0)
{
$array['created_by'] = JFactory::getUser()->id;
}
if (!empty($array['pic']))
{
if (is_array($array['pic']))
{
$array['pic'] = implode(',', $array['pic']);
}
elseif (strpos($array['pic'], ',') != false)
{
$array['pic'] = explode(',', $array['pic']);
}
}
else
{
$array['pic'] = '';
}
if (isset($array['params']) && is_array($array['params']))
{
$registry = new JRegistry;
$registry->loadArray($array['params']);
$array['params'] = (string) $registry;
}
if (isset($array['metadata']) && is_array($array['metadata']))
{
$registry = new JRegistry;
$registry->loadArray($array['metadata']);
$array['metadata'] = (string) $registry;
}
if (!JFactory::getUser()->authorise('core.admin', 'com_breed.breed.' . $array['id']))
{
$actions = JAccess::getActionsFromFile(
JPATH_ADMINISTRATOR . '/components/com_breed/access.xml',
"/access/section[@name='breed']/"
);
$default_actions = JAccess::getAssetRules('com_breed.breed.' . $array['id'])->getData();
$array_jaccess = array();
foreach ($actions as $action)
{
$array_jaccess[$action->name] = $default_actions[$action->name];
}
$array['rules'] = $this->JAccessRulestoArray($array_jaccess);
}
// Bind the rules for ACL where supported.
if (isset($array['rules']) && is_array($array['rules']))
{
$this->setRules($array['rules']);
}
return parent::bind($array, $ignore);
}
private function JAccessRulestoArray($jaccessrules)
{
$rules = array();
foreach ($jaccessrules as $action => $jaccess)
{
$actions = array();
foreach ($jaccess->getData() as $group => $allow)
{
$actions[$group] = ((bool) $allow);
}
$rules[$action] = $actions;
}
return $rules;
}
_getAssetName is the method to compute the default name of the asset which will then be included in the #__assets table of Joomla associated database.
The Check method.
The check method in the table class checks that the properties which are bound to the object are valid and in response this method returns either boolean true or false. We are overriding the check method here to make some checks on our multiple form uploading field, to set the file type of the file which is or are being uploaded, their max size and setting the directory in which the image files will be uploaded.
First we are getting the next ordering value for a single or multiple rows by the getNextOrder() method, which returned value will be assigned to the ordering key and it will be manipulated later, when the form will be ready to save in the database. Next, from line 87 to 89, we have wrtitten some code to support multiple file upload.
Next, by assuming that the provided pic field value is not emplty, we are first removing any previous pic field value and then trying to create a key value pair through foreach loop, so that we can manipulate each file seperately. Then we are importing the filesystm library through which we can manipulate and deal with the files, in joomla. Copy, delete, move and upload are the most common methods used, which are provided by this library and have classes like JFile, JFolder, JPath and JArchive.
Now, if we try to upload a file from frontend ot backend interface of the component, we are developing and if we tackle with some error, like the wrong file type or maximum file size error or partial upload error, we are trying to set proper error messages here first and will send them to user in the form of an error message. These errors occur on the basis of file handling settings in the php.ini configuration file of your web server. You can change its settings according to your requirements.
Next from line 135 to 142, we are setting a default size limit of the file and if it exceeds from that, an error message will be thrown and the code will stop execution right there. If the file size is ok, we start manipulating and saving the file from line 144 to 162, by replacing any special characters in the filename and then assigning the upload path and directory name, in which the file will be uploaded. The code will also check the existance of the directory and whether it is write protected. If it encounters any issues, it will send an error message back to the user, indicating him that it is facing issues while moving the file.
/administrator/models/breed.php
public function getItem($pk = null)
{
if ($item = parent::getItem($pk))
{
// Do any procesing on fields here if needed
}
return $item;
}
protected function loadFormData()
{
$data = JFactory::getApplication()->getUserState('com_breed.edit.breed.data', array());
if (empty($data))
{
if ($this->item === null)
{
$this->item = $this->getItem();
}
$data = $this->item;
}
return $data;
}
protected function prepareTable($table)
{
jimport('joomla.filter.output');
if (empty($table->id))
{
if (@$table->ordering === '')
{
$db = JFactory::getDbo();
$db->setQuery('SELECT MAX(ordering) FROM #__breed_breed');
$max = $db->loadResult();
$table->ordering = $max + 1;
}
}
}
There is a new function in this file, called loadFormData on line 130 in the above mentioned code. First we attempt to get the data from the session. If someone is entering data into the form, it might be a new record and does not exist already in the database. So, the purpose of session is, if someone is redirected back to the form for correcting a mistake or filling up a required field, it will load the data again that user has entered in other fields before pressing the submit button, instead of loading data from database. On line 134, what we are doing is, if the session is empty, we will try to get the data from database, by using getItem(). Finally we return the data to jForm.
The prepareTable method
The prepareTable method is called just before the form is saved to the database and give you a full control of the data that is going to be submit, so that you can manipulate it, as you want. What we are doing here in this method is, we are setting a value for the ordering column of the database table. The id field is auto incremental and is provided by database automatically. So, first we are making a check that whether it is already provided, meaning that user is editing a record or saving a new one. If a new form is submitted without any id value and ordering field is also empty,a query will run, which will get the maximum ordering value and make an addition of 1 to it and this new value will be assigned to the ordering key of table object.