我正在探索一个框架,其中我正在编写一个服务。服务本身有越来越多的方法(这不是那么糟糕,因为它是一个服务)。不安来自服务用来将数据库数据转换为域对象的映射器,因为该类正在增长到令我感到不舒服的地方(每个Service方法至少需要2个Mapper方法和一个属性(一个用于获取数据,一个用于映射)它们和SQL的属性。)
所以我的问题是,如果建议为每个Service方法制作一个mapper类(例如使用Factory)?
所以,这是有问题的课程:
<?php
import('sites::foo::biz', 'Held');
import('sites::foo::biz', 'Attribut');
import('sites::foo::biz', 'Generierung');
import('sites::foo::biz', 'Talent');
import('sites::foo::biz', 'Kampftalent');
class HeldenblattMapper extends APFObject
{
const SQL_GET_HELD = <<<SQL
SELECT
name,
geschlecht,
groesse,
gewicht,
tsatag,
haare,
augen,
aussehen,
stand,
titel,
SO,
hintergrund,
AP_frei AS freieAP,
AP_gesamt AS alleAP
FROM
helden
WHERE
id = ?
;
SQL;
const SQL_GET_ATTR = <<<SQL
SELECT
Attribut,
Wert
FROM
held_attribute
WHERE
HeldenID = ?
;
SQL;
const SQL_GET_TALENTE = <<<SQL
SELECT
Talent,
Probe,
Attribute,
Wert,
Kategorie
FROM
held_talente
WHERE
HeldenID = ? AND Kategorie = ?
ORDER BY
Kategorie, Talent
;
SQL;
const SQL_GET_RKP = <<<SQL
SELECT
RKP,
Typ
FROM
held_rkp
WHERE
HeldenID = ? AND pri_sec = ?
;
SQL;
const SQL_GET_KAMPF = <<<SQL
SELECT
Talent,
Spezialisierung,
AT_PA,
Wert,
Kategorie,
Attacke(HeldenID) AS AT,
Parade(HeldenID) AS PA,
Fernkampf(HeldenID) AS FK
FROM
held_kampftalente
WHERE
HeldenID = ? AND Kategorie = ?
ORDER BY
Kategorie DESC, Talent ASC
;
SQL;
public function getHeld($id)
{
$PDOHeld = $this->getPDOById(self::SQL_GET_HELD, $id);
return $this->mapPDOHeld2DomainObject($PDOHeld);
}
public function getAttributeByHeld($id)
{
$PDOAttr = $this->getPDOById(self::SQL_GET_ATTR, $id);
return $this->mapPDOAttribute2DomainObjects($PDOAttr);
}
public function getRKPByHeld($id)
{
$sql = 'SELECT RKP FROM held_rkp WHERE HeldenID = ? AND Typ = ? ORDER BY pri_sec ASC;';
$rkp = $this->getPDOConnection()->prepareStatement($sql);
$rkp->bindParam(1, $id, PDO::PARAM_INT);
$rkp->bindParam(2, $typ, PDO::PARAM_STR);
$arr = array();
$types = array('Rasse', 'Kultur', 'Profession');
foreach ($types as $typ)
{
$rkp->execute();
$arr[$typ] = $this->mapPDORKP2DomainObject($rkp);
}
return $arr;
}
public function getTalenteByHeld($id)
{
$sql = 'SELECT DISTINCT Kategorie FROM held_talente WHERE HeldenID = ?';
$PDOKat = $this->getPDOById($sql, $id);
$PDOKat->setFetchMode(PDO::FETCH_COLUMN, 0);
$PDOTal = $this->getPDOConnection()->prepareStatement(self::SQL_GET_TALENTE);
$PDOTal->bindParam(1, $id, PDO::PARAM_INT);
$PDOTal->bindParam(2, $kat, PDO::PARAM_STR);
$arr = array();
foreach ($PDOKat as $kat)
{
$PDOTal->execute();
$arr[$kat] = $this->mapPDOTalente2DomainObjects($PDOTal);
}
return $arr;
}
public function getKampftalenteByHeld($id)
{
$sql = 'SELECT DISTINCT Kategorie FROM held_kampftalente WHERE HeldenID = ?';
$PDOKat = $this->getPDOById($sql, $id);
$PDOKat->setFetchMode(PDO::FETCH_COLUMN, 0);
$PDOTal = $this->getPDOConnection()->prepareStatement(self::SQL_GET_KAMPF);
$PDOTal->bindParam(1, $id, PDO::PARAM_INT);
$PDOTal->bindParam(2, $kat, PDO::PARAM_STR);
$arr = array();
foreach ($PDOKat as $kat)
{
$PDOTal->execute();
$arr[$kat] = $this->mapPDOKampf2DomainObjects($PDOTal);
}
return $arr;
}
private function mapPDOHeld2DomainObject(PDOStatement $ps)
{
$row = $ps->fetch(PDO::FETCH_ASSOC);
if (!$row)
{
throw new DomainException('No Character data found.');
}
$held = new Held();
$held->setName($row['name']);
$held->setGeschlecht($row['geschlecht']);
$held->setAlleAP($row['alleAP']);
$held->setFreieAP($row['freieAP']);
return $held;
}
private function mapPDOAttribute2DomainObjects(PDOStatement $ps)
{
$ps->setFetchMode(PDO::FETCH_ASSOC);
$arr = array();
foreach ($ps as $row)
{
$attribut = new Attribut();
$attribut->setName($row['Attribut']);
$attribut->setWert($row['Wert']);
$arr[] = $attribut;
}
return $arr;
}
private function mapPDORKP2DomainObject(PDOStatement $ps)
{
$rkp = new Generierung();
$rkp->setRKPName($ps->fetchColumn());
$mod = $ps->fetchColumn();
if ($mod)
{
$rkp->setModifikation($mod);
}
return $rkp;
}
private function mapPDOTalente2DomainObjects(PDOStatement $ps)
{
$ps->setFetchMode(PDO::FETCH_ASSOC);
$arr = array();
foreach ($ps as $row)
{
$talent = new Talent();
$talent->setName($row['Talent']);
$talent->setWert($row['Wert']);
$talent->setAttribute($row['Attribute']);
$talent->setProbe($row['Probe']);
$talent->setTyp($row['Kategorie']);
$arr[] = $talent;
}
return $arr;
}
private function mapPDOKampf2DomainObjects(PDOStatement $ps)
{
$ps->setFetchMode(PDO::FETCH_ASSOC);
$arr = array();
foreach ($ps as $row)
{
$talent = new Kampftalent();
$talent->setName($row['Talent']);
$talent->setWert($row['Wert']);
$talent->setSpezialisierung($row['Spezialisierung']);
$talent->setAtPaFromDBValue($row['AT_PA'], '_');
if ('Nahkampf' == $row['Kategorie'])
{
$at = (int) $row['AT'] + $talent->getAT();
$talent->setAT($at);
$pa = (int) $row['PA'] + $talent->getPA();
$talent->setPA($pa);
}
elseif ('Fernkampf' == $row['Kategorie'])
{
$fk = (int) $row['FK'] + $talent->getAT();
$talent->setAT($fk);
}
$arr[] = $talent;
}
return $arr;
}
private function getPDOConnection()
{
$cm = $this->getServiceObject('core::database', 'ConnectionManager');
return $cm->getConnection('PDO');
}
private function getPDOById($sql, $id)
{
$ps = $this->getPDOConnection()->prepareStatement($sql);
$ps->bindValue(1, (int) $id, PDO::PARAM_INT);
$ps->execute();
return $ps;
}
}
相关服务
<?php
class HeldenblattService extends APFObject
{
private $id;
public function init($param)
{
if (!is_int($param))
{
throw new InvalidArgumentException('Cannot create a Character Sheet without a valid Character ID.');
}
$this->id = $param;
}
public function getHeld()
{
$mapper = $this->getMapper();
return $mapper->getHeld($this->id);
}
public function heldGetRKP()
{
$mapper = $this->getMapper();
return $mapper->getRKPByHeld($this->id);
}
public function heldGetAttribute()
{
$mapper = $this->getMapper();
return $mapper->getAttributeByHeld($this->id);
}
public function heldGetTalente()
{
$mapper = $this->getMapper();
return $mapper->getTalenteByHeld($this->id);
}
public function heldGetKampf()
{
$mapper = $this->getMapper();
return $mapper->getKampftalenteByHeld($this->id);
}
private function getMapper()
{
return $this->getDIServiceObject(
'sites::foo::data',
'HeldenblattMapper'
);
}
}
看起来他们可能会这样做,但一个是商务类,另一个是模型类(关注点分离)。
答案 0 :(得分:0)
我宁愿选择具有多个Mapper的单个服务,因为Domain-DB映射的实现需要更多代码,只需加载服务的加载/保存调用。
如果服务正在增长(此时不多),我可以考虑为每个部分/主题制作服务映射器对。否则mapper类将轻松扩展500行。