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

Outputting n:m relationship in dropdown list Symfony

  • REFUNDED

I have symfony 1.3 and use doctrine.

I have a situation where I have vendors and locations. Locations can be shared between vendors.

Abbreviated schema:

Vendor:
columns:
id: { type: integer(4), primary: true, autoincrement: true }
name: { type: string(75), notnull:true }
relations:
Location: { refClass: VendorLocation, local: vendor_id, foreign: location_id }
VendorLocation:
options:
symfony:
form: false
filter: false
columns:
vendor_id: { type: integer(4), primary: true }
location_id: { type: integer(4), primary: true }
Location:
columns:
id: { type: integer(4), primary: true, autoincrement: true }
name: { type: string(100), notnull: true }
city: { type: string(50), notnull: true }
relations:
Vendor: { class: Vendor, refClass: AccountWarehouse, local: location_id, foreign: vendor_id }


I want to create a dropdown in a form (a form with shipping options) where a list of all shipping points is available. I want to have it list in the way: Vendor - LocationName (City). So, since it is many to many, it might look like:

<blockquote>VendorA - Location1 (MyCity)
VendorA- Location2 (NextCity)
VendorB - Location1 (MyCity)
VendorB - Location3 (MoreCity)
VendorC - Location4(AnotherCity)</blockquote>

In my location class i have (lib/model/doctrine/Location.class.php)

public function getVendorAndLocation()
{
return sprintf('%s - %s (%s, %s)', $this->getVendor()->getName, $this->getName(), $this->getCity(), $this->getZone());
}



lib/model/doctrine/LocationTable.class.php

public function listLocationsByVendorQuery()

{

$q = Doctrine_Query::create()

->select('l.name, l.city, l.city, l.id, v.id, v.name, vl.*')

->from('Location l')

->leftJoin('l.VendorLocation vl')

->leftJoin('l.Vendor v');

return $q;

}


In my form i have (lib/form/doctrine/ShipForm.class.php)

$this->widgetSchema['location_id'] = new sfWidgetFormDoctrineChoiceMany(array(
'model' => 'Location',
'query' => Doctrine::getTable('Location')->listLocationsByVendorQuery(),
'method' => 'getVendorAndLocation',
'multiple' => false
));




When I try it, I keep getting a doctrine collection instead of having it list as i want. SO, How can I make it output the n:m relationship like this?


<blockquote>VendorA - Location1 (MyCity)
VendorA- Location2 (NextCity)
VendorB - Location1 (MyCity)
VendorB - Location3 (MoreCity)
VendorC - Location4(AnotherCity)</blockquote>

Answers (3)

2010-08-31

Joshua Estes answers:

Can you post the code that corresponds with the function listLocationsByVendorQuery() in the LocationTable.class.php?


webguy comments:

lib/model/doctrine/LocationTable.class.php

public function listLocationsByVendorQuery()
{
$q = Doctrine_Query::create()
->select('w.name, w.city, z.code, w.postcode, w.contact, w.phone, w.id, a.id, a.name, aw.*')
->from('Warehouse w')
->leftJoin('w.AccountWarehouse aw')
->leftJoin('w.Zone z')
->leftJoin('w.Account a');
return $q;
}


webguy comments:

Please disregard that last post, look at body of question for accurate code


Joshua Estes comments:

<blockquote> public function getVendorAndLocation()
{

return sprintf('%s - %s (%s, %s)', $this->getVendor()->getName, $this->getName(), $this->getCity(), $this->getZone());

}</blockquote>

Noticed <strong>$this->getVendor()->getName</strong> doubt it's the issue, but shouldn't it be getName() instead of getName?


Joshua Estes comments:

Try removing the "query" option in the sfWidgetFormDoctrineChoice, that should work for you.


webguy comments:

the getName / getName() thing was a typo when I was writing up that response, so you're correct that's not the issue.

Removing the "query" option is not a suitable solution, I rely on the method to narrow down choices (there is a softdelete and I wish to retain it for other reasons as well).

2010-08-31

Pascal answers:

try that for the widget :


$this->widgetSchema['location_id'] = new sfWidgetFormDoctrineChoice(array(
'model' => 'Location',
'table_method' => 'listLocationsByVendorQuery',
'method' => 'getVendorAndLocation',
));



webguy comments:

Sorry, I checked but that results in the same issue.

2010-09-01

Loban Rahman answers:

I feel that you are unnecessarily complicating matters by putting a widget for "location_id" in the ShipForm. What you want is a list of VendorLocation objects, so why not use a widget for that? Don't forget to declare a __toString() method in the VendorLocation model class with the output you want. If you like this idea, I can write up the code necessary for the widget.