php symfony实体中的计算/虚拟字段-如何做到这一点?

yqlxgs2m  于 2023-09-29  发布在  PHP
关注(0)|答案(3)|浏览(143)

我有第一个名为“地点”的实体,它Map了地点数据,如地名,纬度和经度。另一个称为“用户”的实体存储用户数据,如用户名、用户当前纬度、用户当前经度。
我想为“地点”实体添加一个虚拟字段,用于计算地理点之间的距离。
我在用这个功能-

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();
}
}

但是正如你所看到的,lon 1/lat 1是硬编码的,因为我不能从places实体中获取用户lan/lat。
我该怎么做?
谢谢.

5rgfhyps

5rgfhyps1#

我成功了!!使用事件侦听器解决了这个问题。
监听器:

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
}
cs7cruho

cs7cruho2#

你可以将$place实体传递给你的函数:

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);
}
cedebl8k

cedebl8k3#

你在地点和用户之间没有任何关系,你不能在地点实体内部这样做。假设该用户是已登录用户。你的逻辑必须在一个服务中,并注入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
Sf2:在实体内部使用服务

相关问题