Symfony2:如何通过地址实体上的zip功能来设计解析状态


Symfony2: How to design a resolve state by zip functionality on an address entity

这是一个设计问题。我有一个带有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,它非常方便(将你拥有的任何邮政编码、街道地址……转换为你想要的任何内容),但它可能不是你想要的!

希望我能以某种方式帮助你