我有第一个名为“地方”的实体,用于映射地点数据,如地名,纬度和经度。 另一个称为“用户”的实体存储用户数据,如用户名,用户当前纬度,用户当前经度。
我想为“地点”实体添加一个虚拟字段,用于计算地理点之间的距离。
我正在使用此功能 -
class Places{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
* @ORM\Column(name="name", type="string", length=255)
* @Assert\NotBlank()
* @Expose
*/
private $name;
/**
* @var string
* @ORM\Column(name="description", type="string", length=255, nullable=true)
* @Expose
*/
private $description;
/**
* @var float
* @ORM\Column(name="lon", type="float", nullable=true)
* @Expose
*/
private $lon;
/**
* @var float
* @ORM\Column(name="lat", type="float", nullable=true)
* @Expose
*/
private $lat;
/**
* @var integer
* @ORM\ManyToOne(targetEntity="Countries")
* @ORM\JoinColumn(name="country", referencedColumnName="id", onDelete="SET NULL")
* @Assert\NotBlank()
* @Expose
*/
private $country;
/**
* @var string
* @VirtualProperty
* @Type("string")
* @SerializedName("distance")
* @return string
*/
public function distance(){
$longitude1 = '34.7722';//$user->getLon();(?)
$latitude1 = '32.0114';//$user->getLat();(?)
$longitude2 = $this->getLon();
$latitude2 = $this->getLat();
$theta = $longitude1 - $longitude2;
$miles = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
$miles = acos($miles);
$miles = rad2deg($miles);
$miles = $miles * 60 * 1.1515;
$kilometers = $miles * 1.609344;
//return round($kilometers);
return $this->user->getLastName();
}
}
但是你可以看到lon1 / lat1是硬编码的,因为我无法在places实体中获得用户lan / lat。
我该怎么做?
感谢。
答案 0 :(得分:1)
为什么不将场所实体传递给你的函数?
public function distance($place){
$longitude1 = $place->getLon();
$latitude1 = $place->getLat();
$longitude2 = $this->getLon();
$latitude2 = $this->getLat();
$theta = $longitude1 - $longitude2;
$miles = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
$miles = acos($miles);
$miles = rad2deg($miles);
$miles = $miles * 60 * 1.1515;
$kilometers = $miles * 1.609344;
return round($kilometers);
}
答案 1 :(得分:1)
我懂了!! 使用事件监听器来解决此问题。
监听器:
class SearchIndexer{
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function postLoad (LifecycleEventArgs $args){
$entity = $args->getEntity();
if ($entity instanceof Places) {
$user = $this->tokenStorage->getToken()->getUser();
$entity->setUser_longitude($user->getLastGeoLocationLon());
$entity->setUser_latitude($user->getLastGeoLocationLat());
}
}
}
服务:
services:
doctrine.listener:
class: ApplicationBundle\Listener\SearchIndexer
arguments: ["@security.token_storage"]
tags:
- { name: doctrine.event_listener, event: postLoad }
放置实体:
class Places
{
private $user_longitude;
public function setUser_longitude($user_longitude){
$this->user_longitude = $user_longitude;
}
private $user_latitude;
public function setUser_latitude($user_latitude){
$this->user_latitude = $user_latitude;
}
/**
* @var string
* @VirtualProperty
* @Type("string")
* @SerializedName("distance")
* @return string
*/
public function distance(){
$longitude2 = $this->getLon();
$latitude2 = $this->getLat();
$theta = $this->user_longitude - $longitude2;
$miles = (sin(deg2rad($this->user_latitude)) * sin(deg2rad($latitude2))) + (cos(deg2rad($this->user_latitude)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
$miles = acos($miles);
$miles = rad2deg($miles);
$miles = $miles * 60 * 1.1515;
$kilometers = $miles * 1.609344;
return round($kilometers);
}
//rest of the class
}
答案 2 :(得分:0)
你在地方和用户之间没有任何关系,你不能在地方实体内做到这一点。假设用户是登录用户。您的逻辑必须在服务中并注入TokenStorage以使用户记录:
namespace Acme\Bundle\AcmeBundle\Manager;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Acme\Bundle\AcmeBundle\Entity\Location;
class LocationFinder{
/*
* @var TokenStorageInterface
*/
private $tokenStorage;
public function __construct(TokenStorageInterface $tokenStorage)
{
$this->tokenStorage = $tokenStorage;
}
public function getDistance(Location $location)
{
$longitude1 =$this->tokenStorage->getToken()->getUser()->getLon();
$latitude1 = $this->tokenStorage->getToken()->getUser()->getLat();
$longitude2 = $this->getLon();
$latitude2 = $this->getLat();
$theta = $longitude1 - $longitude2;
$miles = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
$miles = acos($miles);
$miles = rad2deg($miles);
$miles = $miles * 60 * 1.1515;
$kilometers = $miles * 1.609344;
return round($kilometers);
}
}
然后你必须在Resources \ config \ services.xml
中创建服务<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="acme.manager.location_finder" class="Acme\Bundle\AcmeBundle\Manager\LocationFinder">
<argument type="service" id="security.token_storage" />
</service>
</services>
</container>
现在您可以在控制器中获取LocationService并获取位置和用户记录之间的距离
class AccountController extends Controller
{
/**
* @Route("/place/{id}", name="place")
* @Method("GET")
*/
public function placeAction($id)
{
$em = $this->getDoctrine()->getEntityManager();
$location = $em->getRepository('AcmeBundle:Location')->findOneBy([
'id' => $id
]);
$distance = $this->get('acme.manager.location_finder')->getDistance($location);
}
}
您有更多信息: http://symfony.com/doc/current/book/service_container.html