How can I add an item and insert it into 2 tables?
So I have a 'Type' table and 'SpecificType' table.
Type has fields 'id' and some other common fields.
SpecificType has fields 'id', 'type_id' and some other uncommon fields.
When I go to /specific_types/add and I submit, ideally I want to first add that to 'Type' then add it to 'SpecificType'.
This is what I have now.
In SpecificType Model
var $belongsTo = array(
'Type' => array(
'className' => 'Type',
'foreignKey' => 'type_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
In SpecificType Controller
var $uses = ('Type', 'SpecificType');
function add() {
if (!empty($this->data)) {
$this->Type->create();
if ($this->Type->save($this->data)) {
$this->SpecificType->create();
if ($this->SpecificType->save($this->data)) {
$this->Session->setFlash(__('The SpecificType has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The SpecificType could not be saved. Please, try again.', true));
}
} else {
$this->Session->setFlash(__('The Type could not be saved. Please, try again.', true));
}
}
}
In SpecificType add.ctp
echo $form->input('Type.data1');
echo $form->input('title');
So right now, it saves Type.data1 but title isn't getting saved.
What am I missing?
Thanks,
Tee
Additional Info:
The 2nd model isn't saving only when I turn on MeioUpload.
Make sure your view is setup to create a form for SpecificType:
<?php echo $this->Form->create('SpecificType', array('action' => 'add')); ?>
<?php echo $this->Form->input('data1'); ?>
<?php echo $this->Form->input('title'); ?>
<?php echo $this->Form->end(); ?>
This will put all of your form data into: $this->data['SpecificType']
Right before your code:
$this->Type->create();
You need to do this:
$this->data['Type'] = $this->date['SpecificType'];
Then process the save. As long as the view is setup correctly for the SpecificType controller, all of the data from the form will be stored in $this->data['SpecificType']. If you pr($this->data) and there is data you need to save outside of $this->data['SpecificType'], review and fix the view.
Side note: Your design sounds awfully sketchy. You should never need to save the data in two locations. I would recommend revisiting the design of your app. There is something fundamentally wrong with it if you need to save the same data into two tables.
Just copy the data over to a SpecificType index in the data array and use saveAll(). The models are related so Cake will automatically link them via the type_id. We're working off the Type alias, so make sure you also have var $hasMany = array('SpecificType'); in your Type model.
function add() {
if (!empty($this->data)) {
$this->Type->create();
$this->data['SpecificType'] = $this->data;
if ($this->Type->saveAll($this->data)) {
$this->Session->setFlash(__('The SpecificType has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The SpecificType could not be saved. Please, try again.', true));
}
} else {
$this->Session->setFlash(__('The Type could not be saved. Please, try again.', true));
}
}
The code seems to be fine, use saveAll instead of save
Related
i want to create an simple application that will allow graduating students to register for graduation attendance. From the application form the student enter the details that's saved to the students table waiting for approval. The admin then approves the request and the record is inserted in the approved table and deleted from the students table. How can i write the approve action and how can i move the record to the approved table in cakephp 2.6.3.
thanks in advance
I would use one and same table to save this data. Use the table students. Add a approved column to the table where 0 = not approved, 1 = approved. When students are entering their data and saves it to students table, make sure approved = 0. Then admin can go change this value to 1 if student is approved.
// StudentsController.php
public function approve($id = null) {
if (!$this->Student->exists($id)) {
throw new NotFoundException(__('Invalid'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->Student->save($this->request->data)) {
$this->Session->setFlash(__('The student has been saved.'), 'default', array('class' => 'notice success'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The student could not be saved. Please, try again.'), 'default', array('class' => 'notice error'));
}
} else {
$options = array('conditions' => array('Student.' . $this->Student->primaryKey => $id));
$this->request->data = $this->Student->find('first', $options);
}
}
app/View/Students/approve.ctp:
<h1><?php echo __('Approve student');?></h1>
<?php echo $this->Form->create('Student'); ?>
<?php
echo $this->Form->input('id');
echo $this->Form->input('approved', array('label' => __('Approve'), 'options' => array(
'0' => __('Not approved'),
'1' => __('Approved'),
)));
?>
<?php echo $this->Form->end(array('label' => __('Save'), 'class' => 'button')); ?>
Sorry for not answering your exact question, but I really think it is unnecessary to use two tables to identify who are not approved vs approved students.
I've searched high and low for a solution but can't seem to get this figured out. What I'm trying to do is upon adding a product, I want the name field to be populated from the inputs in the form. So the name would include the values the user selects for type_id,category_id and subcategory_id. Does anyone know of a way to accomplish this?
Add product View page
<fieldset>
<legend><?php echo __('Add Product'); ?></legend>
<?php
echo $this->Form->input('type_id');
echo $this->Form->input('category_id', array('label' => 'Vendor'));
echo $this->Form->input('subcategory_id', array('label' => 'Model'));
echo $this->Form->input('location', array('label' => 'Location'));
echo $this->Form->input('sku', array('label' => 'Asset Tag'));
echo $this->Form->input('mac');
echo $this->Form->input('description', array('label' => 'Notes'));
echo $this->Form->input('name', array( 'value' => ['type_id']['category_id'] , 'type' => 'hidden'));
//echo $this->Form->input('cost');
// echo $this->Form->input('Tag');
?>
</fieldset>
Product controller add function
public function add() {
if ($this->request->is('post')) {
$this->Product->create();
if ($this->Product->save($this->request->data)) {
$this->Session->setFlash(__('The product has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The product could not be saved. Please, try again.'));
}
}
$subcategories = $this->Product->Subcategory->find('list',array('order'=>'Subcategory.name asc'));
$categories = $this->Product->Category->find('list',array('order'=>'Category.name asc'));
$types = $this->Product->Type->find('list',array('order'=>'Type.name asc'));
$this->set(compact('subcategories', 'categories', 'types'));
}
In order to do it the way you are trying to do it, you would have to use client-side javascript to update the input value "on-the-fly", but that's not very safe and can easily be messed with. It would make much more sense to drop the name input altogether and just handle this in the beforeSave method of your Product model (or alternatively by defining the name value in your Controller just before saving).
public function beforeSave($options = array()) {
// Generate the name based on type and category
$this->data['Product']['name'] = $this->data['Product']['type_id'] .
$this->data['Product']['category_id'];
return true;
}
Update based on your comment.
In order to get the names, just find those names (assuming your models are associated) and define those:
public function beforeSave($options = array()) {
// Get the type name
$type = $this->Type->field('name', array(
// Set the condition for the field
'Type.id' => $this->data['Product']['type_id']
));
// Get the category name
$category = $this->Category->field('name', array(
// Set the condition for the field
'Category.id' => $this->data['Product']['category_id']
));
// Generate the name based on type and category
$this->data['Product']['name'] = $type . $category;
return true;
}
I'm pretty new to cakePHP and I've been stuck on this problem for a few days now. My Products index view displays a list of products we have in inventory and includes a "Checkout" action with every product that points to the Checkout/add view. The problem is the product_id from the product that needs to be checked out does not get passed to the add checkout page and I can't figure out how to make this happen. If anyone has any suggestions I could really use some help.
Here is my CheckoutController add action:
public function add() {
if ($this->request->is('post')) {
$this->Checkout->create();
if ($this->Checkout->save($this->request->data)) {
$this->Session->setFlash(__('The checkout has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The checkout could not be saved. Please, try again.'));
}
}
$products = $this->Checkout->Product->find('list');
$users = $this->Checkout->User->find('list');
$this->set(compact('products', 'users'));
}
Checkout Add View
<?php echo $this->Form->create('Checkout');?>
<fieldset>
<legend><?php echo __('Add Checkout'); ?></legend>
<?php
echo $this->Form->input('product_id');
echo $this->Form->input('start_time');
echo $this->Form->input('end_time');
echo $this->Form->input('user_id');
echo $this->Form->input('description');
?>
</fieldset>
Link from the Products index page
<?php echo $this->Html->link(__('Checkout'), array('controller' => 'Checkouts','action' => 'add', $product['Product']['id'])); ?>
Cake will pass the product_id as the first argument of your action; Default Cake 'Routes' will match this url;
/mycontroller/myaction/param1/param2/param3
To this action:
MycontrollerController::myaction(param1, param2, param3)
You can pass this value to the form by adding an argument to the add() action and adding it to the 'request' if the form is not posted. Like this;
public function add($productId = null) {
if ($this->request->is('post')) {
$this->Checkout->create();
if ($this->Checkout->save($this->request->data)) {
$this->Session->setFlash(__('The checkout has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The checkout could not be saved. Please, try again.'));
}
} else {
$this->request->data['Checkout']['product_id'] = $productId;
}
$products = $this->Checkout->Product->find('list');
$users = $this->Checkout->User->find('list');
$this->set(compact('products', 'users'));
}
This will automatically propagate the 'value' of the product_id drop down
from your links on the products index page it seems that
public function add()
should read
public function add($product_id)
furthermore you should set the $product_id into the view, and also
fill it into the inputbox echo $this->Form->input('product_id', array('value'=>$product_id));
I have two models Business and User. They are related by a HABTM relationship.
Everything is working with the baked controllers, models and views.
Now I'm trying to combine the two models in one form so the user can enter a business name with is user info.
Here's the form :
Form->create('User'); ?>
Form->input('Business.name', array('label' => __('Business name')));
echo $this->Form->input('User.email');
echo $this->Form->input('User.firstname');
echo $this->Form->input('User.lastname');
echo $this->Form->input('User.password');
echo $this->Form->input('User.phone_cell', array('type' => 'text'));
echo $this->Form->input('User.phone_home', array('type' => 'text'));
echo $this->Form->input('User.phone_work', array('type' => 'text'));
?>
Form->end(__('Submit')); ?>
The only way I was able to make it work was to save the User first and then get the user id and save the business after by adding the user array with the new id.
if ($this->User->save($this->request->data)) {
$this->request->data['User'] = array('User' => array(0 => $this->User->id));
if ($this->User->Business->save($this->request->data)) {
// User saved
} else {
// User not saved
}
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
}
I tried the saveAll method without success. Is is possible to optimize this the CakePHP way for a single save ?
Thanks
I was able to get it to work myself with a couple models named User and Group. Here's some snips from my code to show how I did it:
UsersController.php
public function edit($id = null)
{
$this->User->id = $id;
if ($this->request->is('get')) {
//On page load load the user data
$this->request->data = $this->User->read();
} else {
//Saving
if ($this->User->save($this->data)) {
//....snipped...
} else {
$this->Session->setFlash('Unable to update the user.');
}
}
//Build $groups array for form
// Only admins can assign admin rights
if ($this->isMember('Admin')) {
$this->set('groups',$this->User->Group->find('list'));
} else {
$this->set('groups',$this->User->Group->find('list',array(
'conditions' => array(
'Group.name !=' => 'Admin'
)
)));
}
//...more snipping...
}
edit.ctp (View)
echo $this->Form->create('User', array('action' => 'edit'));
echo $this->Form->input('User.username');
echo $this->Form->input('Group',array(
'type' => 'select',
'multiple' => true,
'label' => "Group (Select multiple entries with CTRL)",
'size' => count($groups)
)
);
//More snipping
With that example to work from, how are you validating that the Business.name entered is valid and can be matched to the HABTM relation? Mine forces a selection list in this case. My Model is extremely simple so I didn't include that.
What are your outputs to debug($this->data); vs. debug($this->request->data)?
trying to edit multiple models
The Controller
function edit($id = null) {
if (!empty($this->data)) {
$this->Qnote->save($this->data);
if ($this->Qnote->save($this->data)) {
$this->data['Step']['qnote_id'] = $this->Qnote->id;
$this->Step->save($this->data);
$this->Session->setFlash(__('The qnote has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The qnote could not be saved. Please, try again.', true));
}
}
The Form
<?php echo $this->Form->create();?>
<fieldset>
<legend><?php __('Edit Qnote'); ?></legend>
<?php
echo $this->Form->hidden('Qnote.id');
echo $this->Form->input('Qnote.subject');
echo $this->Form->input('Qnote.body');
echo $this->Form->hidden('Step.0.id');
echo $this->Form->Hidden('Step.qnote_id');
echo $this->Form->Hidden('Step.user_id');
echo $this->Form->input('Step.0.body');
?>
<?php echo $this->Form->end(__('Submit', true));?>
I am trying to edit and update information in associated models , Qnotes and Step
The information show up in the form. however when i submit the form. the
the Qnote information is saving with out any problem . however the step information is not updating
The models are associated. with Steps belong to Qnote, QNote has Many Steps
Your form include '0' for all the Step inputs.
echo $this->Form->hidden('Qnote.id');
echo $this->Form->input('Qnote.subject');
echo $this->Form->input('Qnote.body');
echo $this->Form->hidden('Step.0.id');
echo $this->Form->Hidden('Step.0.qnote_id');
echo $this->Form->Hidden('Step.0.user_id');
echo $this->Form->input('Step.0.body');
And in your controller action, you need to call saveAll() instead.
if ($this->Qnote->saveAll($this->data)) {
...
Try this to load different model. :)
var $uses = array('Qnote', 'Step', 'modelName');
If you want to save data in mutiple model you have to call the model in controller. Using
$this->loadModel('Step');
then do the save part like below. You have called save function for an object twice.
function edit($id = null) {
if (!empty($this->data)) {
$save = $this->Qnote->save($this->data);
if ($save) {
$this->data['Step']['qnote_id'] = $this->Qnote->id;
$this->Step->save($this->data);
$this->Session->setFlash(__('The qnote has been saved', true));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The qnote could not be saved. Please, try again.', true));
}
}
If the models are associated, you can save the whole thing at once (in all the models concerned) just by using the saveAll() function.