How to save data POSTed from From into database not using Form->setModel() - atk4

I know that's kinda simple and lame question, but still.
I have a Form which should not show all Model fields, but only some of them. That's why I can't use Form->setModel($m), because that'll automatically add all fields into Form.
So I add Model into page, then add form into page and then use form->importFields like this:
$m = $p->add('Model_Example');
$f = $p->add('Form');
//$f->setModel($m); // can't use this because that'll import all model fields
$f->importFields($m,array('id','description'));
$f->addSubmit('Save');
What I don't understand in this situation is - how to save this data in database, because $f->update() in onSubmit event will not work. Basically nothing I tried will work because Form have no associated Model (with setModel).

How about this way?
$your_form->setModel($model,array('name','email','age'));

I have solution for mixed form. Add custom form fields in form init and manipulate with them by hooks ('afterLoad','beforeSave')
In this case you can use setModel() method
$form->setModel('Some_Model',array('title','description'));
class Form_AddTask extends Form {
function init(){
parent::init();
$this->r=$this->addField('autocomplete/basic','contact');
$this->r->setModel('ContactEntity_My');
}
function setModel($model,$actual_fields=undefined){
parent::setModel($model,$actual_fields);
$this->model->addHook('afterLoad',array($this,'setContactId'));
$this->model->addHook('beforeSave',array($this,'setContactEntityId'));
return $this->model;
}
// set saved value for editing
function setContactId() {
$this->r->set($this->model->get('contact_entity_id'));
}
function setContactEntityId() {
$this->model->set('contact_entity_id',$this->get('contact'));
}
}
There is a hook 'validate' as well in Form_Basic::submitted(), so you can add
$this->addHook('validate',array($this,'validateCustomData'));
and validate your data in Form::validateCustomData()

Why not set the fields to hidden in the model?
I.e.:
class Model_Example extends Model_Table {
public $table='assessment';
function init() {
parent::init();
$grant->addField('hidden_field')->hidden(true);
}
}
And then:
$m = $p->add('Model_Example');
$f = $p->add('Form');
$f->setModel($m);

Related

callback functions for cakephp elements?

This might be a naive question since I am new to cakephp.
I am working on a project where there are many layouts, helpers and elements. Because this is a mutli-language site, I am intercepting the final rendered output to do some language conversion(so each visitor only sees his native language on the site including user input).
I've managed to convert most of the layouts and helpers by adding code in two places: AppController's afterFilter() and AppHeler's afterRender() function. But I can't figure out a centralized way to handle the elements and there are dozens of them.
So here are my questions: do all elements in cakephp have a common ancestor class? If so, does this ancestor class have callback functions like afterRender()?
Many thanks!
I'm not sure such a callback exists specific for 'elements', but looking at the source code, View::element() renders an element using the same _render() method as the View itself, and should trigger beforeRender() and afterRender()
Creating a custom View Class and Custom Callbacks
You may use a custom 'View' class and override the element() method, for example to have your own 'custom' callbacks being triggered in helpers
Something like this;
app/view/app_view.php
class AppViewView extends View {
/**
* custom 'element()' method, triggers custom
* before/aferRenderElement callbacks on all loaded helpers
*/
public function element($name, $params = array(), $loadHelpers = false)
{
$this->_triggerHelpers('beforeRenderElement');
$output = parent::element($name, $params, $loadHelpers);
$this->_triggerHelpers('afterRenderElement');
}
/**
* Names of custom callbacks
*/
protected $_customCallBacks = array(
'beforeRenderElement',
'afterRenderElement',
);
function _triggerHelpers($callback)
{
if (!in_array($callback, $this->_customCallbacks)) {
// it's a standard callback, let the parent class handle it
return parent::_triggerHelpers($callback);
}
if (empty($this->loaded)) {
return false;
}
$helpers = array_keys($this->loaded);
foreach ($helpers as $helperName) {
$helper =& $this->loaded[$helperName];
if (is_object($helper)) {
if (
is_subclass_of($helper, 'Helper')
&& method_exists($helper, $callback)
) {
$helper->{$callback}();
}
}
}
}
}
Then, in your AppController specify the 'view' class to use;
class AppController extends Controller {
public $view = 'AppView';
}

Laravel one-to-many relationship returns null

So here's what i have set up. I have two tables; users and todos. Every user can have multiple "todos".
Here's what the tables look like:
Users:
Todos:
And the models:
class User extends Eloquent
{
public function todo() {
$this->has_many('todo');
}
}
And...
class Todo extends Eloquent
{
public function user() {
$this->belongs_to('user');
}
}
Note that i already have a "todo" attached to the user in the database. So, with that said, should i not be able to do the following:
$user = User::find(1)->todo;
To get the todo's for that user? I'm currently getting Null when dd()-ing it:
array(1) {
["todo"]=>
NULL
}
So, any ideas? I tried removing belongs_to() from the Todo's model, because it shouldn't be needed right? Either way it makes no difference. Am i missing something?
You need to return the relation objects, e.g.
class User extends Eloquent
{
public function todos() {
return $this->has_many('Todo');
}
}
Also note that relations that return an array (e.g. has_many, has_many_and_belongs_to) are typically named plural, so 'todos' versus 'todo.

Adding fields on the fly

I have a form with a table source, the form has a few fields (product, quantity)
I'm thinking to add a button that allows me to add another "line" with product, quantity.... and so on, because I don't know how many items I need to add.
Which is the best approach ?
maybe removing the StaticSource('') and implementing on the submit the inserts ?
Thanks
Alejandro
class page_yourpage extends Page {
function init(){
parent::init();
$this->add("CRUD")->setModel("Product");
}
}
class Model_Product extends Model_Table {
$entity_code = "yourtable";
function init(){
parent::init();
$this->addField("product_id")->refModel("Model_Product");
$this->addField("quantity");
}
}
that's it. (did not test in browser);

Why can't add js() to a dropdown field on a form?

I just keep getting this error:
Method js is not defined neither in controller, nor in its Model.
Thi is my page
class page_alumnos_inscribir extends Page {
function init(){
parent::init();
$page=$this;
$model=$this->add('Model_Alumno')->loadData($_GET['id']);
$h=$this->add('H3')->set($model->get('name').' ( '.$model->get('grado').$model->get('nivel'). ' )');
$f=$page->add('Form');
$r=$f->addField('dropdown','Inscribir al Curso')->setModel('Curso');
$r->js('change')->univ()->alert('orale');
$s=$f->addField('line','montoPeriodo');
}
}
You wrote a wrong chain. Set model returns the added model, you need the created field instead. Try to do it in this way:
$r=$f->addField('dropdown','Inscribir al Curso');
$r->setModel('Curso');
$r->js('change')->univ()->alert('orale');

Zend Framework: Populating DB data to a Zend Form dropdown element

I have the following form:
<?php
class Application_Form_RegistrationForm extends Zend_Form{
public function init(){
$country = $this->createElement('select', 'country');
$country->setLabel('country: ')
->setRequired(true);
$email = $this->createElement('text', 'email_address');
$email->setLabel('Email Address: ')
->setRequired(true);
$register = $this->createElement('submit', 'register');
$register->setLabel('Create new Account')
->setIgnore(true);
$this->addElements(array(
$country, $email, $register
));
}
}
?>
The list of the countries are present in a table country in a database.
Is there anyway I can populate the country dropdown list with the country names from the database?
Any help is appreciated.
Thanks
You sure can.
In the init method you can set the options with something like this, assuming $db is a Zend_Db adapter:
$options = $db->fetchPairs('SELECT id, name FROM country ORDER BY name ASC');
$country->setMultiOptions($options);
In case you haven't seen the fetchPairs method, it builds an array, where the first column return becomes the key, and the second column the value.
You could do it from controller's action (or even in Service Layer, if to be meticulous), if your list's content depends from some conditions.
Usage:
$form->getElement('country')->addMultiOption('1','USA'); //add single value
$form->getElement('country')->addMultiOptions(array('1'=>'USA', '2'=>'Canada')); //add values by array
$form->getElement('country')->setMultiOptions(array('1'=>'USA', '2'=>'Canada')); //set values by array
Of course, to add values from DB you need to fetch them first.
See http://framework.zend.com/manual/en/zend.form.standardElements.html#zend.form.standardElements.select for more methods available.
The best way is to create a new class for the element:
Put this in "/application/form/element/CountySelect.php"
class Application_Form_Element_CountrySelect extends Zend_Form_Element_Select {
public function init() {
$oCountryTb = new Application_Model_Country();
$this->addMultiOption(0, 'Please select...');
foreach ($oCountry->fetchAll() as $oCountry) {
$this->addMultiOption($oCountry['id'], $oCountry['name']);
}
}
}
And then add it to the form this way:
class Application_Form_RegistrationForm extends Zend_Form{
public function init() {
$this->addElement(new Application_Form_Element_CountrySelect('country_id'));
}
}

Resources