这是一个设计问题。我有一个带有ZIP字段的地址实体。
use Doctrine'ORM'Mapping as ORM;
/**
* Address
*
* @ORM'Table(name="address")
* @ORM'Entity
*/
class Address
{
/**
* @var integer
*
* @ORM'Column(name="id", type="integer", nullable=false)
* @ORM'Id
* @ORM'GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM'Column(name="street", type="string", length=128, nullable=false)
*/
private $street;
/**
* @var string
*
* @ORM'Column(name="street2", type="string", length=128, nullable=false)
*/
private $street2;
/**
* @var string
*
* @ORM'Column(name="zip", type="string", length=64, nullable=false)
*/
private $zip;
/**
* @var string
*
* @ORM'Column(name="city", type="string", length=128, nullable=false)
*/
private $city;
/**
* @var string
*
* @ORM'Column(name="country", type="string", length=128, nullable=false)
*/
private $country;
/**
* Set city
*
* @param string $city
* @return Address
*/
public function setCity($city)
{
$this->city = $city;
return $this;
}
/**
* Get city
*
* @return string
*/
public function getCity()
{
return $this->city;
}
/**
* Set country
*
* @param string $country
* @return Address
*/
public function setCountry($country)
{
$this->country = $country;
return $this;
}
/**
* Get country
*
* @return string
*/
public function getCountry()
{
return $this->country;
}
/**
* Set street
*
* @param string $street
* @return Address
*/
public function setStreet($street)
{
$this->street = $street;
return $this;
}
/**
* Get street
*
* @return string
*/
public function getStreet()
{
return $this->street;
}
/**
* Set street2
*
* @param string $street2
* @return Address
*/
public function setStreet2($street2)
{
$this->street2 = $street2;
return $this;
}
/**
* Get street2
*
* @return string
*/
public function getStreet2()
{
return $this->street2;
}
/**
* Set zip
*
* @param string $zip
* @return Address
*/
public function setZip($zip)
{
$this->zip = $zip;
return $this;
}
/**
* Get zip
*
* @return string
*/
public function getZip()
{
return $this->zip;
}
}
此外,我还有一个地理数据库,可以用来解析给定zip的状态。
CREATE TABLE IF NOT EXISTS `zipcode` (
`id` int(11) NOT NULL,
`city_id` int(11) NOT NULL,
`district_id` int(11) DEFAULT NULL,
`zipcode` varchar(10) NOT NULL
) ENGINE=MyISAM AUTO_INCREMENT=8262 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `city` (
`id` int(11) NOT NULL,
`state_id` int(11) NOT NULL,
`county_id` int(11) NOT NULL,
`name` varchar(200) NOT NULL,
`lat` float NOT NULL,
`lng` float NOT NULL
) ENGINE=MyISAM AUTO_INCREMENT=12241 DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `state` (
`id` int(11) NOT NULL,
`name` varchar(200) NOT NULL
) ENGINE=MyISAM AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;
SELECT state.name
FROM zipcode
left join city on zipcode.city_id = city.id
left join state on city.state_id = state.id
WHERE zipcode.zipcode = '26123'
我想我想在地址实体上有一个getState()。但我不确定以何种方式设计数据库查询。为地理数据库创建单独的实体有意义吗?或者只是在某个地方创建一个助手函数?本机sql调用?
您需要定义服务。设为GeoHelper
,在其中注入ZipRepository,并定义将ZIP转换为状态名的方法:
public function getStateByZip($zip)
{
return $zipRepository->findBy(array('zipcode' => $zip))->getState();
}
这对我来说很好,您将把查询状态名称的函数放在您的邮政编码实体存储库中。显然你需要其他数据,比如latlng,。。。因此创建3个独立实体是有意义的。
所以你只需要在控制器中做:
$repository = $this->getDoctrine()->getManager()->getRepository('AcmeMyBundle:Adresse');
$state = $repository->getState($zipcode);
在adresse存储库中,一些看起来像的东西
public function getState($zipCode)
{
$qb = $this->createQueryBuilder('a')
->select('a','z','c','s')
->leftJoin('a.zip', 'z')
->leftJoin('z.city', 'c')
->leftJoin('c.state', 's')
->where('a.zip = :zipcode')->setParameter('zipcode', $zipCode);
return $qb->getResult();
}
你写的函数会放在ZipCodeRepository中,这也很好,而且少了一个联接,但你要求AdressRepository,所以你可以选择。
顺便说一句,我不得不这么做,但我使用了谷歌地理本地化api,它非常方便(将你拥有的任何邮政编码、街道地址……转换为你想要的任何内容),但它可能不是你想要的!
希望我能以某种方式帮助你