Cakephp: Designpattern for creation of models in hasMany relationship - cakephp

I have two Models: Car and Passenger.
Car hasMany Passenger
Passenger belongsTo Car
I managed to create add functionality for each model and managed to resolve the hasMany relationship between them.
Now I'm trying to create a addCar function and view that allows the user to create a new car and automatically generate Passengers.
I thought of something like this
The view asks the user enter the car information
The view has some field that allows to temporarily add new passengers and remove remove them
When the user saves the new car, the entities for the passengers are created, the entity for the car is created and the passengers are linked to the car.
If the user decides to cancel everything, the DB remains unchanged.
Now my question is: What is the best way to do this? Is there a pattern / tutorial to follow for such a entity and associated subentity creation?
To clarify: The passengers associated with each car do not exist prior to the existence of the car.

Use the following code in the view views/passengers/add_cars.ctp:
<?php
echo $this->Form->create('Car');
echo $this->Form->input('name');
echo $this->Form->input('model');
echo $this->Form->input('Passenger.0.name');
echo $this->Form->input('Passenger.0.age');
echo $this->Form->input('Passenger.1.name');
echo $this->Form->input('Passenger.1.age');
echo $this->Form->end();
?>
This basically starts off with the necessary fields to input the car information. Then, you can start a loop with a general format of Passenger.{$i}.name to add passengers dynamically when a new car is added. You can use jQuery to create "add" and "remove" buttons that will add or remove rows of Passenger form entries.
In your passengers_controller.php (assuming this is the controller you want add_cars), use the saveAll function:
function add_cars() {
if (!empty($this->data)) {
if ($this->Passenger->Car->saveAll($this->data)) {
$this->Session->setFlash('Success');
$this->redirect('/');
} else {
$this->Session->setFlash('Error');
}
}
}
Hope that helps.

Related

CakePHP 2.x Accessing Another Model

Noob to cakePHP here.
Bicycle belongsTo Stand
Stand hasMany Bicycle
Stand belongsTo Station
Station hasMany Stand
I've baked the CRUDs and now I want to display the station name when I view a bicycle. How should I define the bicycle - station relationship? Or what do I need to do to include the station model in the bicycles controller?
What I've tried so far. Which throws a "Notice (8): Undefined index: Station":
BicyclesController.php:
public function index() {
$this->Bicycle->recursive = 2;
$this->set('bicycles', $this->Paginator->paginate());
}
index.ctp:
<?php echo $this->Html->link($bicycle['Station']['name'].$bicycle['Stand']['stand_no'], array('controller' => 'stands', 'action' => 'view', $bicycle['Stand']['id'])); ?>
Help!
Since you have no direct relationship from Bicycle to Station, its not going to be available within $bicycle['Station'] Its more likely to be available in $bicycle['Stand']['Station]['name'].
In order to see if its actually being returned with recursive set as it is, I would run the query again and call $debug($bicycle);die; in the following order.
public function index() {
$this->Bicycle->recursive = 2;
$bicycles = $this->Paginator->paginate();
$debug($bicycle);die;
$this->set(compact('bicycles'));
}
This will kill the model at this point and display an array of results returned. You will then see where the information you want is, and how to access it. Just remove the $debug line when finished.

CakePHP remove empty relations

I have relation Holiday hasMany Place (Place belongsTo Holiday).
I prepare some form in Holiday view:
echo $this->Form->input('name');
echo $this->Form->input('Place.0.name');
echo $this->Form->input('Place.1.name');
echo $this->Form->input('Place.2.name');
Now, when I add Holiday with 2 places, I can't save because the one is empty.
How remove empty record in model?
Loop through them, if it's empty, unset it.
foreach ($data['Place'] as $key => $place) {
if (empty($place['name'])) {
unset($data['Place'][$key]);
}
}
Not sure about the paths, just update them accordingly to what your post data looks like.

Cakephp FormHelper Create select box

i am cakephp beginner.
My Employee Model,
class Employee extends AppModel {
var $belongsTo = array(
'Department'=>array(
'className'=>'Department',
'foreignKey'=>'department_id',
'conditions'=>null,
'fields'=>null
)
);
blah--
now in employee add.ctp i want to create a select box which list all the department.
i was going through official cakephp 2.1 documentation (here)
it tells me to add
$this->set('departments', $this->Employee->Department->find('list'));
in my controller..
i have no idea to put in which controller ? is it in EmployeesController or DepartmentsController? and in which action of controller?
view to create select box (in add.ctp)
echo $this->Form->input('Department');
you were almost correct - only a minor glitch:
echo $this->Form->input('department_id');
you need to name the fields as they are in the database.
and if it is a BelongsTo relation than there should be a department_id foreign key in your employees table.
PS: cake knows that if you pass down $departments that this array will need to be the options for this form field. so no additional configuration necessary!
// in your add action at the very bottom
$departments = $this->Employee->Department->find('list');
$this->set(compact('departments'));

How to save multiple individual records for a single model

I have a model(friends), where user can export his friend's info from facebook. I want save friends info(id and name) into the mysql database.
I am having trouble creating a form for the same using form helper as i don't know the exact number of friends for each user.
Is there a easier way to save user's friends into the database? (save multiple records for the same model)
Basically you should know how much is the number of friends for the current user, right?
If so, do a loop with following in your view:
echo $this->Form->create('User');
for($i=0;$i<$number_of_current_user_friends;$i++){
echo $this->Form->input('Friend.'.$i.'user_id', array('value'=>$current_user_id));
echo $this->Form->input('Friend.'.$i.'friend_name', array('value'=>$friends[$i]['name']));
echo $this->Form->input('Friend.'.$i.'fb_id', array('value'=>$friends[$i]['fb_id']));
}
echo $this->Form->end('Submit');
then in the controller save it with:
$this->Friend->saveAll($this->data);

CakePHP assocation question

I'm creating a small timesheet application. Timesheets have athletes, and each athlete has personal split times (like in running, or race car driving)
An Athlete hasMany Run, a Run belongsTo Athlete, An Athlete hasAndBelongsToMany Timesheets (and vice versa). A Timesheet hasMany Run, and finally a Run belongsTo Timesheet.
When I'm adding new runs in my view, I'm unable to get anything but the athlete_id in the select box. I'd really like to have their names instead. Instead of
<?php echo $run['athlete_id'];?>, I've tried <?php echo $athlete['Athlete']['last_name'] ?> but I can't seem to get it to work. Any help would be greatly appreciated. Thanks!
Without knowing exactly how you are building your forms/data it is hard to tell, but how I would do it is.
In the RunController add
$athletes = $this->Run->Athlete->find('list');
$this->set('athletes', $athletes);
and then in the View use this form helper line.
<?php echo $form->input('Run.athlete_id', array('type' => 'select', 'options' => $athletes)); ?>
This should work, there is also a way to use 'compact' to make it a little easier but the above should work fine.
---- BEGIN EDIT ----
I did a little research and found the compact method.
In your RunController use
$athletes = $this->Run->Athlete->find('list');
$this->set(compact('athletes'));
and then in your View use
<?php echo $form->input('Run.athlete_id'); ?>
and the form helper will automatically find the compacted Athlete array and build the select.
---- END EDIT ----
Hope this helps.
Cheers,
Dean
Try printing out the content of the $run: print_r($run) and see if the ['Athlete'] is there.
If not, you might have to manually contain the Athlete model when you do your run query:
$this->Run->contain('Athlete');
Don't forget to use the displayField property of the Model class i.e.
<?php
class Athlete extends AppModel {
public $name = "Athlete";
public $displayField = "name"; // the field name that has the athletes name in it
}
?>
http://book.cakephp.org/view/438/displayField

Resources