cakephp 3 form validation for associated model data - validation

I need help with validation of associated model data. I have a form with User data (UsersTable) with additional fields from Model Companies (Users hasMany Companies).
My form view look like this:
echo $this->Form->create($contentData);
echo $this->Form->control('User.person_name');
echo $this->Form->control('User.email');
echo $this->Form->control('User.phone');
echo $this->Form->control('Companies.0.company_name');
//I try Companies.company_name too
echo $this->Form->control('Companies.0.nip');
Action in controller look like this:
$userTable = TableRegistry::get('Users');
$contentData = $userTable->newEntity(null, ['associated' => ['Companies']]);
if ($this->request->is(['post', 'put'])) {
$formData = $this->request->getData();
$contentData = $userTable->newEntity($this->request->getData(),
['validate' => true, 'associated' => ['Companies']]);
pr($contentData->getErrors());
die();
}
Unfortunately debug return error from UsersTable validation, except CompaniesTable.
Could U any idea, where did i go wrong ?

For the main model (User), you shouldn't need the model name at all in the form. For associated models, the convention is lower case plural.
echo $this->Form->control('person_name');
echo $this->Form->control('email');
echo $this->Form->control('phone');
echo $this->Form->control('companies.0.company_name');
echo $this->Form->control('companies.0.nip');
Unrelated notes: you initialize $formData but never use it, you shouldn't need to pass any parameters to the first newEntity call, and typical usage is to use patchEntity instead of newEntity inside the if.

Related

Can be used exist validator with a DynamicModel in Yii2

I need validate a user input against a database, if the input exist, the field should be validate. I have created a Dynamic Model in this way:
$modelDynamic=new DynamicModel(['TIN','Business_Code']);
and added the next exist rule validator:
$modelDynamic->addRule('TIN','exist',[
'targetClass'=>'frontend\modules\profiles\models\PorfBusiness',
'targetAttribute'=>'TIN',
'skipOnEmpty'=>true
])->validate();
all of them in my controller ProfPersonController.
And create this form in a view called profile:
if (isset($modelDynamic)) {
$formDynamic = ActiveForm::begin([
'type'=>ActiveForm::TYPE_HORIZONTAL,
'formConfig'=>[],
]);
echo $formDynamic->errorSummary($modelDynamic);
echo $formDynamic->field($modelDynamic,'TIN')
->textInput()
->label(Yii::t('app','TIN'));
echo $formDynamic->field($modelDynamic,'Business_Code')
->textInput()
->label(Yii::t('app','Business Code'));
echo HTML::submitButton('Submit');
ActiveForm::end();
}
(Imge with a wrong code)
The validation makes nothing, nor if the input is correct, nor if is incorrect. No errorSummary is sended neither.
Any error? Any idea? Thanks in advance.
Change Your Controller Code as
$modelDynamic= new DynamicModel(['TIN','Business_Code']);
$modelDynamic->addRule('TIN','exist',[
'targetClass'=>'frontend\modules\profiles\models\PorfBusiness',
'targetAttribute'=>'TIN',
'skipOnEmpty' => true
]);
if($modelDynamic->load(Yii::$app->request->post())&& $modelDynamic->validate()){
//Model is Validated and ready to go throgh
}
You must validate() your model after load() of your DynamicModel

"Node no longer exists" Yii

I want to keep the data between 2 actions in Yii by session. i'm writing the data in one action
Yii::app()->session['resultsData'] = $data;
and try to get it in next action
$this->resultsData = Yii::app()->session['resultsData'];
but when i want print_r this data in view...
<? print_r($this->resultsData); ?>
i'm get
PHP warning
print_r() [<a href='function.print-r'>function.print-r</a>]: Node no longer exists
actually, any manipulate with this data array, like serialize or json_encode, returns this error. can it be because of corrupted data? thank you.
Yii::app()->session['resultsData'];No need to use $this in action just assign the variable as shown
Yii::app()->session['resultsData'] = $data;
resultsData =Yii::app()->session['resultsData'];
and access it in another action as
echo Yii::app()->session['resultsData'] ;
If U want to acces the resultData in another u need to pass that variable to that action as shown
$this->redirect(array('actionname','resultData'=>$resultData));
And in your actionname echo it or print_r and check
Send it to view as shown
$this->render('ViewName',array('resultData'=>resultData));
From view to action use this
Yii::app()->createAbsoluteUrl('ControllerName/actionName',array('data'->$data));
Maybe this helps you:
$model = new CompanyForm('step1');
if (is_array(Yii::app()->session['step1']))
$model->attributes = Yii::app()->session['step1'];
if (!is_array(Yii::app()->session['step1']))
$this->redirect(array('createStep1'));
$this->render('create', array(
'model' => $model,
'step' => 'step1'
));
maybe you are saving the data in the wrong place;
maybe you have a post or get action;
and also, print_r the $data and see wat you get before saving the data in session

Custom Magento Module

So im creating a module in the backend, I have a shell module created (items in admin top menu and a page to visit.) basically I want to have an input field that the admin can type a number into then click a button "add", this will insert a row into an existing table in the database.
$connection = Mage::getSingleton('core/resource')->getConnection('core_write');
$connection->beginTransaction();
$fields = array();
$fields['name']= 'andy';
$connection->insert('test', $fields);
$connection->commit();
I have a table called "test" within my database. If I put the above code into my Controller file, it successfully adds a row to the database when i visit the admin page. But i need to allow the user to input the data that is inserted.
Would I have to move that code into the Model and somehow send the input data to the Model and let that do the work? or not. If this is correct could someone point me to a good place to research sending data to models? (if thats even possible)
iv tried lots of tutorials but they are all way to big for what I need, I dont need to display anything, I just need to have an input box and a save button.
EDIT
i have created a file block/Adminhtml/Form/Edit/Form.php which contains the following . . .
class AndyBram_Presbo_Block_Adminhtml_Form_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
$form = new Varien_Data_Form(
array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/test'),
'method' => 'post',
)
);
$form->setUseContainer(true);
$this->setForm($form);
$fieldset = $form->addFieldset('display', array(
'legend' => 'Display Settings',
'class' => 'fieldset-wide'
));
$fieldset->addField('label', 'text', array(
'name' => 'label',
'label' => 'Label',
));
if (Mage::registry('andybram_presbo')) {
$form->setValues(Mage::registry('andybram_presbo')->getData());
}
return parent::_prepareForm();
}
}
then in my controller i have 2 functions like below . . .
public function indexAction()
{
$this->loadLayout();
$this->_addContent($this->getLayout()->createBlock('presbo/adminhtml_form_edit_form'));
}
public function testAction()
{
echo 'form data here';
$this->loadLayout();
$this->renderLayout();
}
the form is displayed successfully but there is no button to send or say 'do an action'
Further Edit
i have successfully added a submit button to the form that successfully goes to the testAction and echo' "form data here".
how do i then access the data,
iv added the below line
$postData = $this->getRequest()->getPost();
now if i echo $postData, it just puts "array"
if i echo $postData[0] it doesnt put anything just a blank page
any ideas or pointers?
Magento is built as an MVC framework, thus you're right - you need to pass data from controller to the model, and do not do any DB updates directly in a controller's code. The best source for an example is the own Magento code - you can take any controller action, which saves data to DB to see, how it is done. E.g. check app/code/core/Mage/Adminhtml/controllers/NotificationController.php method markAsReadAction().
There you can see, that:
Data is retrieved from the request by calling
$this->getRequest()->getParam('id') - actually this is the answer
to the question, how to get the submitted data
Data is set to model, and then saved to the DB via call to the
$model->setIsRead(1)->save()
It is strongly encouraged to follow the same approach of working with models. This makes codes much better and easier to support.
Note, that "M" letter of "MVC" architecture in Magento is represented by two layers: Models and Resource Models.
Models:
Contain business logic of an entity. E.g. adding ten items to a
Shopping Cart model triggers a discount rule
Represented by classes with a general name of <Your_Module>_Model_<Model_Name>
If need to work with DB, then extend Mage_Core_Model_Abstract and have a Resource
Model, which is responsible for DB communication
Do not need to have basic save/load methods to be implemented, as the ancestor
Mage_Core_Model_Abstract already has all that routines ready to use
Created via call to Mage::getModel('<your_module>/<model_name>')
Resource Models:
Serve as DB abstraction layer, thus save/load data from DB, perform
other DB queries
Extend Mage_Core_Model_Resource_Db_Abstract in order to communicate with DB
Represented by classes with a general name of
<Your_Module>_Model_Resource_<Model_Name>
Automatically created by a corresponding model, when it needs to communicate with DB
So, in a controller you care about creating Models only. Resource Models are created by a Model automatically.
And, according to everything said above, your controller should look like:
public function testAction()
{
$model = Mage::getModel('your_module/your_model');
$model->setName('andy');
$model->save();
}
You can download a fully working example of the thing you need here.
There can be several variations to the code provided, depending on your specific case. But it represents a general approach to implementing the thing you want.

CakePHP validation not working for contact form

I am trying to do some very simple validation in my CakePHP contact form, but validation does not work eventhough I think I did everything necessary. Here's what I did:
I made a model like this:
class Office extends AppModel
{
var $name = 'Office';
var $useTable = false;
public $validate = array('onderwerp' => 'notEmpty');
}
(I also tried many other values for $validate from the CakePHP online manual)
In Config/bootstrap.php I made this rule for not letting CakePHP expect plural "Offices":
Inflector::rules('plural', array('rules' => array(),
'irregular' => array(),
'uninflected' => array('office')));
In OfficeController, I do this in my method contact():
$this->Office->set($this->request->data);
if($this->Office->validates()){
echo "code validates";
} else {
print_r($this->Office->validationErrors);
}
And in my Office/contact.ctp view, I have (amongst other code like starting and ending the form) this code:
$this->Form->input('onderwerp', array('label'=>false, 'size' => 60));
Now, even when I fill in the form, leaving empty the field 'onderwerp', it executes the code that should be executed when the code is executed.
When I print_r($this->request->data) or print_r($this->Office) I see that my onderwerp field is there and that it is empty (or filled when I do fill in something).
Now, when I add a public function validates() in my model and echo something there, it IS being displayed. So I'd say CakePHP knows where to find my model, and does execute my controller code. I also tried adding return parent::validates(); in my validates() function, but this also yielded no validation error, or any other error for that matter. My debug level is set to 2.
I guess I'm missing a needle in this haystack. Thanks for helping me finding it!
so drop all the inflector stuff.
and use the right model in your Form->create()
either
$this->Form->create(null)
or
$this->Form->create('Office');
and if you follow my advice to use a table less model with schema you will also have more power over input creation and validation.

A little confused about MVC and where to put a database query

OK, so my Joomla app is in MVC format. I am still a little confused about where to put certain operations, in the Controller or in the Model. This function below is in the controller, it gets called when &task=remove. Should the database stuff be in the Model? It does not seem to fit there because I have two models editapp (display a single application) and allapps (display all the applications), now which one would I put the delete operation in?
/**
* Delete an application
*/
function remove() {
global $mainframe;
$cid = JRequest::getVar( 'cid', array(), '', 'array' );
$db =& JFactory::getDBO();
//if there are items to delete
if(count($cid)){
$cids = implode( ',', $cid );
$query = "DELETE FROM #__myapp_apps WHERE id IN ( $cids )";
$db->setQuery( $query );
if (!$db->query()){
echo "<script> alert('".$db->getErrorMsg()."');window.history.go(-1); </script>\n";
}
}
$mainframe->redirect( 'index.php?option=' . $option . '&c=apps');
}
I am also confused about how the flow works. For example, there is a display() function in the controller that gets called by default. If I pass a task, does the display() function still run or does it go directly to the function name passed by $task?
I would try to keep all database functionality in your model. If you don't know which model a method should go in, it's possible that you need to change your models to better reflect your problem.
In your case, though, I think this method would go in allapps since it can handle operations on multiple apps.
If you pass in a task, that method will be called. If you want to then call the display method, just call it at the end of your edit method.
When in doubt, take a look at the weblinks component's models and controllers. They are very simple and a good example of how to do MVC in Joomla!.

Resources