类继承和与另一个类的组合


PHP - Classes inheritance and combining with another class

我想写一些继承3层结构中的类的东西。这样的抽象例子。

couriers_list -> Courier -> courier_name

class couriers_list {
   // I'm searches courier_name of the database and reference to the class of courier_name found in database
    public function show_courier() {
      return $this->xxx();
   }
}
class courier extends couriers_list {
   // Function for the courier
   // Probably it would interface or abstraction
}
class courier_name extends courier {
    // Methods of accurately courier eg. Calculation associated with the delivery
    // Here each courier would separate file php eg. ups.php
   public function xxx() {
      return 'xxx';
   }
}
$k = new couriers_list();
echo $k->xxx();

我不认为我可以扩展courier到courier_list,因为我没有访问方法的后代。从外部看,我只想引用类couriers_list,她必须从数据库中获取信息并获取courier_name产生的方法。

如何把这个问题放到组织对象上?

你的类courier应该是一个接口,因为它用来定义你的courier应该如何使用

interface CourrierInterface
{
    const CLASS_NAME = __CLASS__;
    public function getName();
    public function getPrices();
    public function XXX();
    public function calculateDelivery($from, $to);
    /** these are just example add here all the method that define a courier */
}

那么对于你拥有的每个信使,你应该实现de CourrierInterface

class UpsCourrier implements CourrierInterface
{
    private $name;
    public function getName()
    {
        return $this->name;
    }
    public function setName($name)
    {
        $this->name = $name;
    }
    public function XXX()
    {
        // do something
    }
}

我不认为CourrierList应该知道数据库,但只需要包含所有的快递对象你有。这里我使用项目

https://github.com/yvoyer/collection

为了管理集合(TypedCollection类),它允许控制你想在集合中使用的类的类型(这里是courrierInterface),但是如果你想让它更简单,你可以使用数组。

我创建了两个XXX方法,一个用于特定的快递员(因为它是一个列表),另一个用于应用于所有列表。我不知道你需要什么,所以拿走你需要的

class CourrierList
{
    /**
     * TypedCollection
     */
    private $courrierList;
    public function __construct()
    {
        // i prefer to use a collection class that valid my type instead of an array, your choice!
        $this->courrierList = new TypedCollection("CourrierInterface");
    }
    public function addCourrier(CourrierInterface $courrier)
    {
        $this->courrierList->add($courrier);
    }
    public function removeCourrier(CourrierInterface $courrier)
    {
        $this->courrierList->removeElement($courrier);
    }
    protected function getCourrierByName($courrierName)
    {
        $closure = function (CourrierInterface $courrier) use ($courrierName) {
            return $courrier->getName() == $courrierName;
        };
        return $this->courrierList->filter($closure)->toArray();
    }
    // since its a list, you must be able to select your courrier to execute the XXX() method
    public function XXXByName($name)
    {
        $courrier = $this->getCourrierByName($name);
        $courrier->XXX();
    }
    // if you prefer to apply to all your courrierList just do
    public function XXX()
    {
        foreach ($this->courrierList as $courrier) {
            $courrier->XXX();
        }
    }
}

因为我不认为CourrierList应该知道数据库,你可以创建一个工厂,在你的数据库中获取数据,并创建所有的快递。这里dbConnection是你的选择,pdo等等…我只是做了一个例子,找到一个好的方法来查询。

class CourrierListFactory
{
    private $dbConnection;
    public function __construct(DbConnection $connection)
    {
        $this->dbConnection = $connection;
    }
    public function createCourrierList()
    {
        $results = $this->dbConnection->query(".....")->getResults();
        $courrierList = new CourrierList();
        foreach ($results as $result) {
            $courrier = null;
            switch ($result['name']) {
                case 'ups':
                    $courrier = new UpsCourrier();
                    break;
                case 'fedex':
                    $courrier = new FedexCourrier();
                    break;
                /** and so on ... */
                default:
                    // maybe throw exception if courier is not handle
            }
            $courrier->setName("....");
            /** prepare your object here */
            // add the courrier to the list
            $courrierList->addCourrier($courrier);
        }
        return $courrierList;
    }
}

最后是如何使用所有这些,首先创建一个dbCOnnection,然后构建你的列表,然后你可以访问

$dbConnection = new DbConnection();
// the factory allows you to separate the database from the List class and may be to generate
// your list in an other way later (using apis, etc...)
$factory = new CourrierListFactory($dbConnection);
$courrierList = $factory->createCourrierList();
$courrierList->XXX(); // apply to all
$courrierList->XXXByName("ups"); // apply just to ups courrier