我正在尝试创建我自己的轻量级但OOP方式来跟踪我的PHP框架中加载的文件及其相应的版本(尚未实现),以便能够在将来轻松测试依赖性问题。
这是我目前的代码,但作为OOP和模式的新手,我无法确定我是否已经完成了正确的单例:
class loadRegistry {
private static $registry = null;
private function __construct(){
if (is_null(self::$registry));
self::$registry = array();
}
public static function get() {
return self::$registry;
}
public static function set($filename){
if ( isSet( self::$registry[$filename]) AND !empty($filename) ) {
throw new Exception("File already loaded");
}
else self::$registry[$filename] = '';
}
}
loadRegistry::set('filename');
loadRegistry::set('filename2');
$reg = loadRegistry::get();
答案 0 :(得分:2)
不,它不是单身人士。实际上你只是在玩静态属性。单身人更像是这样:
class Registry {
private static $registry = null;
private $data;
private function __construct(){
$this->data = array();
}
public static function getInstance() {
if (is_null(self::$registry)) {
self::$registry = new Registry();
}
return self::$registry;
}
public function set($filename){
if (isset($this->data[$filename]) && !empty($filename) ) {
throw new Exception("File already loaded");
}
else {
$this->data[$filename] = '';
}
}
// further **instance** methods
}
$reg = Registry::getInstance();
$reg->set('filename');
$reg->set('filename2');
我不知道你是否可以在PHP中将构造函数设置为私有......我认为不是。
静态类 $ 和单例之间存在差异。单例允许一次只有一个实例。对于静态类,您甚至不需要实例。此外,静态属性在类的所有实例之间共享(如果您创建实例)。
如果您不需要实例来保存某个状态,则通常使用静态类。
$:没有真正的静态类。只有成员才能被定义为静态。我会说一个只有静态成员的类可以称为静态类。
答案 1 :(得分:2)
您在上面提到的内容并不遵循Singleton的模式。 Singleton只允许一次存在该类的一个实例(而不是定义一个静态对象,这不会阻止您创建同时的其他对象并使它们混淆)。
您可以在官方手册中阅读PHP中的Singleton模式; http://php.net/manual/en/language.oop5.patterns.php
上面的手动示例给出了一个准系统示例,但我从未真正需要在PHP中使用Singleton,因为PHP5已经发布。它们在诸如iPhone之类的设备上更有用,在这些设备上你只需要一个特定硬件的单一接口 - 例如屏幕。但是,我想你可能会在PHP应用程序中将它用于数据库连接......
答案 2 :(得分:1)
这段代码看起来很奇怪 - 首先,构造函数永远不会被任何内部函数调用,因为它是私有的,所以不能在外部调用。它不是单身,因为单身实际上意味着被创建为一个对象,而这个类永远不会。
但是,您可以使用此类代码创建分区全局存储,如果这是您想要的。
这是给你的单身人士:
class Singleton {
private static $me;
private function __construct
{
/* something */
}
public static getInstance()
{
if(empty(self::$me)) self::$me = new self;
return self::$me;
}
}
这里改进了5.3+单身:
class Singleton {
private static $me;
private function __construct
{
/* something */
}
public static getInstance()
{
if(empty(self::$me)) self::$me = new static;
return self::$me;
}
}
答案 3 :(得分:0)
我觉得这有点旧了。
我曾经仅仅为了单个实例使用单例,但是使用注册表你不再需要静态。 另一方面,如何实现和使用注册表来定义注册表解决方案是否良好。
因为我使用MVC并且只需要为基本控制器传递一次注册表,为基本模型传递一次,这就是全部。另一方面,如果一个设计需要经常传递注册表对象,那么它可能不是一个好主意。
基本理念是:
有一个注册表
刚开始时只创建了一个数据库类的实例,这样我们就不用费心去创建连接等了。我使用了两个数据库,直到我第一次需要它时才创建连接
$ registry-> dbManager = new dbManager();
将注册表对象传递给路由器,控制器和模型基类注册表随处可见 $ registry = My_Registry :: singleton(); $ registry-> router = new router($ registry); $ registry-> dbManager = new dbManager(); 等..................
Db类保持正常类,这只是db类的一部分
类dbManager {
//DB Connections
private $Internal_db_con = null;
private $Business_db_con = null;
//DB Connection Parameters
private $host=null;
private $user=null;
private $pass=null;
//DB Names
private $internal_db_name=null;
private $business_db_name=null;
//
private $result = null;
// only one object created
public function __construct()
{
include_once __SITE_PATH . 'includes/db_config.inc';
list($ this-> host,$ this-> user,$ this-> pass,$ this-> internal_db_name,$ this-> business_db_name)= $ db_conf;
}
//set internal database connection
private function setInternalDBCon()
{ debug('setInternalDBCon called');
try{
# MySQL with PDO_MYSQL
$dbq="\"";
$this->Internal_db_con = new
PDO(“mysql:host =”。$ this-> host。“; dbname =”。$ this-> internal_db_name,$ this-> user,$ this-> pass, array(PDO :: MYSQL_ATTR_INIT_COMMAND =>“SET NAMES utf8”));
$this->Internal_db_con->setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e)
{
echo 'Error connecting to MySQL: ' .$e->getMessage();
}
}
//set business database connection
public function setBusinessDBCon()
{
try{
# MySQL with PDO_MYSQL
$dbq="\"";
$this->Business_db_con = new
PDO(“mysql:host =”。$ this-> host。“; dbname =”。$ this-> internal_db_name,$ this-> user,$ this-> pass, array(PDO :: MYSQL_ATTR_INIT_COMMAND =>“SET NAMES utf8”));
$ this-> Business_db_con-> setAttribute(PDO :: ATTR_ERRMODE,PDO :: ERRMODE_EXCEPTION);
}
catch(PDOException $ e)
{
echo'连接到MySQL的错误:'。$ e-> getMessage();
}
}
/*check if a row exists in a safe way that avoids sql atack*/
public function uniqueRowExists($dbcon, $table,$col_name, $data)
{
//check if connection is set
if($this->{$dbcon.'_db_con'}==null) //dynamic variable call
$this->callMyFunc( 'set'.$dbcon.'DBCon'); //dynamic function call
.......................等....
//prepare
$stmt = $this->{$dbcon.'_db_con'}->prepare($sql);
$stmt->execute($data);
.................等
这就是我从db class
调用公共函数的方法 //查询数据库
$结果= $这 - >登记处送交> dbManager-> uniqueRowExists
('Internal','internal_user',Array('uname','pass'),$ input);
//连接可供选择,表格,颜色,数组搜索数据
这样在任何地方只有一个实例。