Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/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 对于静态查找表,我通常创建静态常量文件(例如#3)。我通常使用以下类: namespace Constants; class UserTypes { const ADMIN = 1; const USER = 2; const GUEST = 3; } $id = Constants\UserTypes::ADMIN;_Php_Design Patterns_Database Design - Fatal编程技术网

Php 对于静态查找表,我通常创建静态常量文件(例如#3)。我通常使用以下类: namespace Constants; class UserTypes { const ADMIN = 1; const USER = 2; const GUEST = 3; } $id = Constants\UserTypes::ADMIN;

Php 对于静态查找表,我通常创建静态常量文件(例如#3)。我通常使用以下类: namespace Constants; class UserTypes { const ADMIN = 1; const USER = 2; const GUEST = 3; } $id = Constants\UserTypes::ADMIN;,php,design-patterns,database-design,Php,Design Patterns,Database Design,当我使用更可变的lookup take时,我会将它拉入一个对象,然后缓存24小时。这样一来,它每天只更新一次。这将使您免于进行数据库往返,但允许您轻松地用代码处理事情。是的,您关于避免使用#3而坚持使用#2是正确的。请尽可能地像使用usertype表来包含角色,然后使用id值将它们与用户表关联时那样查看,id值应保留在数据库中。如果使用常量,则数据必须始终依赖于要解释的php代码。此外,您可以通过使用外键(在服务器允许的情况下)强制执行数据完整性,并允许您将报告从php代码移植到其他报告工具。维

当我使用更可变的lookup take时,我会将它拉入一个对象,然后缓存24小时。这样一来,它每天只更新一次。这将使您免于进行数据库往返,但允许您轻松地用代码处理事情。

是的,您关于避免使用#3而坚持使用#2是正确的。请尽可能地像使用usertype表来包含角色,然后使用id值将它们与用户表关联时那样查看,id值应保留在数据库中。如果使用常量,则数据必须始终依赖于要解释的php代码。此外,您可以通过使用外键(在服务器允许的情况下)强制执行数据完整性,并允许您将报告从php代码移植到其他报告工具。维护也变得更容易。如果您使用了#3,数据库管理员不需要了解php就可以得出数字的含义,如果他们被要求帮助开发报表。这看起来可能不太相关,但就维护而言,在php代码中使用存储过程而不是嵌入式sql在几个方面对维护都很友好,而且对DBA也很有利

我选择选项#2并按预期使用连接。你永远不知道未来会发生什么,今天做好准备总是更好的

至于让数据库尽可能地独立于此类操作,也有可能长期缓存。对于这个路由,PHP中的一个选项是使用一个文件缓存,这个缓存只有在时间需要时才会更新。对于我创建的框架,这里有一个示例;我很想知道人们是怎么想的:

注:

(LStore、LFetch、GetFileName)属于静态调用的缓存对象

(Blobify和Unblobify)属于始终处于活动状态的SystemComponent对象

每段缓存数据都有一个密钥。这是你唯一需要记住的事情

public function LStore($key,$data, $blnBlobify=true) {
    /* Opening the file in read/write mode */
    $h = fopen(self::GetFileName($key, 'longstore'),'a+');
    if (!$h) throw new Exception('Could not write to cache');
    flock($h,LOCK_EX); // exclusive lock, will get released when the file is closed
    fseek($h,0); // go to the start of the file
    /* truncate the file */
    ftruncate($h,0);
    if($blnBlobify==true) { $data = SystemComponent::Blobify(array($data)); }
    If (fwrite($h,$data)===false) {
        throw new Exception('Could not write to cache');
    }
    fclose($h);
}   
public function LFetch($key) {
    $filename = self::GetFileName($key, 'longstore');
    if (!file_exists($filename)){ return false;}
    $h = fopen($filename,'r');
    if (!$h){ return false;}
    /* Getting a shared lock */
    flock($h,LOCK_SH);
    $data = file_get_contents($filename);
    fclose($h);
    $data = SystemComponent::Unblobify($data);
    if (!$data) {
        /* If unserializing somehow didn't work out, we'll delete the file */
        unlink($filename);
        return false;
    }
    return $data;
}
/* This function is necessary as the framework scales different directories */

private function GetFileName($key, $strCacheDirectory='') {
    if(!empty($strCacheDirectory)){ 
        return SystemComponent::GetCacheAdd() . $strCacheDirectory.'/' .  md5($key); 
    } else {    
        return SystemComponent::GetCacheAdd() . md5($key);
    }
}
public function Blobify($Source){
    if(is_array($Source)) { $Source = serialize($Source); }

    $strSerialized = base64_encode($Source);

    return $strSerialized;

}
public function Unblobify($strSerialized){
    $Decoded = base64_decode($strSerialized);
    if(self::CheckSerialized($Decoded)) { $Decoded = unserialize($Decoded); }

    return $Decoded;    

}
function CheckSerialized($Source){
    $Data = @unserialize($Source);
    if ($Source === 'b:0;' || $Data !== false) {
        return true;
    } else {
        return false;
    }
}  
现在,在访问实际数据时,我只调用一个fetch。为了确保它是最新的,我告诉它去商店。在您的情况下,这将在更新usertype表之后进行。

我建议#3避免无用的查询,并防止在意外修改现有DB表行时发生行为更改的风险:

  • 在模型类中添加必要的常量:

    class Role // + use namespaces if possible
    {
      // A good ORM could be able to generate it (see @wimvds answer)
      const ADMIN = 1;
      const USER = 2;
      const GUEST = 3;
    
      //...
    
    }

  • 那么像这样的查询是有意义的:

    $query = "SELECT info, foo FROM user WHERE role_id = ".Role::ADMIN;
    
    使用ORM(例如,在下面的示例中),您将完成以下工作:

    $isAdminResults = UserQuery::create()->filterByRoleId(Role::ADMIN);
    

如果类型表仅由一个表使用(如示例中所示),则此操作将起作用。但是,如果多个表需要使用相同的枚举类型呢?那么,您需要使用规范化方法。然后,你要么不断地查询数据库中的值,要么陷入困境。要么这样,要么在两个地方维护它(这并不有趣)…这就是我对解决方案2的意思。虽然我不得不承认我为我的人类可读id列选择的名称(
name
)不是很直观。哦,我的错。被varchar列上的连接弄糊涂了(我认为效率不高)。顺便问一下,这个sql语句会产生任何结果吗?!关于这种方法还有一件事:最好限制它可以包含的值,例如:ereg(“^[a-z]{1}[a-z0-9_307;]{0254}$”,$hid),即允许使用小写、字母数字和下划线。如果您不是唯一一个可以输入值的人,那么它非常有用……是的,name列应该是唯一的索引,否则效率会非常低。你说得对#2中的查询是错误的:S--刚刚修复了它,谢谢!我知道这对于你的需求来说似乎有些过分,但它可以在整个网站上反复使用。
usertype_id (primary key)  | name       | description       | hid (unique key)
---------------------------+------------+-------------------+---------------
1                          | 'admin'    | 'Administrator'   | 'admin'
2                          | 'reguser'  | 'Registered user' | 'user'
3                          | 'guest'    | 'Guest'           | 'guest'
select usertype_id from tablename where hid = "admin"
foreach (getdbarr("SELECT * FROM usertype") as $row)  {
  define($row['name'],$row['id']);
}
$user = DAO_User::get(1); // this pulls a JOIN-less record
$role = $user->getRole(); // lazy-load
public function getRole() { 
  // This comes from a cache that may be called multiple 
  // times per request with no penalty (i.e. store in a registry)
  $roles = DAO_UserRoles::getAll();

  if(isset($roles[$this->role_id]))
    return $roles[$this->role_id];

  return null; // or: new Model_UserRole();
}
namespace Constants;
class UserTypes {
    const ADMIN = 1;
    const USER = 2;
    const GUEST = 3;
}

$id = Constants\UserTypes::ADMIN;
public function LStore($key,$data, $blnBlobify=true) {
    /* Opening the file in read/write mode */
    $h = fopen(self::GetFileName($key, 'longstore'),'a+');
    if (!$h) throw new Exception('Could not write to cache');
    flock($h,LOCK_EX); // exclusive lock, will get released when the file is closed
    fseek($h,0); // go to the start of the file
    /* truncate the file */
    ftruncate($h,0);
    if($blnBlobify==true) { $data = SystemComponent::Blobify(array($data)); }
    If (fwrite($h,$data)===false) {
        throw new Exception('Could not write to cache');
    }
    fclose($h);
}   
public function LFetch($key) {
    $filename = self::GetFileName($key, 'longstore');
    if (!file_exists($filename)){ return false;}
    $h = fopen($filename,'r');
    if (!$h){ return false;}
    /* Getting a shared lock */
    flock($h,LOCK_SH);
    $data = file_get_contents($filename);
    fclose($h);
    $data = SystemComponent::Unblobify($data);
    if (!$data) {
        /* If unserializing somehow didn't work out, we'll delete the file */
        unlink($filename);
        return false;
    }
    return $data;
}
/* This function is necessary as the framework scales different directories */

private function GetFileName($key, $strCacheDirectory='') {
    if(!empty($strCacheDirectory)){ 
        return SystemComponent::GetCacheAdd() . $strCacheDirectory.'/' .  md5($key); 
    } else {    
        return SystemComponent::GetCacheAdd() . md5($key);
    }
}
public function Blobify($Source){
    if(is_array($Source)) { $Source = serialize($Source); }

    $strSerialized = base64_encode($Source);

    return $strSerialized;

}
public function Unblobify($strSerialized){
    $Decoded = base64_decode($strSerialized);
    if(self::CheckSerialized($Decoded)) { $Decoded = unserialize($Decoded); }

    return $Decoded;    

}
function CheckSerialized($Source){
    $Data = @unserialize($Source);
    if ($Source === 'b:0;' || $Data !== false) {
        return true;
    } else {
        return false;
    }
}  
class Role // + use namespaces if possible
{
  // A good ORM could be able to generate it (see @wimvds answer)
  const ADMIN = 1;
  const USER = 2;
  const GUEST = 3;

  //...
$query = "SELECT info, foo FROM user WHERE role_id = ".Role::ADMIN;
$isAdminResults = UserQuery::create()->filterByRoleId(Role::ADMIN);