EasyAdminBundle NumberField 是舍入纬度和经度小数

Posted

技术标签:

【中文标题】EasyAdminBundle NumberField 是舍入纬度和经度小数【英文标题】:EasyAdminBundle NumberField is rounding latitude and longitude decimals 【发布时间】:2021-08-19 18:48:41 【问题描述】:

我在 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", length=255, nullable=true)
     */
    private $city;

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

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

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

    /**
     * @ORM\Column(type="string", length=255, 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", length=255, nullable=true)
     */
    private $public_accueilli_detail;

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

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

    /**
     * @ORM\Column(type="string", length=255, 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),

但这并不是我想要的,因为在详细信息和编辑视图中并没有显示存储在数据库中的确切浮点数。如果浮点数少于 12 位小数,则加 0。

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

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

但它也不起作用。

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

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

提前感谢您的帮助!

【问题讨论】:

【参考方案1】:

尝试在 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)

如果您需要添加更多选项,只需使用复数版本-&gt;setFormTypeOptions(['scale' =&gt; 8])

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

【讨论】:

【参考方案2】:

目前没有使用 EasyAdmin 的干净方法。

一个快速而肮脏的解决方法是编辑 NumberConfigurator.php (EasyCorp\Bundle\EasyAdminBundle\Field\Configurator)。

在此处将 'fraction_digit' 替换为 'max_fraction_digit':

// $formatterAttributes['fraction_digit'] = $scale;
$formatterAttributes['max_fraction_digit'] = $scale;

然后调用 NumberField::new('longitude')->hideOnIndex()->setNumDecimals(12), 应该按你的意愿工作。

或者,您可以在 NumberField.php 中添加一个 setMaxNumDecimals 方法,并相应地修改源代码到 NumberConfigurator.php。

(如果您愿意,请提交合并请求)

【讨论】:

以上是关于EasyAdminBundle NumberField 是舍入纬度和经度小数的主要内容,如果未能解决你的问题,请参考以下文章

使用 FOS 为 EasyAdminBundle 设置安全性

Symfony EasyAdminBundle 自定义视图

EasyAdminBundle NumberField 是舍入纬度和经度小数

FOSUserBundle 在 EasyAdminBundle 中管理((“用户”实体必须使用“类”选项定义其关联的 Doctrine 实体类))Symfony

CKEditor 未与 easyadmin 集成显示

easyadmin 实体字段的动态自定义选择