我在开发中使用Propel ORM,我遇到了这个问题:
$mo = new Category();
$mo->setId(7); // This Id exists
$mo->setDescription('New description!');
$mo->save(); //it should update!
嗯,它不会更新值。它抛出异常并说我无法插入重复的密钥。有办法解决这个问题吗?
希望有人可以提供帮助, 大卫
[编辑]
我知道我可以这样做:
$mo = CategoryQuery::create()
->findByPk(7)
->setDescription("something")
->save();
我知道这有效,但由于我项目的具体问题,我不能这样做。这就是问题的原因。
再次感谢!
答案 0 :(得分:3)
这似乎就像旧线程一样,这里是我想提及的更新答案
$q = array(1,2,3,4);
$rp = RolesPermissionsQuery::create()->filterById($roleId)->findOneOrCreate();
$rp->setRolesId($roleId);
$rp->setPermissions(serialize($q));
$rp->save();
在上面的代码中,propel将创建新行或根据条件更新现有行。希望这可能有助于某人。
答案 1 :(得分:1)
Propel根据您要保存的对象调用isNew()
的结果,在插入和更新之间进行选择(请参阅BaseCategory::save()
函数:$isInsert = $this->isNew();
)。因此,您可以通过自己更改此属性来欺骗它,使其认为它是现有对象:$mo->setNew(false);
。 isNew()
和setNew()
在the BaseObject
class中定义。
一般来说,使用部分水合物体可能不是一个好主意(这就是你在这里做的事情:你创建一个对象,但是不要用它们的实际数据库填充所有属性值)。某些行为或您自己的代码可能依赖于对象的两个属性,然后给出不正确的结果。一个简单的示例:如果您有一个自动生成的字段nameAndDescription
,您在保存时将其设置为name
和description
字段的串联(通过扩展Propel对象,通过新的preInsert()
和preUpdate()
挂钩),如果您像在此处一样更新对象,这将无法达到预期效果。但这是我所知道的唯一警告,而且这可能是你掌控的情况。
如果您只想更新某些字段,甚至可能更新多个对象(例如:对于今天之前Order
的所有executionDate
个对象,请将status
设置为{{ 1}}),您可以通过自己调用BasePeer::doUpdate()
来完成此操作。第一个参数是您的选择Criteria对象:今天之前具有"archived"
的所有Order
个对象。第二个参数也是Criteria对象,但这用于存储新值:executionDate
到status
。它应该看起来像这样(未经测试):
"archived"
此方法当然不会执行您在PHP代码中定义的任何// This probably also works with a Query object
$selectCriteria = new Criteria(OrderPeer::DATABASE_NAME);
$selectCriteria->add(OrderPeer::EXECUTION_DATE, time(), Criteria::LESS_THAN);
// And this too, it's just used as a simple hash table
$valueCriteria = new Criteria(OrderPeer::DATABASE_NAME);
$valueCriteria->add(OrderPeer::STATUS, "archived");
$con = Propel::getConnection(OrderPeer::DATABASE_NAME, Propel::CONNECTION_WRITE);
BasePeer::doUpdate($selectCriteria, $valueCriteria, $con);
或preUpdate()
挂钩,因为生成的对象已被完全绕过。因此,只有在绝对必要时(出于性能原因?)才使用它,并且您知道周围没有其他“陈旧”对象。
答案 2 :(得分:0)
解决此问题的最快方法是首先查询实体,然后更新它(这样您就不会使用分离的实体):
$mo = CategoryPeer::retrieveByPK(7);
$mo->setDescription('New description!');
$mo->save(); // should work since the entity was retrieved first
如果你需要能够在不首先查询的情况下进行更新,我恐怕我太过于担心Propel新手了。可能有可能做一个手动SQL语句,但也可能有一种方法来附加您手动设置id的实例。也许另一位回答者可以启发我们。
答案 3 :(得分:0)
使用Find One或创建这将找到或创建一个对象
$ mo = CategoryQuery :: create() - > filterByPk(7) - > findOneOrCreate();
$钼> setDescription("东西&#34);
if($ mo-> validate()){$ mo-> save()}