【问题标题】:Symfony 4 - FOSUserBundle - Render user information on custom routeSymfony 4 - FOSUserBundle - 在自定义路由上呈现用户信息
【发布时间】:2018-12-05 05:10:37
【问题描述】:

我的自定义 ProfileController 中有一个构造函数和路由

private $userManager;

public function __construct(UserManagerInterface $userManager)
{
    $this->userManager = $userManager;
}

/**
 * @Route("/profile/bookings", name="profile_bookings")
 */
public function bookings()
{

    $user = $this->getUser();

    return $this->render('profile/bookings/bookings.html.twig', array('user'=>$user));
}

在我的模板中我引用了

{{ user.first_name }}

但我得到了错误:

HTTP 500 内部服务器错误 属性“first_name”和方法“first_name()”、“getfirst_name()”/“isfirst_name()”/“hasfirst_name()”或“__call()”都不存在,并且在类“App\”中具有公共访问权限实体\用户”。

我如何从数据库中获取用户信息并显示在个人资料的子页面中?

编辑:用户实体 ...

<?php

namespace App\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use FOS\UserBundle\Model\User as BaseUser;

/**
 * @ORM\Entity
 * @ORM\Table(name="`user`")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     * @ORM\Column(type="integer")
     */
    protected $id;

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

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

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

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

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

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

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

    /**
     * @ORM\OneToMany(targetEntity="App\Entity\Booking", mappedBy="user")
     */
    private $bookings;

    public function __construct()
    {
        parent::__construct();
        $this->bookings = new ArrayCollection();
    }

    /**
     * Overridde setEmail method so that username is now optional
     *
     * @param string $email
     * @return User
     */
    public function setEmail($email)
    {
        $this->setUsername($email);

        return parent::setEmail($email);
    }

    public function getFirstName()
    {
        return $this->first_name;
    }

    public function setFirstName($first_name)
    {
        $this->first_name = $first_name;
    }

    public function getLastName()
    {
        return $this->last_name;
    }

    public function setLastName($last_name)
    {
        $this->last_name = $last_name;
    }

    public function getPhoneNumber(): ?string
    {
        return $this->phone_number;
    }

    public function setPhoneNumber(string $phone_number): self
    {
        $this->phone_number = $phone_number;

        return $this;
    }

    public function getProfileHeight(): ?int
    {
        return $this->profile_height;
    }

    public function setProfileHeight(?int $profile_height): self
    {
        $this->profile_height = $profile_height;

        return $this;
    }

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

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

        return $this;
    }

    public function getProfileWeight(): ?int
    {
        return $this->profile_weight;
    }

    public function setProfileWeight(?int $profile_weight): self
    {
        $this->profile_weight = $profile_weight;

        return $this;
    }

    public function getProfileGender(): ?string
    {
        return $this->profile_gender;
    }

    public function setProfileGender(?string $profile_gender): self
    {
        $this->profile_gender = $profile_gender;

        return $this;
    }

    /**
     * @return Collection|Booking[]
     */
    public function getBookings(): Collection
    {
        return $this->bookings;
    }

    public function addBooking(Booking $booking): self
    {
        if (!$this->bookings->contains($booking)) {
            $this->bookings[] = $booking;
            $booking->setUser($this);
        }

        return $this;
    }

    public function removeBooking(Booking $booking): self
    {
        if ($this->bookings->contains($booking)) {
            $this->bookings->removeElement($booking);
            // set the owning side to null (unless already changed)
            if ($booking->getUser() === $this) {
                $booking->setUser(null);
            }
        }

        return $this;
    }

}

谢谢。

【问题讨论】:

  • 你能显示你的用户实体吗?
  • 是的,现在刚刚添加。谢谢。

标签: php symfony doctrine fosuserbundle symfony4


【解决方案1】:

@Franck Gamess 是对的,但您也可以摆脱 get。 如果你写{{ user.firstName }},twig 会自动将它关联到你的方法getFirstName()

我不知道你为什么用snake_case 编写你的属性,但你可以将它更改为camelCase 并通过它们的“真实”名称访问你的属性。

【讨论】:

    【解决方案2】:

    只需在你的树枝模板中使用:

    {{ user.getFirstName }}
    

    它工作正常。通常 Twig 在 PHP 层所做的事情非常简单:

    check if user is an array and first_name a valid element;
    if not, and if user is an object, check that first_name is a valid property;
    if not, and if user is an object, check that first_name is a valid method (even if first_name is the constructor - use __construct() instead);
    if not, and if user is an object, check that getfirst_name is a valid method;
    if not, and if user is an object, check that isfirst_name is a valid method;
    if not, and if user is an object, check that hasfirst_name is a valid method;
    if not, return a null value.
    

    Twig variables

    顺便说一句,您应该遵循Symfony Coding Standard 作为变量,因为twig 很难找到用snake_case 编写的属性的值。

    【讨论】:

    • 关于蛇盒的好建议,谢谢。等等,所以我应该在我的树枝中使用方法而不是变量?
    • 如果您使用 my_variable 之类的变量 yes,访问这样的值会更容易,因为您必须为 getter/setter 使用一个奇怪的名称才能访问 Twig 中的这个私有属性。或者使用 myVariable 之类的变量
    【解决方案3】:

    我认为您不应该在控制器中构造UserManagerInterface。另外,就像 Franck 所说,如果可以,请使用编码标准,这将在未来节省大量时间和挫败感!

    这是我在 Symfony 4 项目中使用的控制器:

    namespace App\Controller;
    
    use FOS\UserBundle\Model\UserInterface;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use Symfony\Component\Security\Core\Exception\AccessDeniedException;
    
    /**
     * @Route("/profile/bookings", name="profile_bookings")
     */
    public function bookings()
    {
        $user = $this->getUser();
        if (!is_object($user) || !$user instanceof UserInterface) {
            throw new AccessDeniedException('This user does not have access to this section.');
        }
    
        return $this->render('profile/bookings/bookings.html.twig', array(
            'user' => $user,
        ));
        }
    } 
    

    【讨论】:

    • 当你说他不应该在控制器中“构造” UserManager 时,我不同意你的看法。在许多情况下,在我的控制器上,我使用了一些管理器/服务的方法,因此我将其注入 __construct 并可以在整个控制器中访问它。
    • @Etshy,我认为从 symfony 3.3 开始你应该使用依赖注入。我错了吗?
    • 是的,这就是他对服务类型提示所做的事情。它将Service注入到Controller的构造函数中,这样就可以使用了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-14
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多