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

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.

$4
Simple 1:n embedRelation problem

Hi,

I am using symfony 1.3 and doctrine 1.2

I have a simple situation where one contact has many phone numbers. Contacts are one object/table, phone numbers are another object/table.

I want to have a form where I create a contact along with a single phone number. However, for some reason the "phone" form never displays.

I must be doing something simple wrong, but I can't figure out out.

Here is the schema snippet:

schema.yml

Contact:
columns:
id: { type: integer(4), primary: true, autoincrement: true }
first_name: { type: string(50)}
last_name: { type: string(50)}

Phone:
columns:
id: { type: integer(5), primary: true, autoincrement: true }
contact_id: { type: integer(4) }
number: { type: string(20) }
type: { type: enum, values: [Home, Work, Cell, Fax] }
relations:
Contact: { foreignAlias: Phone }


What I want is for the form to look like:

First name: (input firstname)
Last name: (input lastname)
Phone number: (input number) (dropdown phone number type)


Code snippets:

lib/form/doctrine/PhoneEmbedForm.class.php

<?php

/**
* Phone Embed Form
*
* @package form
* @subpackage PhoneEmbed
* @version 0.1
*/
class PhoneEmbedForm extends BasePhoneForm
{
public function configure()
{
$this->useFields(array('number', 'type'));
}

}


lib/form/doctrine/Contact.class.php

<?php

/**
* Contact form.
*
* @package form
* @subpackage Contact
* @version SVN: $Id: sfDoctrineFormTemplate.php 6174 2007-11-27 06:22:40Z fabien $
*/
class ContactForm extends BaseContactForm
{
public function configure()
{
$this->embedRelation('Phone', 'PhoneEmbedForm');

$this->useFields(array('first_name', 'last_name', 'Phone'));
}
}


apps/myapp/modules/contact/templates/_form.php

<?php echo $form?>



The contact part of the form displays, and it says "Phone" in text but with no input boxes. How do I get it to show the phone boxes AND associate it with the contact upon save? Thank you.

Answerer must submit actual code for this specific case and not just link to a manual (however links to add clarity are appreciated).

This question has been answered.

webguy | 10/19/10 at 4:55pm Edit


The experts have suggested, on average, a prize of $5 for this question.

(9) Responses

See a threaded view of answers?

Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

  • avatar
    Last edited:
    10/20/10
    11:54am
    Joshua Estes says:

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

  • avatar
    Last edited:
    10/20/10
    11:54am
    Pawel Dawczak says:

    Hi,

    first thing is a little change in schema:


    Contact:
    columns:
    id: { type: integer(4), primary: true, autoincrement: true }
    first_name: { type: string(50)}
    last_name: { type: string(50)}



    Phone:
    columns:
    id: { type: integer(5), primary: true, autoincrement: true }
    contact_id: { type: integer(4) }
    number: { type: string(20) }
    type: { type: enum, values: [Home, Work, Cell, Fax] }
    relations:
    Contact: { foreignAlias: Phone, foreignType: one }


    PhoneForm.class.php should be:


    class PhoneForm extends BasePhoneForm
    {
    public function configure()
    {
    $this->useFields(array('number', 'type'));
    }
    }


    and ContactForm.class.php:


    class ContactForm extends BaseContactForm
    {
    public function configure()
    {
    $this->useFields(array('first_name', 'last_name'));

    // embdding form
    $phoneForm = new PhoneForm($this->getObject()->getPhone());
    $this->embedForm('Phone', $phoneForm);
    }
    }


    If you use
    $this->embedRelation('Phone', 'PhoneEmbedForm');
    Doctrine fetches Phone objects related with Contact object only for editing, so you can't create new Phone objects.

    In case I showed above you are embedding a Phone form initialized with related Phone object
    $this->getObject()->getPhone()
    If there is no related Phone object, then you can see a blank form for creating new object.

    Previous versions of this answer: 10/19/10 at 6:49pm

  • avatar
    Last edited:
    10/20/10
    11:54am
    Ivan Rey says:

    Just do both things in your form. Do a embedForm to allow the user to add new phone numbers, and do embedRelation to allow the user to edit current relations.

    In ContactForm.class.php



    class ContactForm extends BaseContactForm
    {
    public function configure()
    {

    $this->embedRelation('Phone'); //This allows the user to edit current relations
    $phone = new Phone();
    $phone->setContact($this->getForm()->getObject());
    $phonesForm = new PhoneForm($phone);
    $this->embedForm($phonesForm); //This allows new phones to be added
    }
    }


    Previous versions of this answer: 10/20/10 at 12:24am

  • avatar
    Last edited:
    10/20/10
    4:25am
    saki says:

    Instead of this:

    $phone->setContact($this->getForm()->getObject());


    Use this:

    $phone->Contact = $this->getObject();


    I hope this helps...

  • avatar
    Last edited:
    10/19/10
    5:16pm
    webguy says:

    I specifically asked please don't directly link to docs with no notes. I have read that page and am still having issues.

    So, a few things:

    1) The phone number is a doctrine object, so according to that page embedRelation should work (am i wrong?)

    2) I have tried the embedForm approach, however it doesn't properly associate the phone number and contact (however it creates both in the database

    lib/form/doctrine/ContactForm.class.php

    <?php
    /**
    * Contact form.
    */
    class ContactForm extends BaseContactForm
    {
    public function configure()
    {
    $phoneForm = new PhoneEmbedForm(new Phone());
    $this->embedForm('Phone', $phoneForm);
    $this->useFields(array('first_name', 'last_name', 'Phone'));
    }
    }


    lib/form/doctrine/PhoneEmbedForm.class.php

    <?php

    /**
    * Phone Embed Form
    *
    * @package form
    * @subpackage PhoneEmbed
    * @version 0.1
    */
    class PhoneEmbedForm extends PhoneForm
    {
    public function configure()
    {
    $this->useFields(array('number', 'type'));
    }

    }

  • avatar
    Last edited:
    10/19/10
    5:20pm
    Joshua Estes says:

    schema.yml


    Contact:
    columns:
    first_name: { type: string(50)}
    last_name: { type: string(50)}
    relations:
    Phone:
    foreign: contact_id
    local: id

    Phone:
    columns:
    contact_id: { type: integer(4) }
    number: { type: string(20) }
    type: { type: enum, values: [Home, Work, Cell, Fax] }


    ContactForm.class.php

    class ContactForm extends BaseContactForm
    {
    public function configure()
    {
    $this->embedRelation('Phone');
    }
    }


    PhoneForm.class.php

    class PhoneForm extends BasePhoneForm
    {
    public function configure()
    {
    unset($this['contact_id']);
    }
    }


    That should get you started

  • avatar
    Last edited:
    10/19/10
    7:40pm
    webguy says:

    That works, but the schema complicates things a bit now.

    I have a page where I list contacts and all of their phone numbers...

    For example:


    Contact 1:
    - Phone1
    - Phone2
    Contact 2:
    - Phone3
    Contact3:
    - Phone 4
    - Phone 5


    I used to be able to do a

    <?php foreach ($contact->getPhone() as $i => $phone): ?>
    <?php echo $phone->getNumber(); ?>
    <?php endforeach; ?>


    but now because of the schema updates, that doesnt work...

  • avatar
    Last edited:
    10/20/10
    9:47am
    Pawel Dawczak says:

    Hi, sorry for my mistake. I gave you solution if you want to have relation 1:1. But this is for relation 1:N.

    config/schema.yml


    Contact:
    columns:
    id: { type: integer(4), primary: true, autoincrement: true }
    first_name: { type: string(50)}
    last_name: { type: string(50)}

    Phone:
    columns:
    id: { type: integer(5), primary: true, autoincrement: true }
    contact_id: { type: integer(4) }
    number: { type: string(20) }
    type: { type: enum, values: [Home, Work, Cell, Fax] }
    relations:
    Contact: { foreignAlias: PhoneNumbers }


    Now you can fetch all related objects with:

    foreach ($contact->getPhoneNumbers() as $number)
    {
    echo $number->getNumber();
    }


    lib/form/doctrine/PhoneForm.class.php

    class PhoneForm extends BasePhoneForm
    {
    public function configure()
    {
    $this->useFields(array('contact_id', 'number', 'type'));

    $this->widgetSchema['contact_id'] = new sfWidgetFormInputHidden();
    }
    }


    lib/form/doctrine/ContactForm.class.php

    class ContactForm extends BaseContactForm
    {
    public function configure()
    {
    $this->useFields(array('first_name', 'last_name'));

    // if object is new, it has no ID that we need to set in new embedded form
    if (!$this->getObject()->isNew())
    {
    // adds blank form for adding new related values
    $newPhoneForm = new PhoneForm();
    $newPhoneForm->setDefault('contact_id', $this->getObject()->getId());
    $this->embedForm('new', $newPhoneForm);

    // adds forms for all related objects
    $this->embedRelation('PhoneNumbers');
    }
    }

    protected function doBind(array $values)
    {
    // you need to check if blank form is filled
    if ('' === trim($values['new']['number']))
    {
    unset($values['new'], $this['new']);
    }

    parent::doBind($values);
    }
    }


    It is based on . You can find there a solution, how to add a check box, to delete embedded values.

  • avatar
    Last edited:
    10/20/10
    9:49am
    Pawel Dawczak says:

    Sorry, I missed a link to article: link

This question has expired.





Current status of this question: Completed



Warning: Please do not give out any FTP or ssh credentials to anyone, unless you trust them completely. Giving out login details is dangerous.

If the asker does not get an answer then they have 10 days to request a refund.