基于stackoverflow上的一些好建议,我需要更多的指导。我被告知,分离关注对于保持代码整洁和模块化非常重要,我发现它是。
我的问题是:根据我读到的关于SOC的内容,我开发了2个类。供应商类和Csv类。供应商仅从数据库中检索有关我的不同供应商的数据。 Csv类从正在导入的csv文件中检索数据,我需要解析它的所有信息,最终目标是将数据插入到我的Supplier表中。为了实现将csv数据插入数据库的目标,我需要使用两个类中的方法。我是否创建了一个名为ImportSuppliersCsv的第三类,或者将导入函数创建为Suppliers类的方法更有意义吗?
缩短以节省空间,我的课程就像这样:
class Suppliers
{
public $db;
public $inv;
public $table;
public function __construct (PDO $db)
{
$this->db = $db;
$this->inv = 'lightsnh_inventory';
$this->table = 'suppliers';
}
public function getSuppliers()
{
$sql = 'SELECT * FROM `'.$this->inv.'`.`'.$this->table.'`';
$statement = $this->db->query($sql);
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
public function getActiveSuppliers()
{
$suppliers = $this->getSuppliers();
$active = array();
foreach($suppliers as $supplier) {
if($supplier['exclude'] == 0)
$active[] = $supplier;
}
return $active;
}
public function getDistributors()
{
$suppliers = $this->getSuppliers();
$distributors = array();
foreach($suppliers as $supplier) {
if($supplier['type'] == 1)
$distributors[] = $supplier;
}
return $distributors;
}
class Csv
{
public $form;
public function __construct($form_name)
{
$this->form = $form_name;
}
public function getFile()
{
if(isset($_POST[$this->form.'-upload-submit'])) {
return $_FILES[$this->form.'-file'];
}
}
public function getName()
{
$file = $this->getFile();
return $file['name'];
}
public function getExtension()
{
return end(explode('.',$this->getName()));
}
public function getType()
{
$file = $this->getFile();
return $file['type'];
} etc.....
答案 0 :(得分:0)
都不是。 OOP / SoC / DI等不是目的,它们是一种手段。 SoC的目的是模块化架构,使维护更容易,尽管分离问题总是通过模糊它来扩大问题。 我发现在PHP中提出一个好的设计的最好方法是首先让它工作,然后重构。您也可以先在想象中做到这一点,以节省一些时间。以您认为最好的方式组织它。毕竟,这个想法是为了维护代码能够轻松找到自己的方式,因为他们以这种方式组织它。简而言之,要注意过度工程。
在你的例子中,如果它只在一个地方使用,我就不会费心去做一些东西了。作为一个例子:通常一个可以将CSV记录导入数据库的应用程序,也有一个用于编辑这些行的表单,所以我假设有一个' save'在Suppliers类中的函数,因为它已经抽象查询(严重 - 没有缓存,没有WHERE子句,SQL注入等)。现在导入CSV文件的问题是以有序的方式呈现数据到这个“保存”的问题。功能
现在,将CSV文件导入数据库的基本代码本身就像这样简单:
$data = array_map( 'str_getcsv', explode("\n", file_get_contents( $filename ) ) );
$columns = array_shift( $data );
$sth = $db->prepareStatement( "INSERT INTO suppliers( " . implode( ',', $columns )
. ") VALUES ( " . substr(str_repeat(",?",count($columns)),1) . ")"
);
foreach ( $data as $line )
$sth->execute( $line );
通常它不是那么理想 - 但这本质上是核心功能。它只有4个语句,有四个问题:解析CSV,映射字段,更新数据库以及效率/一致性(使用预准备语句)。
OOP仍然依赖于函数式编程 - 按功能组织。以上内容可以保留为脚本,由cron作业或网页调用。它可以放在一个函数' import_csv'被这些任务重用。但把它放在一个班级是有点矫枉过正。 SoC还利用了外墙或接口。函数就是这样,如果需要,可以很容易地分组成一个类。您只需要一个函数import_csv($ filename,$ profile)。 $ profile将指示表(或多个表),列映射等。通过将它们分开,您可以创建一个通用的CSV到DB映射编辑器 - 或者至少支持通过更改配置将任何CSV文件导入任何表。如果您对所有内容进行了分类,那么您最终将为每个CSV文件编写一个类,您将不得不导入。你当然可以创建一个CSVImporter类,但这只有在有其他Importer类时才有用 - 毕竟,使一个类是抽象功能,你不能只从一个例子中抽象出来。
相反,想象一下通用导入器,无论数据如何。专注于功能,因为这就是代码。这是一种更好的方法,因为您的代码不依赖于数据库结构 - 您已经将其抽象化了(通过使用公共接口扩展Table基类,因此您可以使用$ table-> save())。你不抽象CSV(它不值得,如第一行代码所示),但是映射。
这不是您所期望的答案,但我确定您不希望答案是您给出的答案,因为您将其作为一个问题提出。
答案 1 :(得分:-1)
您不需要新类来从CSV插入新供应商。您只需添加一个新方法并将Csv对象传递给它。这样,所有与供应商相关的活动都将封装在一个类中。
或者,除了CSV之外,如果您计划拥有其他信息来源,则可以使供应商方法接受已解析的信息,而不是CSV对象。