Reputation: 93
how can I solve this problem. An entity class aggregates an object. Its value should be stored in the database. I have the following entity:
<?php
class Price
{
private $_amount;
public function getAmount()
{
return $this->_amount;
}
public function setAmount($amount)
{
$this->_amount = $amount;
return $this;
}
}
/**
* Class Product
*
* @Entity
* @Table(name="product", options={"engine" = "NDBCLUSTER"})
*/
class Product
{
/**
* @Id
* @GeneratedValue
* @Column(name="id", type="integer")
* @var int
*/
private $_id;
/**
* @Column(name="price", type="decimal", precision=10, scale=2)
* @var Price
*/
private $_price;
}
?>
If I want to store a price in the database, how can I do that? This is obviously not working:
<?php
$price = new Price();
$price->setAmount(19.99);
$product = new Product();
$product->setPrice($price);
$em->persist($product);
$em->flush();
?>
Do I have to implement a new mapping type?
Upvotes: 2
Views: 1645
Reputation: 2954
you should create custom type in doctrine, like:
declare(strict_types = 1);
namespace App\Infrastructure\Persistence\Doctrine\Type;
use App\Domain\Model\OrderStatus;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\DBAL\Types\TextType;
final class StatusDoctrineType extends TextType
{
/**
* @return string
*/
public function getName()
{
return 'status_doctrine_type';
}
/**
* @param $value
* @param AbstractPlatform $platform
*
* @return OrderStatus
* @throws ConversionException
*/
public function convertToPhpValue($value, AbstractPlatform $platform): OrderStatus
{
if (null === $value) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return new OrderStatus($value);
}
/**
* @param mixed $value
* @param AbstractPlatform $platform
*
* @return null|string
* @throws ConversionException
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
{
if (null === $value) {
throw ConversionException::conversionFailed($value, $this->getName());
}
/** @var OrderStatus $value */
if (!is_a($value, OrderStatus::class)) {
throw ConversionException::conversionFailed($value, $this->getName());
}
return $value->currentStatus();
}
}
and in your entity something like this :
// ...
/**
* Order constructor.
*
* @param Route $route
* @param OrderId $orderId
* @param Distance $distance
*/
public function __construct(Route $route, OrderId $orderId, Distance $distance)
{
$this->route = $route;
$this->id = $orderId;
$this->distance = $distance->spacing();
// according to grasp Information Expert pattern.
$this->status = new OrderStatus(OrderStatus::UNASSIGN);
}
//...
/**
* @return OrderStatus
*/
public function status(): OrderStatus
{
return $this->status;
}
Upvotes: 0
Reputation: 4431
You can use doctrine Embeddables.
Declare your price as an embeddable like this:
/**
* @Embeddable
*/
class Price
{
/** @Column(type = "decimal") */
private $_amount;
...
and then use it:
class Product
{
/** @ORM\Embedded(class="Price") */
private $price;
...
Upvotes: 2