Ask your Symfony questions! Pay money and get answers fast! (more info)

Problem with embedded relationship form Symfony

  • SOLVED

I want to embed an additional relationship into a form. I have used the advanced form tutorial to save photos against an encounter (the equivalent of the product in the tutorial)

http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms

I have another relation with a table called cameras and want to save the camera_id with my photos.

<?php

class CcEncountersPhotosCollectionForm extends sfForm {

public function configure() {

if (!$encounter = $this->getOption('CcEncounters')) {
throw new InvalidArgumentException('You must provide an encounter object');
}

for ($i = 0 ; $i < $this->getOption('size', 2); $i++) {

$encounterPhoto = new CcPhotos();
$encounterPhoto->CcEncounters = $encounter;

$form = new CcPhotosForm($encounterPhoto);
$this->embedForm($i, $form);
$this->mergePostValidator(new CcPhotosValidatorSchema()); //from advanced form tut which has a custom validator
}

}

}

I am using Doctrine and Symfony 1.4. My schema is as follows:

CcAnimals:
actAs: [Timestampable]
connection: doctrine
tableName: cc_animals
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
type:
type: string(11)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
nickname:
type: string(255)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
created_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
updated_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
sex:
type: string(6)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
notes:
type: string()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
flag_is_collared:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
last_known_location:
type: string(11)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
relations:
CcPhotosAnimals:
local: id
foreign: animal_id
type: many
CcCameras:
actAs: [Timestampable]
connection: doctrine
tableName: cc_cameras
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
longitude:
type: float()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
latitude:
type: float()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
elevation:
type: float()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
terrain_type:
type: string()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
created_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
updated_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
relations:
CcEncounters:
local: id
foreign: camera_id
type: many
onDelete: set null
CcPhotos:
local: id
foreign: camera_id
type: many
CcEncounters:
actAs: [Timestampable]
connection: doctrine
tableName: cc_encounters
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
camera_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false

latitude:
type: float()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
longitude:
type: float()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
elevation:
type: float()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
created_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
updated_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
relations:
CcCameras:
local: camera_id
foreign: id
type: one
CcPhotos:
local: id
foreign: encounter_id
type: many

CcIdentifiedCats:
actAs: [Timestampable]
connection: doctrine
tableName: cc_identified_cats
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
animal_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
user_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
identification_notes:
type: string()
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
created_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
updated_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
CcPhotos:
actAs: [Timestampable]
connection: doctrine
tableName: cc_photos
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
filename:
type: string(255)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
created_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
camera_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
encounter_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
right_flank_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
left_flank_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
left_tail_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
right_tail_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
dorsal_tail_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
face_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
right_forelimb_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
left_forelimb_visible:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
gis_confirmation:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
flag_unidentifiable:
type: integer(1)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
updated_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
relations:
CcEncounters:
local: encounter_id
foreign: id
type: one
onDelete: set null
CcCameras:
local: camera_id
foreign: id
type: one
CcPhotosAnimals:
local: id
foreign: photo_id
type: many
CcPhotosAnimals:
connection: doctrine
tableName: cc_photos_animals
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
photo_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
animal_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
relations:
CcAnimals:
local: animal_id
foreign: id
type: one
CcPhotos:
local: photo_id
foreign: id
type: one
CcVotes:
actAs: [Timestampable]
connection: doctrine
tableName: cc_votes
columns:
id:
type: integer(4)
fixed: false
unsigned: false
primary: true
autoincrement: true
user_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
animal_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
photo_id:
type: integer(4)
fixed: false
unsigned: false
primary: false
notnull: false
autoincrement: false
created_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false
updated_at:
type: timestamp(25)
fixed: false
unsigned: false
primary: false
notnull: true
autoincrement: false


The question is how can I get the camera id to save with the photos? The saving of photos works but the camera ID is not stored.

Answers (1)

2011-02-22

Gergely Szilagyi answers:

Hi!

<em><strong>Once : </strong></em>

Did you try to unset the camera_id field in child forms?!

[[LINK href="http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_easily_embedding_doctrine_related_forms"]]http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_easily_embedding_doctrine_related_forms[[/LINK]]

This method of Doctrine Forms are supported from sf1.3+ .
This is more easily. And when you watch, the product_id from this example is missing, cause this function connect the object relations - detected in schema.

// product forms

widgetSchema => array
(
[id] => sfWidgetFormInputHidden, <strong> //id of product</strong>
[name] => sfWidgetFormInputText,
[price] => sfWidgetFormInputText,
[newPhotos] => array(...)
[Photos] => array(
[0] => array(<strong> // dont need product_id again cause doctrine handle it automatic</strong>
[id] => sfWidgetFormInputHidden,
[caption] => sfWidgetFormInputText,

),
[1] => array(<strong> // dont need product_id again cause doctrine handle it automatic</strong>
[id] => sfWidgetFormInputHidden,
[caption] => sfWidgetFormInputText,
),
),
)




<em><strong>Twice</strong></em>

You are not using doctrine form in inheritance, just a simple sfForm.... Watch with this.
From symfony 1.4 you can handle the doctrine forms mutch more in OOP acpect , than earlier.
Use for example this and use inside the embedRelation function of ssfFormDoctrine class:
class CcEncountersPhotosCollectionForm<strong> extends BaseCcCamerasForm</strong>

and so more, just going deeper, and setting your forms as custom sfFormDoctrine instances.

Could you show me the expected output of widget schema - just like array?
( like i wrote in my first code example above )



---- sorry, but i have no idea why show the system my one answer triple .... :(



Gergely Szilagyi comments:


Hi!

<em><strong>Once : </strong></em>

Did you try to unset the camera_id field in child forms?!

http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_easily_embedding_doctrine_related_forms.

This method of Doctrine Forms are supported from sf1.3+ .
This is more easily. And when you watch, the product_id from this example is missing, cause this function connect the object relations - detected in schema.

// product forms

widgetSchema => array
(
[id] => sfWidgetFormInputHidden, <strong> //id of product</strong>
[name] => sfWidgetFormInputText,
[price] => sfWidgetFormInputText,
[newPhotos] => array(...)
[Photos] => array(
[0] => array(<strong> // dont need product_id again cause doctrine handle it automatic</strong>
[id] => sfWidgetFormInputHidden,
[caption] => sfWidgetFormInputText,

),
[1] => array(<strong> // dont need product_id again cause doctrine handle it automatic</strong>
[id] => sfWidgetFormInputHidden,
[caption] => sfWidgetFormInputText,
),
),
)




<em><strong>Twice</strong></em>

You are not using doctrine form in inheritance, just a simple sfForm.... Watch with this.
From symfony 1.4 you can handle the doctrine forms more OOP acpect, than earlier.
Use for example :
class CcEncountersPhotosCollectionForm<strong> extends BaseCcCamerasForm</strong>

and so more, just going deeper, and setting your forms as custom DoctrineForm instances.

Could you show me the expected output of widget schema - just like array?
( like i wrote in my first code example above )


codecowboy comments:

Hi,

Thanks for your replies. I think the form is already in the format I need:


* $form['id'] (sfWidgetFormInputHidden)
* $form['camera_id'] (sfWidgetFormDoctrineChoice)
* $form['latitude'] (sfWidgetFormInputText)
* $form['longitude'] (sfWidgetFormInputText)
* $form['elevation'] (sfWidgetFormInputText)
* $form['newPhotos'][0]['filename'] (sfWidgetFormInputFileEditable)
* $form['newPhotos'][0]['id'] (sfWidgetFormInputHidden)
* $form['newPhotos'][1]['filename'] (sfWidgetFormInputFileEditable)
* $form['newPhotos'][1]['id'] (sfWidgetFormInputHidden)

The issue is that the embedded photo form is not saving the camera ID. I think maybe I just need some custom form saving logic to do this?


Gergely Szilagyi comments:

Hi!

<strong>In this case you can override the doSave method, to fixing the camera_id.</strong>
And no need custom form, just a little customize the base doctrine generated form!
Then the <strong>doSave</strong> of parent will handle, and store the embedded forms and fields, and take care just with the camera_id, after you saved this object.
Just example, use what you need:

class CcEncountersPhotosCollectionForm extends BaseCcCamerasForm
{

protected function doSave($con = null)
{
$return_value = parent::doSave($con);

/***
* do something with camera_id
* you can use the $this->getObject(), or $this->getOption(), or something.
*/
return $return_value;
}

}


I guess, this should work.

Best Regards :
Gergely Szilagyi