PHP:OOP设计和如何跨类似类重用方法
我熟悉扩展父类,但是我不知道如何创建一个从父类继承工作方法的类,这个类可能会根据它所在的类而变化。例如,对于存储日志元数据的数据库表,我有一个名为Log_Metadata的模型类。我还有一个名为Station_Metadata的类,用于存储站点元数据的表。除了站点或日志ID的控制字段外,表模式类似,但模式的其余部分相同,因为每个元数据行都有一个ID、一个meta_键列和一个meta_值列PHP:OOP设计和如何跨类似类重用方法,php,oop,interface,abstract-class,Php,Oop,Interface,Abstract Class,我熟悉扩展父类,但是我不知道如何创建一个从父类继承工作方法的类,这个类可能会根据它所在的类而变化。例如,对于存储日志元数据的数据库表,我有一个名为Log_Metadata的模型类。我还有一个名为Station_Metadata的类,用于存储站点元数据的表。除了站点或日志ID的控制字段外,表模式类似,但模式的其余部分相同,因为每个元数据行都有一个ID、一个meta_键列和一个meta_值列 我基本上想为这些模型创建一个通用方法,它允许我在各种模型之间添加/编辑/删除元数据。在这种情况下,使用抽象类
我基本上想为这些模型创建一个通用方法,它允许我在各种模型之间添加/编辑/删除元数据。在这种情况下,使用抽象类或接口是否合适?如果模型端发生变化,如何覆盖该方法?首先考虑这应该是您的初始设置
- 元数据(接口,定义元数据的基本内容,在任何共享条件下)
- MetadataAbstract(实现元数据、接口并提供所有元数据共享的基本方法)
- 元数据\日志(添加属性和特定于日志的方法)
- 元数据\站点(添加属性和…)
此外,您可能需要考虑将表结构更改为更类似于
的内容。- 元数据(共享列)
- 元数据日志(特定于日志)
- 元数据_站点(特定于站点)
<?php
namespace Example;
interface Metadata {
function getKey();
function getValue();
}
abstract class AbstractMetadata implements Metadata {
abstract protected function getKey()
{
return 5;
}
protected function getValue()
{
return 3;
}
}
// use Example\AbstractMetadata;
class LogMetadata extends AbstractMetadata {
public function getKey()
{
return 1;
}
public function getValue()
{
return 2;
}
}
// use Example\AbstractMetadata;
class StationMetadata extends AbstractMetadata {
public function getKey()
{
return 2;
}
public function getValue()
{
return parent::getValue(); // 3
}
}
我不确定你是否应该这样设计。听起来您应该从保存数据的类中抽象出常用方法(也许您想使用
DataMapper
?)。但是如果你认为这种继承的ActiveRecord
模式是有意义的,我想你是想做这样的事情吗
abstract class Base
{
public function add($data)
{
$something = do_stuff($this->getId($data));
}
abstract protected function getId($data);
}
class Derived extends Base
{
private $idKey = 'DerivedKey';
protected function getId($data)
{
return $data[$this->idKey];
}
}
在您的例子中,您将使用通用方法(CRUD),但调用抽象保护方法来获取特定的内容
这是模板方法模式
编辑:如果您认为可能有添加额外列/元数据等的类,那么可以尝试另一种方法
abstract class Base
{
public function add($data)
{
$something = array();
$something[] = do_stuff($this->getId($data));
$something[] = do_stuff($this->getName($data));
$something[] = $this->additionalFields($data);
}
abstract protected function getId($data);
abstract protected function getName($data);
protected function additionalFields($data)
{
// no additional fields by default
}
}
class Derived extends Base
{
private $idKey = 'DerivedKey';
private $nameKey = 'DerivedName';
private $other = 'new thing';
protected function getId($data)
{
return $data[$this->idKey];
}
protected function getName($data)
{
return $data[$this->nameKey];
}
protected function additionalFields($data)
{
return do_foo($this->other, $data);
}
}
请记住,这些都是向您展示OOP模式的精心设计的示例。例如,我假设getId
可能更复杂。如果您的产品一直遵循这种模式,那么更好的设计可能是:
class Base
{
protected $metadata = array(
'id' => 'defaultId',
'name' => 'defaultName'
);
public function add($data)
{
foreach ($metadata as $key => $value) {
do_something($key, $data[$value]);
}
}
}
class Derived extends Base
{
public function __construct()
{
$this->metadata['id'] = 'DIfferentId';
}
}
同样,这只是一种可以根据需要进行调整的模式。您真的确定表结构永远不会改变吗?有很多用于持久性的库[例如,条令],您可能想看看它们。肯定的。如果需要,我只提供一个关系表。我只需要ID、meta_键、meta_值和关系映射器ID。@moonwave99谢谢你的建议,但我没有这个选项。Hmmmm。好的,这很有帮助。所以元数据提供了必需的方法,MetadataAbstract允许在后一个类中重写使用?我想我想在这里要做的是,如果元数据对象有特殊的处理情况,则重写CRUD功能的默认方法。我试试这个。Thank=)没有元数据将只是定义元数据是什么/有什么的接口。我会用一个例子更新我的帖子…谢谢@Matt的反馈非常好!这个例子真的帮了大忙。干杯很高兴我能帮忙!祝你的项目好运:-)!我将很快发布一个TMDB(电影数据库)的API包装,您可能有兴趣看看。如果需要,我可以覆盖抽象类add()?当然,为什么不呢?但是你得到了什么?你没有针对特定片段的通用方法吗?您应该编写
add
,这样将要定制的任何内容都可以在另一个受保护的方法中处理。请注意,如果想提供默认实现,则不需要对上面的代码<>代码> GETId <代码>进行抽象。请把上面的评论考虑到@ CuFrFik,它询问元数据结构是否会发生变化,我说它不会,如果有数据的附件,我会把它指向相关表,因此,我需要对该关系数据进行操作(从而在重写方法中处理该数据)。现在,虽然情况并非如此,所以这一点无关紧要,但它可能会在某个时候出现。不过我理解getId()的概念,我根本不需要重写它。
class Base
{
protected $metadata = array(
'id' => 'defaultId',
'name' => 'defaultName'
);
public function add($data)
{
foreach ($metadata as $key => $value) {
do_something($key, $data[$value]);
}
}
}
class Derived extends Base
{
public function __construct()
{
$this->metadata['id'] = 'DIfferentId';
}
}