Php分离关注点&依赖注入

时间:2013-04-06 01:15:43

标签: php oop class dependencies code-injection

基于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.....

2 个答案:

答案 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对象。