EasyAdminBundle NumberField 是四舍五入纬度和经度小数点

问题描述

我在 PHP Symfony 项目中使用 EasyAdminBundle。在管理员中,我在编辑和详细信息视图中显示 NumberFields 纬度和经度时遇到问题,因为 EasyAdmin 不显示存储在数据库中的值,这些值仅四舍五入为 3 位小数,而不是存储在数据库中的所有小数.

您可以在下面看到我的 ActionCrudController:

<?PHP

namespace App\Controller\Admin;

use App\Entity\Action;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use Symfony\Component\Routing\Annotation\Route;
use EasyCorp\Bundle\EasyAdminBundle\Field\Field;
use EasyCorp\Bundle\EasyAdminBundle\Field\EmailField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TelephoneField;
use EasyCorp\Bundle\EasyAdminBundle\Field\UrlField;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextareaField;
use EasyCorp\Bundle\EasyAdminBundle\Field\NumberField;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;

use EasyCorp\Bundle\EasyAdminBundle\Config\Action as EasyCorpAction;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;

class ActionCrudController extends AbstractCrudController
{

    public static function getEntityFqcn(): string
    {
        return Action::class;
    }

    public function configureFields(string $pageName): iterable
    {
        return [
            IdField::new('id')->hideOnForm(),TextField::new('name'),TextEditorField::new('description')->hideOnIndex(),TextareaField::new('address'),TextField::new('city')->hideOnIndex(),TextField::new('postal_code')->hideOnIndex(),TextField::new('email'),TelephoneField::new('phone'),UrlField::new('website')->hideOnIndex(),TextEditorField::new('opening_hours'),NumberField::new('latitude')->hideOnIndex(),NumberField::new('longitude')->hideOnIndex(),TextareaField::new('public_accueilli_detail')->hideOnIndex(),TextareaField::new('modalite_acces')->hideOnIndex(),TextareaField::new('tarif')->hideOnIndex(),TextField::new('slug')->hideOnIndex(),DateTimeField::new('created_at')->onlyOnIndex(),DateTimeField::new('updated_at')->onlyOnIndex(),AssociationField::new('operateur')->setrequired(true),AssociationField::new('sousthematiques'),AssociationField::new('public_accueilli')->hideOnIndex(),];
    }

    public function configureActions(Actions $actions): Actions
    {
        return $actions
            ->add(Crud::PAGE_INDEX,EasyCorpAction::DETAIL);
    }
}

你可以在这里看到我的动作实体,其中纬度和经度是浮动的:

<?PHP

namespace App\Entity;

use App\Repository\ActionRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass=ActionRepository::class)
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Table("action")
 */
class Action
{
    use Timestamps;

    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string",length=255)
     */
    private $name;

    /**
     * @ORM\Column(type="text",nullable=true)
     */
    private $description;

    /**
     * @ORM\Column(type="string",length=255,nullable=true)
     */
    private $address;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $city;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $postal_code;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $email;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $phone;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $website;

    /**
     * @ORM\Column(type="text",nullable=true)
     */
    private $opening_hours;

    /**
     * @ORM\Column(type="float")
     */
    private $latitude;

    /**
     * @ORM\Column(type="float")
     */
    private $longitude;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $public_accueilli_detail;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $modalite_acces;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $tarif;

    /**
     * @ORM\Column(type="string",nullable=true)
     */
    private $slug;

    /**
     * @ORM\Column(type="datetime")
     */
    private $created_at;

    /**
     * @ORM\Column(type="datetime",nullable=true)
     */
    private $updated_at;

    /**
     * @ORM\ManyToOne(targetEntity=Operateur::class,inversedBy="actions")
     * @ORM\JoinColumn(nullable=false)
     */
    private $operateur;

    /**
     * @ORM\ManyToMany(targetEntity=SousThematique::class,inversedBy="actions")
     */
    private $sousthematiques;

    /**
     * @ORM\OnetoMany(targetEntity=HoraireAction::class,mappedBy="action")
     */
    private $horaire_actions;

    /**
     * @ORM\ManyToMany(targetEntity=PublicAccueilli::class,inversedBy="actions")
     */
    private $public_accueilli;

    public function __construct()
    {
        $this->sousthematiques = new ArrayCollection();
        $this->horaire_actions = new ArrayCollection();
        $this->public_accueilli = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getName(): ?string
    {
        return $this->name;
    }

    public function setName(string $name): self
    {
        $this->name = $name;

        return $this;
    }

    public function getDescription(): ?string
    {
        return $this->description;
    }

    public function setDescription(?string $description): self
    {
        $this->description = $description;

        return $this;
    }

    public function getAddress(): ?string
    {
        return $this->address;
    }

    public function setAddress(?string $address): self
    {
        $this->address = $address;

        return $this;
    }

    public function getCity(): ?string
    {
        return $this->city;
    }

    public function setCity(?string $city): self
    {
        $this->city = $city;

        return $this;
    }

    public function getPostalCode(): ?string
    {
        return $this->postal_code;
    }

    public function setPostalCode(?string $postal_code): self
    {
        $this->postal_code = $postal_code;

        return $this;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(?string $email): self
    {
        $this->email = $email;

        return $this;
    }

    public function getPhone(): ?string
    {
        return $this->phone;
    }

    public function setPhone(?string $phone): self
    {
        $this->phone = $phone;

        return $this;
    }

    public function getWebsite(): ?string
    {
        return $this->website;
    }

    public function setWebsite(?string $website): self
    {
        $this->website = $website;

        return $this;
    }

    public function getopeningHours(): ?string
    {
        return $this->opening_hours;
    }

    public function setopeningHours(?string $opening_hours): self
    {
        $this->opening_hours = $opening_hours;

        return $this;
    }

    public function getLatitude(): ?float
    {
        return $this->latitude;
    }

    public function setLatitude(float $latitude): self
    {
        $this->latitude = $latitude;

        return $this;
    }

    public function getLongitude(): ?float
    {
        return $this->longitude;
    }

    public function setLongitude(float $longitude): self
    {
        $this->longitude = $longitude;

        return $this;
    }

    public function getPublicAccueilliDetail(): ?string
    {
        return $this->public_accueilli_detail;
    }

    public function setPublicAccueilliDetail(?string $public_accueilli_detail): self
    {
        $this->public_accueilli_detail = $public_accueilli_detail;

        return $this;
    }

    public function getModaliteAcces(): ?string
    {
        return $this->modalite_acces;
    }

    public function setModaliteAcces(?string $modalite_acces): self
    {
        $this->modalite_acces = $modalite_acces;

        return $this;
    }

    public function getTarif(): ?string
    {
        return $this->tarif;
    }

    public function setTarif(?string $tarif): self
    {
        $this->tarif = $tarif;

        return $this;
    }

    public function getSlug(): ?string
    {
        return $this->slug;
    }

    public function setSlug(?string $slug): self
    {
        $this->slug = $slug;

        return $this;
    }

    public function getCreatedAt(): ?\DateTimeInterface
    {
        return $this->created_at;
    }

    public function setCreatedAt(\DateTimeInterface $created_at): self
    {
        $this->created_at = $created_at;

        return $this;
    }

    public function getUpdatedAt(): ?\DateTimeInterface
    {
        return $this->updated_at;
    }

    public function setUpdatedAt(?\DateTimeInterface $updated_at): self
    {
        $this->updated_at = $updated_at;

        return $this;
    }

    public function getoperateur(): ?Operateur
    {
        return $this->operateur;
    }

    public function setoperateur(?Operateur $operateur): self
    {
        $this->operateur = $operateur;

        return $this;
    }

    /**
     * @return Collection|SousThematique[]
     */
    public function getSousthematiques(): Collection
    {
        return $this->sousthematiques;
    }

    public function addSousthematique(SousThematique $sousthematique): self
    {
        if (!$this->sousthematiques->contains($sousthematique)) {
            $this->sousthematiques[] = $sousthematique;
        }

        return $this;
    }

    public function removeSousthematique(SousThematique $sousthematique): self
    {
        $this->sousthematiques->removeElement($sousthematique);

        return $this;
    }

    /**
     * @return Collection|HoraireAction[]
     */
    public function getHoraireActions(): Collection
    {
        return $this->horaire_actions;
    }

    public function addHoraireAction(HoraireAction $horaireAction): self
    {
        if (!$this->horaire_actions->contains($horaireAction)) {
            $this->horaire_actions[] = $horaireAction;
            $horaireAction->setAction($this);
        }

        return $this;
    }

    public function removeHoraireAction(HoraireAction $horaireAction): self
    {
        if ($this->horaire_actions->removeElement($horaireAction)) {
            // set the owning side to null (unless already changed)
            if ($horaireAction->getAction() === $this) {
                $horaireAction->setAction(null);
            }
        }

        return $this;
    }

    /**
     * @return Collection|PublicAccueilli[]
     */
    public function getPublicAccueilli(): Collection
    {
        return $this->public_accueilli;
    }

    public function addPublicAccueilli(PublicAccueilli $public_accueilli): self
    {
        if (!$this->public_accueilli->contains($public_accueilli)) {
            $this->public_accueilli[] = $public_accueilli;
        }

        return $this;
    }

    public function removePublicAccueilli(PublicAccueilli $public_accueilli): self
    {
        $this->public_accueilli->removeElement($public_accueilli);

        return $this;
    }

    public function __toString()
    {
        return $this->name;
    }
}

我一直在尝试多种解决方案,例如:

  • 修改ActionCrudController中的纬度和经度表单字段 -->

例如。 NumberField::new('longitude')->hideOnIndex()->setNumDecimals(12),

但这并不是我想要的,因为在 Detail 和 Edit 视图中没有出现存储在数据库中的确切浮点数。如果浮点数少于 12 位小数,则加 0。

  • 我尝试的另一种可能性是修改操作实体:

@ORM\Column(type="float",scale=15) 私人 $latitude;

但它也不起作用。

您知道如何在 EasyAdmin 的“编辑”和“详细信息”视图中显示具有准确小数位数的纬度和经度浮点数吗?

您知道我可以在哪里配置 EasyAdmin 中 NumberField 中显示的小数位数吗?

预先感谢您的帮助!

解决方法

尝试在 Doctrine 注释中添加精度(和十进制类型)?

/**
 * @ORM\Column(type="decimal",precision=9,scale=7)
 */
protected $latitude;
 
/**
 * @ORM\Column(type="decimal",precision=10,scale=7)
 */
protected $longitude;

您可以通过调整它们来选择所需的精确度。

回复您最近的回答(关于您的数据库错误): 您收到此错误是因为您的数据库中有数据以更准确的级别存储(例如 -120.923828919)

精度=总位数(不考虑小数) 小数位数 = 小数点后多少位

MySQL 要求 Scale

你只需要调整你的精度 8 只允许 8 个数字,例如最大可能是 999.99999。纬度坐标从 -90 到 90,经度坐标从 -180 到 180,这取决于您真正需要的小数点后多远。我已经修改了我的价值观,变得更加慷慨。

抱歉,我还不能发表评论,但您可以尝试添加自定义表单类型选项吗?我不认为这归结于 EasyAdmin 本身,而是更多是从 Symfony 继承的 NumberType 字段。文档似乎指向使用“缩放”表单类型选项。

所以也许

NumberField::new('latitude')->hideOnIndex()->setFormTypeOption('scale',8)

如果您需要添加更多选项,只需使用复数形式 ->setFormTypeOptions(['scale' => 8])

指向此功能的直接文档链接: NumberType#scale