Cakephp data does'nt save in multiple models association - model-view-controller

I am trying to save data in multiple models association but the same is not saving at all. I have all set up correctly i.e. data from form is ok (debug shows all) and find also fetches the data but couldn't understand where the problem lies. My code is follows as:
Controller:
if($url == "expense_reports") { $this->set('tab_content','Invoice - Expense Reports'); $this->render('/job/invoice2');
if($this->request->is('post'))
{//debug($this->data);
$this->Event->Invoice->Expense->save($this->data); }
}
Models (Associations):
Event
public $belongsTo = array(
'EventType' => array(
'className' => 'AgencyCalendar.EventType',
'foreignKey' => 'event_type_id'
)
);
public $hasMany = array(
'Invoice' => array(
'className' => 'AgencyCalendar.Invoice',
'foreignKey' => 'event_id',
'dependent' => false
)
);
Invoice
public $belongsTo = array(
'Event' => array(
'className' => 'AgencyCalendar.Event',
'foreignKey' => 'event_id'
)
);
public $hasMany = array(
'Expense' => array(
'className' => 'AgencyCalendar.Expense',
'foreignKey' => 'invoice_id',
'dependent' => false
)
);
Expense
public $belongsTo = array(
'Invoice' => array(
'className' => 'AgencyCalendar.Invoice',
'foreignKey' => 'invoice_id'
)
);
I am also not getting any sql dump in my view for this particular action to find out what is going on actually. Also how can I save multiple rows which would be generated from my expense view. My expense view is custom url so might be it would be a cause of not showing the sql dump or is this also a cause of not saving the data at all? Please let me know what I am doing wrong?

I believe what you are looking for is saveAll. (http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveall-array-data-null-array-options-array)
$this->Event->saveAll($this->data);
This will work as long as you have:
- the model relationships setup correctly
- the correct array attributes in $this->data

Related

How is it possible to retrieve the id of a Model right after it was created in the same controller function?

Let me show you my code, and place comments for you guys to better understand:
$homework = new Homework([ // I create Homework (And I indeed want to get the ID of the one that was just created).
'subject_id' => $request->subject_id,
'user_id' => auth()->user()->id,
'title' => $request->name,
'image' => $path,
'progress' => $request->progress,
'description' => $request->description,
'duedate' => $request->date
]);
$homework->save(); // I save it
$homeworkid = Homework::where('id', $id)->first(); // I try to retrieve it, but I'm not sure how to get it as I need to define `$id`.
$progress = newProgress([
'user_id' => auth()->user()->id,
'homework_id' => $homeworkid, // I need this for the relationship to work.
'title' => 'Initial Progress',
'description' => 'This progress is auto-generated when you create an assignment',
'username' => auth()->user()->name,
'progress' => $homeworkid->progress
]);
$progress->save(); // I save the progress
Well, as you saw, I'm trying to retrieve the ID of Homework right after it was created, but I'm not sure how to define $id in order to get it.
There is no need to instantiate a new model and saving it if your are not doing anything between instantiating and saving, you can use the create method instead:
$homework = Homework::create([
'subject_id' => $request->subject_id,
'user_id' => auth()->user()->id,
'title' => $request->name,
'image' => $path,
'progress' => $request->progress,
'description' => $request->description,
'duedate' => $request->date
]);
$homework->id; // get the id
After saving / creating the model you can access the id like you normally would:
$homework->id
What you then could do is setup the relationships between your models so you can do the following after creating a new homework:
$homework->newProgress()->create([
'user_id' => auth()->user()->id,
'title' => 'Initial Progress',
'description' => 'This progress is auto-generated when you create an assignment',
'username' => auth()->user()->name,
'progress' => $homework->progress
]);
This way you don't have to pass the homework id when creating a new newProgress, laravel will pass it automatically for you.
This is very simple for you. No need to complex it.
$homework->save(); // I save it
After this line just use only
$progress = newProgress([
'user_id' => auth()->user()->id,
'homework_id' => $homework->id, // I need this for the relationship to work.
'title' => 'Initial Progress',
'description' => 'This progress is auto-generated when you create an assignment',
'username' => auth()->user()->name,
'progress' => $homework->progress
]);
You don't no need this line of code
$homeworkid = Homework::where('id', $id)->first(); // I try to retrieve it, but I'm not sure how to get it as I need to define `$id`.
$data = $homework->save();
Get the ID this way: $data->id

CakePHP - paginate and sort hasMany association

I have three tables:
Book -> belongTo -> Document ,Document -> hasOne -> Book, Document -> hasMany -> Language , Language -> belongTo -> Document
Document.php
public $hasOne = array(
'Book' => array(
'className' => 'Book',
'foreignKey' => 'document_id',
'dependent'=>true,
)
public $hasMany = array(
'Language' => array(
'className' => 'Language',
'foreignKey' => 'document_id'
)
Book.php
public $belongsTo = array(
'Document' => array(
'className' => 'Document',
'foreignKey' => 'document_id'
)
);
Language.php
public $belongsTo = array(
'Document' => array(
'className' => 'Document',
'foreignKey' => 'document_id'
)
);
BooksController.php
$this->Book->bindModel(array(
'hasOne' => array(
'Language' => array(
'foreignKey' => false,
'conditions' => array('Document.id = Language.document_id')
));
$this->Prg->commonProcess();
$this->Paginator->settings = [
'conditions' => $this->Book->parseCriteria($this->Prg->parsedParams()),
'contain' => array('Document','Language')
];
$this->set('books', $this->Paginator->paginate());
index.php
<th><?php echo $this->Paginator->sort('Document.Language.type',__('language')); ?></th>
I just can't sort data by language type!
Can anyone suggest a fix for this problem?
You can use the virtual field feature in order to sort by language type.
First, add this virtual field to your Document model:
public $virtualFields = ['Min_LangType' => 'SELECT MIN(type) FROM languages as Language WHERE Language.document_id = Document.id'];
Then, sort by language type in this way:
$this->Paginator->sort('Document.Min_LangType',__('language'));

add validation rule checking conditions

I have defined a validation rule like
protected $add_rules = array(
'add_question' => array(
'field' => 'add_question',
'label' => 'lang:topic.add_question_error',
'rules' => 'trim|required'
)
);
I have to add extra rules in this class if user is not logged on like
if(!isset($this->current_user->id)){
'username' => array(
'field' => 'username',
'label' => 'lang:topic.username',
'rules' => 'trim|required'
)
}
How can i add this second rule within the first protected class?
If you want to add it to the $add_rules array you need to do
if(!isset($this->current_user->id)) {
$this->add_rules['username'] = array(
'field' => 'username',
'label' => 'lang:topic.username',
'rules' => 'trim|required'
);
}
Because it is a protected property you will only be able to manipulate it in the same class or any class that extends it

how can i set validation for multi select list in cakephp

I have a form with multi select box:
echo $this->Form->input('emp_id', array( 'options' => array( $arr),
'empty' => '(choose one)',
'div'=>'formfield',
'error' => array( 'wrap' => 'div',
'class' => 'formerror'
),
'label' => 'Team Members',
'type' => 'select', 'multiple' => true,
'style' => 'width:210px; height:125px;'
));
I selected multiple values from this list box and click the SAVE button.
But it displays the validation message.
How can i solve this?
class TravancoDSRGroup extends AppModel {
var $name = 'TravancoDSRGroup';
var $useTable = 'dsr_group'; // This model uses a database table 'exmp'
var $validate = array(
'emp_id' => array(
'rule' => 'notEmpty',
'message' => 'The employee field is required'
)
);
}
This is the model code....
If it is possible...?
You don't have to explicitly specify
'type' => 'select'
if you set 'emps' from the controller, it will allow cake's automagic to work. just add
$this->set(compact('emps'));
Post output of debug($this->request->data) for better understanding of problem.
Have you defined hasMany or HABTM relationships to the emp ? To have multiple values saved you will have to define hasMany or HABTM relations, if you wish to save it as CSV then you will have to do the processing yourself in 'beforeSave'.

CakePHP 2.1 - Custom Validation Rule - Check for Unique Field Value Combination

I have a couple of columns (ip, provider_id) for which I want combinations of values to always be unique. Therefore, I am trying to build a custom validation function. But I am having issues grabbing on the value of the secondary field. This is my code so far in the model:
public $validate = array(
'ip' => array(
'rule' => array('uniqueClick', 'provider_id'),
'message' => 'The click is not unique.'
)
);
public function uniqueClick ($ip, $field) {
$count = $this->find('count', array('conditions' => array('ip' => $ip, 'provider_id' => $field)));
// echo $field;
return $count == 0;
}
So the problem is that when I am testing what value is loaded into $field, it's just 'provider_id', a string. I was hoping it would contain the value of the 'provider_id' field. Does anyone know how to grab that value (and all other secondary model field values if necessary) and send it to the custom validation function?
My reading in the CookBook and people who've discussed similar problems seemed to suggest this solution would work, but not for me unfortunately.
Thanks in advance!
Cake is definitely behaving the way it's supposed to there. The second paramameter that you pass in that 'rule' array is meant to be passed as a static value.
However, your provider_id should be available in $this->data['MyModel']['provider_id']
So you should be able to forget about that second parameter completely, and do:
public function uniqueClick ($ip) {
$count = $this->find('count', array(
'conditions' => array(
'ip' => $ip,
'provider_id' => $this->data[$this->alias]['provider_id'])
));
return $count == 0;
}
Hope that helps!
To complement Joshua's answer, the validation array should be build like this:
// Validation rules
public $validate = array(
'ip' => array(
'rule' => array('uniqueClick', 'ip'),
'message' => 'The click is not unique.'
)
);
/**
* Checks if there are records on the datasource with the same ip and same provider_id
*
*/
public function uniqueClick ($ip) {
$count = $this->find('count', array(
'conditions' => array(
'ip' => $ip,
'provider_id' => $this->data[$this->alias]['provider_id'])
));
return $count == 0;
}
you can also use my rule with is able to work with as many fields as you need
try http://www.dereuromark.de/2011/10/07/maximum-power-for-your-validation-rules/
and
https://github.com/dereuromark/tools/blob/master/Model/MyModel.php#L930
so basically the same than you tried:
'ip' => array(
'validateUnique' => array(
'rule' => array('validateUnique', array('provider_id')),
'message' => 'You already have an entry',
),
),
You can directly go with this solution without passing anything in validation rules except the custom unique function.
// Validation rules
public $validate = array(
'ip' => array(
'rule' => array('uniqueClick'),
'message' => 'The click is not unique.'
)
);
/**
* Checks if there are records on the datasource with the same ip and same provider_id
*
*/
public function uniqueClick ($ip) {
$count = $this->find('count', array(
'conditions' => array(
'ip' => $ip,
'provider_id' => $this->data[$this->alias]['provider_id'])
));
return $count == 0;
}
$this->data[$this->alias]['provider_id'] automatically gets the value of the provider_id.

Resources