Comstum magento extention doesnt save form post value - database

I'm trying to create a custom magento extension.
It works, only 1 form field is not saved to the db.
public function saveAction()
{
if ($postData = $this->getRequest()->getPost()) {
$model = Mage::getSingleton('foo_bar/baz');
$model->setData($postData);
try {
$model->save();
Mage::getSingleton('adminhtml/session')->addSuccess($this->__('The baz has been saved.'));
$this->_redirect('*/*/');
return;
}
catch (Mage_Core_Exception $e) {
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
}
catch (Exception $e) {
Mage::getSingleton('adminhtml/session')->addError($this->__('An error occurred while saving this baz.'));
}
Mage::getSingleton('adminhtml/session')->setBazData($postData);
$this->_redirectReferer();
}
}
The form:
protected function _prepareForm()
{
$model = Mage::registry('foo_bar');
$form = new Varien_Data_Form(array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
'method' => 'post'
));
$fieldset = $form->addFieldset('base_fieldset', array(
'legend' => Mage::helper('checkout')->__('Baz Information'),
'class' => 'fieldset-wide',
));
if ($model->getId()) {
$fieldset->addField('id', 'hidden', array(
'name' => 'id',
));
}
$fieldset->addField('name', 'text', array(
'name' => 'name',
'label' => Mage::helper('checkout')->__('Name'),
'title' => Mage::helper('checkout')->__('Name'),
'required' => true,
));
$fieldset->addField('stock', 'text', array(
'name' => 'stock',
'label' => Mage::helper('checkout')->__('stock'),
'title' => Mage::helper('checkout')->__('stock'),
'required' => true,
));
$form->setValues($model->getData());
$form->setUseContainer(true);
$this->setForm($form);
return parent::_prepareForm();
}
}
The value of the 'stock field is not saved'.
I checked that the column stock exist in the db and en name's are the same.
Does anyone know what I'm doing wrong?
Thanks in advance.

If you have added stock field after all the others it is possible that you only need to clear cache through admin System -> Cache Management (Flush Magento Cache and Flush Cache Storage buttons).
Magento likes to cache previous queries so adding new fields without clearing the cache can cause problems with new columns not being saved.

Related

Cake php modal validation error

I have a simple registration form and complete model validation.
public function add() {
// Has any form data been POSTed?
if ($this->request->is('post')) {
$this->User->set($this->request->data); //echo '<pre>'; print_r($this->data);exit;
if($this->User->validates()){
if ($this->User->save($this->request->data)) {
// Set a session flash message and redirect.
$this->Session->setFlash('User Saved!');
return $this->redirect('/users');
}
}
}
}
Modal validation code is below
class User extends AppModel {
public $validate = array(
'username' => array(
'alphaNumeric' => array(
'rule' => 'alphaNumeric',
'required' => true,
'message' => 'Alphabets and numbers only'
),
'between' => array(
'rule' => array('between', 5, 15),
'message' => 'Between 5 to 15 characters'
)
),
'password' => array(
'rule' => array('minLength', '8'),
'message' => 'Minimum 8 characters long'
),
'email' => 'email',
'born' => array(
'rule' => 'date',
'message' => 'Enter a valid date',
'allowEmpty' => true
)
);
}
The problem is that when i delete html fields using firebug and submit form it save data with blank entries . i think its a big problem i am facing because it not good practice to save blank entry and i want to stop it by the hacker or any one.
please help.
Add the validation rule 'notEmpty' for all fields which shouldn't be blank entries in the database.
Reference: cookbook
I am agree with semmelbroesel13
please use notEmpty rules as:
'rule' => array('notempty')
Updated:
Please try below code and check whats the query exactly
public function add() {
// Has any form data been POSTed?
if ($this->request->is('post')) {
$this->User->set($this->request->data); //echo '<pre>'; print_r($this->data);exit;
if($this->User->validates()){
if ($this->User->save($this->request->data)) {
$log=$this->User->getDataSource()->getLog(false, false);
echo "<pre>";print_r($log);exit;
// Set a session flash message and redirect.
$this->Session->setFlash('User Saved!');
return $this->redirect('/users');
}
}
}
}

Simple CakePHP search action

I want a simple search feature that can search the current selected results on the model's index page. I have created a model Search which has no actual table:
class Search extends AppModel {
protected $_schema = array(
'search_term' => array('type' => 'string' , 'null' => true, 'default' => '', 'length' => '255'),
'model' => array('type' => 'string' , 'null' => true, 'default' => '', 'length' => '255'),
);
public $useTable = false;
public $validate = array(
'search_term' => array(
'notEmpty' => array(
'rule' => array('notEmpty'),
'message' => 'Please enter a search term'
),
'between' => array(
'rule' => array('between',3,30),
'message' => 'Please enter a search term greater than 3 characters.'
)
)
);
}
In any index.ctp view I have this with a hidden input field with the model's name:
echo $this->Form->create('Search, array('action' => 'search'));
echo $this->Form->input('search_term', array('label'=> 'Search'));
echo $this->Form->input('model', array('type'=> 'hidden', 'value'=>$this->params['controller']));
echo $this->Form->end(__('Submit'));
In the SearchesController:
public function search() {
$conditions = null;
if( $this->request->is('post') ) {
$searchModel = $this->request->data[$this->modelClass]['model'];
...
$this->{$this->modelClass}->useTable = Inflector::tableize($searchModel);
...
$this->paginate = array('conditions'=>array($groups,'OR' => $conditions));
$this->set($searchModel, $this->paginate());
$this->render("/$searchModel/index");
}
Problem is paginate is returning an array with the model labelled as 'Search' (understandably because of the useTable call) and not say Groups or Users, the model's being searched. Any way to relabel the array returned from paginate to the model being searched ? The alternative is to modify all the index.ctp files or create a results.ctp for each model.
I wouldn’t create another model merely for searching; it’s a hack and not extendable.
In the past, I’ve just used parameters (usually in the query string) to alter the conditions array (whether it’s a normal find operation of a paginate operation). An example:
<?php
class ItemsController extends AppController {
public function index() {
$conditions = array();
if (isset($this->request->query['search'])) {
$conditions['Item.title'] = $this->request->query['search'];
}
$items = $this->Item->find('all', array(
'conditions' => $conditions
));
$this->set(compact('items'));
}
}
Hopefully the above demonstrates this approach.

Better approach to do this for security and code management purpose

I am working on a Cakephp 2.3 on a very big project and I'm about to launch my site worldwide.
I have a login system on my app. I am sharing my code because I want to make sure if I am coding right or not ... and also any check for any functions missing or if any advice of adding something or removing something in the code would be greatly appreciated. And also comment in security perspective too...
Do tell me some tips of making my website faster.. for example how to write faster queries or remove unwanted from this blabla
class UsersController extends AppController
{
public $components = array('Cookie');
public function beforeFilter()
{
parent::beforeFilter();
App::uses('Utility', 'Utility');
$this->Auth->allow('index');
$this->Security->requireSecure('login'); // for security
$this->Auth->authenticate = array(
'Authenticate.Cookie' => array(
'fields' => array(
'username' => 'email',
'password' => 'password'
),
'userModel' => 'User',
'scope' => array(
'User.active' => 1
)
),
'Authenticate.MultiColumn' => array(
'fields' => array(
'username' => 'email',
'password' => 'password'
),
'columns' => array(
'email',
'mobileNo'
),
'userModel' => 'User'
)
);
}
public function index()
{
$this->layout = 'logindefault';
if (!$this->Auth->login() || !$this->Auth->loggedIn()) {
$this->redirect(array(
'controller' => 'users',
'action' => 'login'
));
} else {
$this->redirect(array(
'controller' => 'users',
'action' => 'dashboard'
));
}
}
public function login()
{
$this->layout = 'logindefault';
$this->set('title_for_layout', 'Account Login');
if ($this->Auth->login() || $this->Auth->loggedIn()) {
$lastLogin = $this->Auth->User('lastLogin');
if ($lastLogin != null) {
$this->redirect($this->Auth->redirect());
} else {
$this->redirect(array(
'controller' => 'Userinfo',
'action' => 'gettingstarted'
));
}
} else {
if ($this->request->is('post')) {
$mobileNo = $this->request->data['User']['email'];
$mobileNo = Utility::addPlusToMobileNo($mobileNo);
$this->request->data['User']['email'] = $mobileNo;
if ($this->Auth->login() || $this->Auth->loggedIn()) {
if ($this->Session->check('Auth.User')) {
$this->_setCookie($this->Auth->user('idUser'));
$lastLogin = $this->Auth->User('lastLogin');
if ($lastLogin != null) {
$this->redirect(array(
'controller' => 'users',
'action' => 'dashboard'
));
} else {
$this->redirect(array(
'controller' => 'Userinfo',
'action' => 'gettingstarted'
));
}
}
} else {
$this->Session->setFlash('Incorrect Email/Password Combination');
}
}
}
}
protected function _setCookie($id)
{
if (!$this->request->data('User.remember_me')) {
return false;
}
$data = array(
'username' => $this->request->data('User.email'),
'password' => $this->request->data('User.password')
);
$this->Cookie->write('User', $data, true, '1 week');
return true;
}
public function logout()
{
$this->Cookie->delete('User');
$this->redirect($this->Auth->logout());
}
Looks like you're already using the SecurityComponent if you want to secure your app use it everywhere. For AJAX forms white list only the fields you need, dont disable the component!
Put App::uses('Utility', 'Utility'); on top of the file
$mobileNo = Utility::addPlusToMobileNo($mobileNo); should happen in the model beforeSave()
If this is supposed to be used world wide I assume you want translations, this is missing the translation method call __() setFlash('Incorrect Email/Password Combination');
Most of the code CAN and should go into the model layer
Are there unit tests? If not add unit tests, specially test validation of data and false data input. You want ~85%+ Code Coverage for unit tests.
You're not following the CakePHP coding standards
There is no way to tell you more than this without being able to access the whole app code and doing a code review (I could do that). For queries, always just query the data you need, check the generated SQL queries, use DebugKit to check the query times to find slow querys and slowly rendering pages.

CakePHP: Keep the same checkboxes checked after submit

How can I keep the same checkboxes checked after submit? All the other input fields on the form automatically keeps the values. I thought this would also go for checkboxes, but nope.
echo $this->Form->input('type_id', array(
'multiple' => 'checkbox',
'options' => array(
'1' => 'Til salgs',
'2' => 'Ønskes kjøpt',
'3' => 'Gis bort'
),
'div' => false,
'label' => false
));
I believe this can be done in the controller, but how?
Edit:
Since I posted this question I've changed to CakeDcs Search plugin, because I've gotten this to work with that before. Still... I can't get it to work this time.
Adding model and controller code:
AppController
public $components = array('DebugKit.Toolbar',
'Session',
'Auth' => array(
'loginAction' => '/',
'loginRedirect' => '/login',
'logoutRedirect' => '/',
'authError' => 'Du må logge inn for å vise denne siden.',
'authorize' => array('Controller'),
),
'Search.Prg'
);
public $presetVars = true; //Same as in model filterArgs(). For Search-plugin.
AdsController
public function view() {
$this->set('title_for_layout', 'Localtrade Norway');
$this->set('show_searchbar', true); //Shows searchbar div in view
$this->log($this->request->data, 'debug');
//Setting users home commune as default filter when the form is not submitted.
$default_filter = array(
'Ad.commune_id' => $this->Auth->user('User.commune_id')
);
$this->Prg->commonProcess(); //Search-plugin
$this->paginate = array(
'conditions' => array_merge($default_filter, $this->Ad->parseCriteria($this->passedArgs)), //If Ad.commune_id is empty in second array, then the first will be used.
'fields' => $this->Ad->setFields(),
'limit' => 3
);
$this->set('res', $this->paginate());
}
Model
public $actsAs = array('Search.Searchable');
public $filterArgs = array(
'search_field' => array('type' => 'query', 'method' => 'filterSearchField'),
'commune_id' => array('type' => 'value'),
'type_id' => array('type' => 'int')
);
public function filterSearchField($data) {
if (empty($data['search_field'])) {
return array();
}
$str_filter = '%' . $data['search_field'] . '%';
return array(
'OR' => array(
$this->alias . '.title LIKE' => $str_filter,
$this->alias . '.description LIKE' => $str_filter,
)
);
}
/**
* Sets the fields which will be returned by the search.
*
* #access public
* #return array Database table fields
* #author Morten Flydahl
*
*/
public function setFields() {
return array(
'Ad.id',
'Ad.title',
'Ad.description',
'Ad.price',
'Ad.modified',
'User.id',
'User.first_name',
'User.middle_name',
'User.last_name',
'User.link',
'User.picture_url',
'Commune.name',
'Type.id',
'Type.name'
);
}
You have to set manually the selected option of the input, as an array with "keys = values = intval(checkbox id)"
I cannot explain why this format, but this is the only way I get it to work.
Here is my code:
echo $this->Form->create('User');
// Read the submitted value
$selected = $this->Form->value('User.Albums');
// Formats the value
if (empty($selected)) {
$selected = array(); // avoid mess
} else {
$selected = array_map('intval', $selected);
$selected = array_combine ($selected, $selected);
}
// Renders the checkboxes
echo $this->Form->input('Albums',array(
'type' => 'select',
'multiple' => 'checkbox',
'options' => $albums, // array ( (int)id => string(label), ... )
'selected' => $selected, // array ( (int)id => (int)id, ... )
));
Hope this helps.
++

Drupal allowed_values_function does not get called when creating a field

For some reason my allowed_values_function never gets called when showing a field on a user bundle. Code:
function get_business_units()
{
$options = entity_load('business_unit', FALSE, NULL, FALSE);
$opt = bu_to_list_values($options);
return $opt;
}
function MYMODULE_enable()
{
if (!field_info_field('field_user_business_unit')) {
$field = array(
'field_name' => 'field_user_business_unit',
'type' => 'text',
'settings' => array(
'allowed_values' => array(),
'allowed_values_function' => 'get_business_units',
)
);
field_create_field($field);
// Create the instance on the bundle.
$instance = array(
'field_name' => 'field_user_business_unit',
'entity_type' => 'user',
'label' => 'Business Unit',
'bundle' => 'user',
'required' => FALSE,
'settings' => array(
'user_register_form' => 1,
),
'widget' => array(
'type' => 'options_select',
),
);
field_create_instance($instance);
}
}
The field is created, and even displayed on the users "edit" page when editing their info. But the only value is "Select" or "None". My method is never called (I even placed a debug point). This is all in MYMODULE.install file.
The problem is: 'type' => 'text'.
You have to use: 'type' => 'list_text'.
Allowed values is meaningless for a text type.
Your get_business_units() function needs to be in the MYMODULE.module file; the .install files aren't included in a normal Drupal bootstrap.
Have you tried
drush features-revert MYMODULE ?

Resources