- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
因此,我使用 PDO::FETCH_CLASS 来创建一个新对象,并使用数据库中同名列中的值填充属性,如下所示:
$db = Connection::get();
$sql = $db->prepare("SELECT * FROM table WHERE id = :id");
$sql->bindParam(":id", "1");
$sql->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'table');
$sql->execute();
$newobj = $sql->fetch();
是否有相反的方法将对象的属性插入到表中相应的列中,以节省键入整个 bindParam() 负载和较长的 SQL 查询?
非常感谢
最佳答案
这是一件有趣的事情
public
属性,并尝试将它们用作查询的一部分。如果确实需要,您可以对它们进行更多过滤。我们将使用所谓的反射。
这是一把双刃剑。
一方面,我们可以将其放入基类中,并使用所有对象扩展它,这对它们来说效果很好。如果稍后您向表中添加字段,同样您无需更改任何内容,它就可以正常工作。
另一方面,处理这个问题需要花费少量的时间,而不是把它写成字符串。其中一些问题可以通过缓存 protected 静态属性
内的查询以及缓存属性本身(但不是值)来解决
我将从创建一个抽象类开始。这是解决这个问题的一种非常灵活的方法,并且它可以被重用 - 注意:我只测试了 Insert 方法,所以如果其他部分有任何错误,请原谅我。
abstract class BaseObject
{
public $id;
protected static $_DB;
public function getDB(\PDO $db ){
if( !self::$_DB ){
//@todo: connect to Database
}
return self::$_DB;
}
public function getId(){ return $this->id; }
public function setId( $id ){ $this->id = $id }
//returns the records id
public function save(){
//if there is no ID then we know it didn't come from the DB
if( $this->id )
return $this->update();
else
return $this->insert();
}
// query format = 'INSERT INTO table (id, ... )VALUES(:id, ... )'
public function insert(){
$this->validate();
$db = $this->getDB(); //localize
$R = new \ReflectionObject( $this );
$props = (array)$R->getProperties()[0];
$names = array_keys( $props );
$sql = 'INSERT INTO '.$this->getTable().' ('.implode(',', $names).' )VALUES( :'.implode(', :', $names).' )';
$params = array_combine(
array_map(function($item){
return ':'.$item;
}, $names),
$props
);
$stmt = $db ->prepare( $sql );
$stmt->execute( $params );
$this->id = $db->lastInsertId(); //don't forget to update the id
return $this->id;
}
// query format = 'UPDATE table SET prop=:prop, ... WHERE id=:id'
public function Update(){
$this->validate();
$db = $this->getDB(); //localize
$R = new \ReflectionObject( $this );
$props = (array)$R->getProperties()[0];
$names = array_keys( $props );
$sql = 'UPATE '.$this->getTable().' SET ';
$set = [];
$params = [];
foreach( $props as $name=>$value ){
$params[':'.$name] = $value;
if( $name == 'id' ) continue;
$set[] = "$name = :$name";
}
$sql .= implode(', ', $set).' WHERE id=:id'
$stmt = $db->prepare( $sql );
$stmt->execute( $params );
return $this->_id;
}
abstract public function getTable();
abstract public function vallidate();
}
然后在具体类中,您只需要实现抽象方法,并添加特定于它们的其他属性
class Dude extends BaseObject
{
public $name;
public function getName(){ return $this->name ; }
public function setName( $name ){ $this->name = $name }
public function getTable(){
return 'dudes';
}
public function validate(){
if( empty( $this->name ) ) throw new \Exception( "Name cannot be empty" );
//...etc.
}
}
我碰巧想到您应该注意的一件事,当通过 PDO 结果加载类时,不会调用该类的构造函数。我以这种方式加载类已经有一段时间了,可能有一种方法可以强制它调用构造函数,或者我可能只是记忆错误。但这是值得一提的。
我提到这一点的原因是抽象类需要一个 PDO 实例,所以我添加了 getDB()
方法。这只是一个关于如何缓存所有类的数据库连接的简短示例,(我懒得做实际的连接部分,抱歉)
就我个人而言,我使用所谓的 Singleton
来满足我的数据库需求,因此我只需调用类似这样的东西 self::$_DB = DB::getInstance();
就在那里,但那是另一天的故事了。
我还建议添加一个 delete
方法,这样您就可以获得所有程序员爱好者一直在谈论的完整 CRUD
体验。
我能想到的另一个主要改进是您可以将其中一些内容存储在静态属性中,基本上在第一次运行后缓存它。这将节省一些对类的多次重新处理(内省(introspection))的时间。
不过这有点棘手,你会想要进一步分解。我可以给你的一个提示是,确保在基类中使用 static::$Var
而不是 self::$Var
,这样你就可以使用所谓的 >后期静态绑定(bind)
。这基本上是棘手的部分,因为您可能会拥有包含完全不同内容的后代类。我不确定这是否是正确的术语,但这是一种范围解析问题。
但我会把最后的事情留给你。这个例子应该为您指出正确的路径(或者至少是我知道可行的路径),并为您提供一些关于可能性的想法。
最后一件事是使用这样的字符串访问属性或调用方法是完全可以的(当然假设它们存在)
foreach( $props as $name=>$value ){
//for this we will say $name = 'id'
$method = "get".ucFirst( $name ); // 'getId'
$a = $this->$method(); // calls $this->getId()
$a = $this->$name; //access property $this->id;
}
我只是想把它放在那里,为您提供另一种方式来访问您可能认为有用的数据。
关于php - 与 PDO::FETCH_CLASS 相反,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45396094/
有什么方法可以将 PDO 的结果作为构造函数的参数传递吗?比方说,我有以下类(class): class Test { private $value1; private $value2
是否可以创建另一个实例作为 PDO::fetchAll() 中当前实例的参数发送? 如果设置了\PDO::FETCH_PROPS_LATE,它将首先调用__construct,然后设置属性。因此通过数
我喜欢使用 PDO::FETCH_CLASS 来获取对象数组,应该调用构造函数,因为我需要此类中的构造函数。作为第三个参数,我使用数据库表中的列名。结果我得到了列的名称,但不是数据库中的预期值。我正在
我正在尝试将查询结果转换为类。 $result->setFetchMode(PDO::FETCH_CLASS, 'myclass', array()); 这工作得很好,但是类名 myclass 取决于
我有以下映射到 MySql 表的示例类(如下所示)。当我使用 PDO::FETCH_CLASS 并执行 *var_dump* 时,我看到映射将转到所有小写属性。即“shortName”映射到“shor
有什么方法可以将 PDO 的结果作为构造函数的参数传递吗?比方说,我有以下类(class): class Test { private $value1; private $value2
我正在尝试在一个对象上使用 PDO::FETCH_CLASS。我正在使用命名空间并输入: $result = $query->fetchAll(\PDO::FETCH_CLASS, 'Product'
我遇到了一段代码,其中 PDO::FETCH_CLASS 被调用时没有将类的名称作为参数传递,如下所示: function getUsers() { $DBH = $this->getDb
PDO::FETCH_CLASS 允许使用预填充数据初始化类实例。它看起来像这样: data === ['foo' => 1, 'bar' => 1] } public functio
假设我有 2 个 php 对象: 和 每个帖子都有一个唯一的约束,数据库中有 1 个用户。 我想使用 PDO 的“FETCH_CLASS”方法将数据填充到“Post”对象中,该方法适用于所有“Po
假设我有 2 个 php 对象: 和 每个帖子都有一个唯一的约束,数据库中有 1 个用户。 我想使用 PDO 的“FETCH_CLASS”方法将数据填充到“Post”对象中,该方法适用于所有“Po
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 去年关闭。
在使用 PDO::FETCH_CLASS 时,似乎没有办法让 PDO 使用构造函数/setter 创建新对象。 我猜,目前使用 FETCH_CLASS 时,成员变量会使用反射来填充。它们当然不会通过构
借助 PDO,我们现在可以轻松地将字段映射到对象的属性,速度极快。这个: class myClass {} $stmt = $db->prepare('SELECT foo,bar FROM tab
因此,我使用 PDO::FETCH_CLASS 来创建一个新对象,并使用数据库中同名列中的值填充属性,如下所示: $db = Connection::get(); $sql = $db->prepar
我有一个像这样的 php 类: class bar{ public $value; } class foo extends bar{ public $value; public
我有一个类使用魔术方法来存储属性。这是一个简化的示例: class Foo { protected $props; public function __construct(array
我在下面的代码中遇到问题: $query = 'SELECT user.id as id, pet.name as name FROM user LEFT JOIN pet on
我想使用 PDO 创建对象实例。我知道有很多 questions已经,但我只发现可以将参数数组发送给构造函数。在我看来,构造函数似乎只能接受一个数组作为参数。然而,这会降低构造函数的意义。 我想用我自
我觉得在这里问这个问题有点脏,因为我觉得我应该可以用谷歌搜索它,但是好吧......我没有找到任何东西。 有没有办法在正常的 fetch 函数中使用 fetchmode PDO::FETCH_CLAS
我是一名优秀的程序员,十分优秀!