I have the following structure in the database.
I have an abstract entity (exchange)
#[MappedSuperclass]
abstract class AbstractExchange implements ExchangeInterface
{
protected HttpClientInterface $httpClient;
#[Id]
#[Column('name')]
protected string $exchangeName;
#[JoinTable(name: 'currency_pairs')]
#[JoinColumn(name: 'exchange_name', referencedColumnName: 'name')]
#[ManyToMany( targetEntity: CurrencyPair::class, cascade: ['persist', 'remove'])]
protected Collection $currencyPairs;
#[JoinTable(name: 'currency_exchange')]
#[JoinColumn(name: 'exchange_name', referencedColumnName: 'name')]
#[InverseJoinColumn(name: 'currency_name', referencedColumnName: "name")]
#[ManyToMany(targetEntity: Currency::class)]
protected Collection $currencies;
public function __construct()
{
$this->httpClient = new CurlHttpClient();
$this->currencyPairs = new ArrayCollection();
$this->currencies = new ArrayCollection();
}
}
i have a specific exchange class
#[Entity]
#[Table(name: 'exchanges')]
final class ConcreateExchange extends AbstractExchange{
public function parseCurrencyPairs(): void
{
$responseArr = $this
->httpClient
->request('GET', $this->baseUrl)
->toArray();
foreach ($responseArr['symbols'] as $symbol) {
$baseCurrency = new Currency($symbol['baseAsset']);
$quoteCurrency = new Currency($symbol['quoteAsset']);
$currencyPair = new CurrencyPair(
$baseCurrency,
$quoteCurrency,
$this->exchangeName
);
$this->currencyPairs->add($currencyPair);
}
return;
}
}
I have CurrencyPair entity
#[Entity]
#[Table(name: 'currency_pairs')]
final class CurrencyPair
{
#[Id]
#[Column(name: 'base_currency_name')]
private Currency $baseCurrency;
#[Id]
#[Column(name: 'quote_currency_name')]
private Currency $quoteCurrency;
#[Id]
#[Column(name: 'exchange_name')]
private string $exchangeName;
public function __construct(
Currency $baseCurrency,
Currency $quoteCurrency,
string $exchangeName
) {
$this->baseCurrency = $baseCurrency;
$this->quoteCurrency = $quoteCurrency;
$this->exchangeName = $exchangeName;
}
}
i have Currency Entity
#[Entity]
#[Table(name: "currencies",)]
final class Currency
{
#[Id]
#[Column(name: 'name')]
private string $ticker;
public function __construct(string $ticker)
{
$this->ticker = strtoupper($ticker);
}
public function __toString(): string
{
return $this->ticker;
}
}
the fact is that I may have many exchanges, but different exchanges may have the same currencies (for example, USD or RUB) different exchanges can have different currency pairs which is related to common currencies, i am trying to design DDD but cant save with doctrine 2 in symfony, first I get an error:
An exception occurred while executing a query: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`arbitrage`.`currency_pairs`, CONSTRAINT `FK_788B4E8F5C2F08CB` FOREIGN KEY (`base_currency_name`) REFERENCES `currencies` (`name`))
this means that doctrine tries to save the currency_pair first and not the currency (which is wrong), I need Doctrine to save the Currency first. Then I get an error: 1062 Duplicate entry for key 'PRIMARY' such currency pairs, the currencies of which are already in the database. For example. first, the currency from the usd/rub ticker (usd and rub) is inserted into the database, then we get the usd/eur pair and get an error. currency usd already exists in the database but this is not correct either, because there is only one currency, but currency_pair exists separately. However, CurrencyPair as an entity must contain 2 currencies (based on DDD).
how to make doctrine work within DDD framework (and is it possible?)
public function parseCurrencyPairs(): void
{
$responseArr = $this
->httpClient
->request('GET', $this->baseUrl)
->toArray();
foreach ($responseArr['symbols'] as $symbol) {
$baseCurrency = new Currency($symbol['baseAsset']);
$quoteCurrency = new Currency($symbol['quoteAsset']);
$currencyPair = new CurrencyPair(
$baseCurrency,
$quoteCurrency,
$this->exchangeName
);
$this->currencyPairs->add($currencyPair);
}
return;
}
This code is correct from the point of view of DDD, but tell me how to remove doctrine errors so that it works? ps let's assume that this code is run 1 time concreateExchange each time put if run this code:
public function parseExchanges(): void
{
foreach ($this->exchanges as $exchange){
$exchange->parseCurrencyPairs();
$this->entityManager->persist($exchange);
}
$this->entityManager->flush();
}
source https://stackoverflow.com/questions/76526307/how-to-implement-the-preservation-of-nested-identical-entities-in-doctrine

No comments:
Post a Comment