Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP中的OOP方法_Php_Oop - Fatal编程技术网

PHP中的OOP方法

PHP中的OOP方法,php,oop,Php,Oop,我用PHP程序化编程(这是一个词吗?)已经五年了,我决定尝试OOP方法,但遇到了一些概念/设计问题。假设程序中有一些模块,每个模块都可以列出、添加、编辑和删除实体。实体可以是..dunno、用户、客户、产品等 您将如何设计类来操作这些实体 我想到了两种可能性: 使用getUsersList、addUser、editUser、delUser等方法为每个实体创建类 这种方法似乎消耗了资源,因为在列表的脚本中,您只需要getUsersList和delUser方法,而在add user弹出脚本中,您只

我用PHP程序化编程(这是一个词吗?)已经五年了,我决定尝试OOP方法,但遇到了一些概念/设计问题。假设程序中有一些模块,每个模块都可以列出、添加、编辑和删除实体。实体可以是..dunno、用户、客户、产品等

您将如何设计类来操作这些实体

我想到了两种可能性:

  • 使用getUsersList、addUser、editUser、delUser等方法为每个实体创建类
    这种方法似乎消耗了资源,因为在列表的脚本中,您只需要getUsersList和delUser方法,而在add user弹出脚本中,您只需要addUser方法,在edit user弹出脚本中,您只需要editUser方法。所以,你必须实例化一个对象,并且只使用它的两个或一个方法
  • 创建通用类:为每个实体列出、添加、编辑、删除和扩展它们,这样一次只需实例化一个类(您真正需要的类)

提前感谢,

使用您的第一个方法,即使用方法创建可重用对象。这不是浪费时间,因为您只需编写一次代码

class User {
    function __construct() { /* Constructor code */ }
    function load($id) { ... }
    function save() { ... }
    function delete() { ... }
}
我将创建一个定义列表、添加、编辑和删除方法的工具。这将为您提供一个类“模板”。如果您的类(用户、客户机、产品等)实现了此接口,则必须在这些类中定义接口中的方法

这将为您提供一个类似的“API”,以访问实现接口的每个类的所有功能。由于列出的每个对象都包含不同的数据,因此方法的详细信息将不同,因此是分开的,但接口将是相同的

旁白:

你在方法列表中包含的“列表”让我有点担心。这似乎意味着您将对象视为用户、客户机、产品等的集合,其中最有可能存在表示单个用户的用户类、表示单个客户机的客户机类等

另一方面,“list”可以作为一个静态方法处理——一个不需要类实例就可以调用的方法

$bob = new User('bob');
$bob->add(); // Adds bob to the database
$fred = new User('fred');
$fred->add(); // Adds fred to the database

$users = User::list(); // Gives an array of all the users in the database

无论如何,这就是我处理事情的方式。

您需要创建一个坚实的体系结构和框架来管理数据模型。这并不容易,而且随着数据模型的增长,这只会变得更加复杂。我强烈建议使用PHP框架(Symfony、CakePHP等),或者至少使用ORM(条令、推进等)

如果您仍然想自己开发,我将从一个类似于下面的架构开始

您需要一个用于单个记录操作(如保存、删除等)的
DbRecord
类。这个<代码> dBeords< /Cord>类将被特定的实体扩展,并为基本实体操作提供基础。
class DbRecord {
    public function save() {
        // save logic (create or update)
    }

    public function delete() {
        // delete logic
    }

    // other record methods
}

class User extends DbRecord {
    private $name;
    private $email;

    public function setName($name_) {
        $this->name = $name_;
    }

    public function setEmail($email_) {
        $this->email = $email_;
    }
}
从中,您可以执行单个记录操作:

$user = new User();
$user->setName('jim');
$user->setEmail('jim@domain.com');

$user->save();
$userTable = new UserTable();
$users = $userTable->readAll();

foreach ($users as $user) {
    // etc
}
您现在需要一个
DbTable
类,用于表上的批量操作(如读取所有实体等)

从中,您可以执行批量/表格操作:

$user = new User();
$user->setName('jim');
$user->setEmail('jim@domain.com');

$user->save();
$userTable = new UserTable();
$users = $userTable->readAll();

foreach ($users as $user) {
    // etc
}
代码体系结构是网站正确扩展的关键。将数据模型划分为适当的类和层次结构非常重要

同样,随着网站的发展,手动管理数据模型会变得非常复杂。这时,您将真正看到PHP框架或ORM的好处


注意:
DbRecord
DbTable
是任意名称-使用您喜欢的w/e名称。

您使用“通用类”(也称为基类,或抽象类,以防在使用它们之前,它们的行为需要子类的补充)

OOP方法将把所有实体共有的行为放在基类中

如果您使用类似于ActiveRecord的东西,那么您已经有了用于创建更新删除操作的通用(抽象)接口。利用这一点,让基类只在那些接口方法上操作。他们不需要知道他们正在更新产品或用户,他们只需要知道他们可以对实体调用update()方法

但是,即使不使用AR框架等功能非常强大的东西(如果您对非常灵活的ORM感兴趣,请查看条令…),您也可以使用接口来抽象行为

让我给你一个更详细的例子


/**
 * Interface for all entities to use
 */
interface Entity {
    static function newEntity();
    static function fetch($id);
    function save();
    function setProperties(array $properties);
    function delete();
}


/**
 * A concrete product entity which implements the interface
 */
class Product implements Entity {
    public $productId;
    public $name;
    public $price;
    public $description;

    /**
     * Factory method to create a new Product
     *
     * @param integer $id Optional, if you have auto-increment keys you don't need to set it
     * @return Product
     */
    public static function newEntity($id=NULL) {
        $product = new Product();
        $product->productId = $id;
        return $product;
    }

    /**
     * Factory method to fetch an existing entity from the database
     *
     * @param integer $id
     * @return Product
     */
    public static function fetch($id) {
        // make select with supplied id
        // let $row be resultset
        if (!$row) {
            return NULL; // you might devise different strategies for handling not-found cases; in this case you need to check if fetch returned NULL
        }

        $product = new Product();
        $product->productId = $id;
        $product->name = $row['name'];
        $product->price = $row['price'];
        $product->description = $row['description'];
        return $product;
    }

    /**
     * Update properties from a propreties array
     * @param array $properties
     * @return void
     */
    public function setProperties(array $properties) {
        $this->name = $properties['name'];
        $this->price = $properties['price'];
        $this->description = $properties['description'];
    }

    public function save() {
        // save current product properties to database
    }

    public function delete() {
        // delete product with $this->productId from database
    }
}

/**
 * An abstract CRUD controller for entities
 */
abstract class EntityCrudController {
    protected $entityClass = 'UNDEFINED'; // Override this property in child controllers to define the entity class name
    protected $editTemplate = NULL; // Override this to set an edit template for the specific entity
    protected $templateEngine; // Pseudo-Templating engine for this example

    /**
     *  Display the edit form for this entity
     * @param integer $entityId
     * @return string
     */
    public function editAction($entityId) {
        // Fetch entity - this is not the most clean way to fetch, you should probably consider building a factory that encapsulates this.
        $entity = call_user_func($this->entityClass, 'fetch', $entityId);

        // Assign entity to your edit template, in this example I'm assuming we're using a template engine similar to Smarty
        // You can generate the HTML output in any other way you might like to use.
        $this->templateEngine->setTemplate($this->editTemplate);
        $this->templateEngine->assign('entity', $entity);
        return $this->template->render();
    }

    /**
     * Update an existing entity
     *
     * @param integer $entityId
     * @param array $postArray
     * @return string
     */
    public function updateAction($entityId, array $formArray) {
        // Be sure to validate form data first here, if there are errors call $this->editAction() instead and be sure to set some error information
        $entity = call_user_func($this->entityClass, 'fetch', $entityId);
        $entity->setProperties($formArray);
        $entity->save();

        // Again, using our imaginary templating engine to display...
        $this->templateEngine->setTemplate($this->editTemplate);
        $this->templateEngine->assign('entity', $entity);
        $this->templateEngine->assign('message', 'Saved successfully!');
        return $this->template->render();
    }

    // Devise similar generic methods for newAction/insertAction here
}


/**
 * Concrete controller class for products
 * This controller doesn't do much more than extend the abstract controller and override the 2 relevant properties.
 */
class ProductCrudController extends EntityCrudController {
    protected $entityClass = 'Product';
    protected $editTemplate = 'editProduct.tpl';
}

// Usage example:

// Display edit form:
$controller = new ProductCrudController();
$htmlOutput = $controller->editAction(1);

// Save product:
$htmlOutput = $controller->updateAction(1, array('name' => 'Test Product', 'price' => '9.99', 'description' => 'This is a test product'));
当然,还有很多地方需要改进。。e、 g.您通常不希望每次对实体调用fetch()时都进行查询,而是只查询一次并将结果对象存储在中,这也确保了数据的完整性


希望这会有所帮助,比我预想的要多一些,但我认为,如果你试图解决这个问题而不在这个问题上抛出框架,这是值得称赞的:)

是的,但这不是浪费资源吗?实例化整个对象并在只需要一半或更少的对象时将其保留在内存中?尝试将其扩展到更大的范围。@Catalin:OOP默认情况下比过程代码更庞大。看看ORM,它们的效率非常低。但是,它加快了开发速度并使代码更干净。是的,我也这么认为,但仔细想想……您可以为函数创建一个命名规则并按程序工作。创建一个user.utils.php,其中包含诸如user_load()之类的函数;用户_save();用户_delete()@卡塔林:当然可以,但是那样他们就不会在同一个物体上互动了。您必须在函数之间传递第二个对象。用户和用户应该是独立的实体,就像您可能希望执行的那样
User->delete()
,但您也可能希望
Users->delete()
删除多个用户。。。正如您所说,
用户
应该是一个集合,应该是可编辑的,并且应该具有
length()
属性..而不是单个
用户