Mais recentemente, tenho trabalhado com o Symfony (há pouco mais de um ano) e em todos os projetos em que tive a chance de trabalhar - as entidades sempre foram criadas de tal forma que continham apenas campos particulares e criadores / criadores nus para eles.
Os artigos discutirĂŁo e exemplos de por que essa abordagem Ă© perigosa, a saber: viola nosso bom e velho encapsulamento, provoca a escrita de cĂłdigos com bugs e aumenta a complexidade do sistema.
O artigo omitirá o tópico de setters em vários construtores e o tópico de injeção de dependência por meio de setters (direi apenas que não aprovamos). Não haverá nada sobre tópicos complexos como DDD, Rich Model, sobre acoplamento / coesão e outras palavras inteligentes - apenas fale sobre encapsulamento. Bem-vindo ao gato.
Vá para o código. Vamos omitir por um segundo a indicação typehint e type type e pensar em como, ao trabalhar com um objeto, o código a seguir difere do ponto de vista utilitário:
$userName = $user->name;
$user->name = $newUserName;
:
$userName = $user->getName();
$user->setName($newUserName);
, , .
C . — , .
? , , . , , , .
«» , :
class Order
{
     private const STATUS_OPEN = 'open';
     private const STATUS_DELIVERED = 'delivered';
     private ProductCollection $products;
     private string $deliveryStatus;
     private ?DateTime $deliveryDate = null;
     public function deliver()
     {
          if ($this->isDelivered()) {
               throw new OrderDomainException('Order already delivered.');
          }
          $this->deliveryDate = new DateTime();
          $this->deliveryStatus = self::STATUS_DELIVERED;
     }
     private function isDelivered(): bool
     {
         return $this->deliveryStatus === self::STATUS_DELIVERED;
     }
     //  
}
« » - ? ? — ? . — , , . (cohesion).
:
class Order
{
    private const STATUS_OPEN = 'open';
    private const STATUS_DELIVERED = 'delivered';
    private ProductCollection $products;
    private string $deliveryStatus;
    private ?DateTime $deliveryDate = null;
    public function getDeliveryStatus(): string
    {
        return $this->deliveryStatus;
    }
    public function setDeliveryStatus(string $deliveryStatus): void
    {
        $this->deliveryStatus = $deliveryStatus;
    }
    public function getDeliveryDate(): ?DateTime
    {
        return $this->deliveryDate;
    }
    public function setDeliveryDate(?DateTime $deliveryDate): void
    {
        $this->deliveryDate = $deliveryDate;
    }
    public function getProducts(): ProductCollection
    {
        return $this->products;
    }
    public function setProducts(ProductCollection $products): void
    {
        $this->products = $products;
    }
}
? ( ). — , , , , ? , ? . — , — . . . , — ?
, 
. — , .
— , , , , , .
. :
/**
 * @ORM\Entity
 */
class Project
{
    /**
     * @var Id
     * @ORM\GeneratedValue()
     * @ORM\Id
     */
    private $id;
    /**
     * @var string
     * @ORM\Column(type="string")
     */
    private $name;
    /**
     * @var string
     * @ORM\Column(type="string", nullable=false)
     */
    private $status;
    /**
     * @var int
     * @ORM\Column(type="integer", nullable=true)
     */
    private $sort;
    /**
     * @var User
     * @ORM\Column(type="user_type", nullable=false)
     */
    private $user;
    /**
     * @var Department
     * @ORM\OneToMany(targetEntity="Department")
     */
    private $department;
    /**
     * @var string
     * @ORM\Column(type="string", nullable=true)
     */
    private $membership;
    
    public function getId(): Id
    {
        return $this->id;
    }
    
    public function getName(): string
    {
        return $this->name;
    }
    
    public function setName(string $name): Project
    {
        $this->name = $name;
        return $this;
    }
    
    public function getStatus(): string
    {
        return $this->status;
    }
    
    public function setStatus(string $status): Project
    {
        $this->status = $status;
        return $this;
    }
    
    public function getSort(): int
    {
        return $this->sort;
    }
    
    public function setSort(int $sort): Project
    {
        $this->sort = $sort;
        return $this;
    }
    
    public function getUser(): User
    {
        return $this->user;
    }
    
    public function setUser(User $user): Project
    {
        $this->user = $user;
        return $this;
    }
    
    public function getDepartment(): Department
    {
        return $this->department;
    }
    
    public function setDepartment(Department $department): Project
    {
        $this->department = $department;
        return $this;
    }
    
    public function getMembership(): string
    {
        return $this->membership;
    }
    
    public function setMembership(string $membership): Project
    {
        $this->membership = $membership;
        return $this;
    }
}
not nullable — ( false). , — not nullable , ? :)
, — ( ). .
, Doctrine ( ) , Reflection API. Marco Pivetta , : 
ocramius.imtqy.com/blog/doctrine-orm-optimization-hydration. .
, 
, ( DTO, ..)., , - «» . , , .
-. ID, — :$order = $this->orderRepository->find($orderId);
if ($order === null) {
     throw new OrderException('Order not found.');
}
if ($order->getStatus() === Order::STATUS_ACTIVE 
    && $order->getDeliveryDate() <= $date
) {
    $this->orderDeliveryService->handle($order);
}
— , :$order = $this->orderRepository->find($orderId);
$cityFreeLimit = $this->cityOrderService->getCityFreeLimit($cityName);
if ($order->getCity() === $cityName 
    && $order->getTotalPrice() > $cityFreeLimit
) {
     $delivery = 0;
     $this->orderDeliveryService->deliveryOrder($order, $delivery);
     
     return;
}
//         
, - .
, - . , , , . , , , . «» «».
/ , , , , « » , — , , .
— Symfony (DAO), /. — - ( , ).
, — :)
. — .