Need clue about the problem. I want to update the record in database based on id through the propel save operation but I am getting this error.
Cannot insert a value for auto-increment primary key (pyz_client_record.id)
crudOperationEntity = new PyzCrudOperation(); $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray()); $crudOperationEntity->save();
It's exactly as I told, so please load the entity from the DB instead of creating it via new
.
A good rule of thumb is that you should never use new
outside of DependencyProvider and Factories in Spryker, except for Transfers.
Did you received the entity through a propel query (e.g.: PyzClientQuery::create()->findById(1)
) or through an alternative way?
Seems like the entity you are trying to save does not know that it already exists in the DB and does an insert instead of an update.
If your case is to create a new entry in the DB please check if you have allowed to insert auto-increment values (allowPkInsert
on the table definition: http://propelorm.org/documentation/reference/schema.html#table-attributes)
Thanks for your response.
I have set the allowPkInsert
and now it is throwing this error SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '22' for key 'PRIMARY'
So I assume you have loaded/assembled the entity you try to save without using propel, could that be the case?
Or do you overwrite the id at some place
no, here is my code
$crudOperationTransfer->setId(22); $crudOperationTransfer->setName('Test update'); $crudOperationTransfer->setDescription('description update'); $crudOperationTransfer->setStatus(false); $crudOperationTransfer = $this->getFacade()->updateCrudOperationEntity($crudOperationTransfer);
$crudOperationTransfer->setId(22);
Where is the 22 coming from?
I set it hardcoded for the moment but it will be come through the post data.
Here is my method to update.
may be I am doing something wrong in this
public function updateEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer { $crudOperationEntity = new PyzCrudOperation(); $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray()); $crudOperationEntity->save(); $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true); return $crudOperationTransfer; }
I assume inside updateCrudOperationEntity
you just create an entity with new PyzClient
fill it with data and call save()
, could that be the case?
If so please try to receive the entity first through
$entity = PyzClientQuery::create()->filterById($transfer->getId())->findOneOrCreate(); $entity->fromArray($transfer->toArray()); $entity->save();
Well the save
method in the PyzCleint actually used for both create and update the entity. Here is the code.
on the other side Call to undefined method: findOneOrCreate.
I know, propel checks the isNew()
method if an insert or an update should be executed during save.
From the error you have it pretty much seems like propel is doing an insert (isNew()
returns true), but should execute an update instead as you already have the entity in your DB and just want to update it.
The most common case for this is that the entity was not loaded from the DB before, but created via new
.
crudOperationEntity = new PyzCrudOperation(); $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray()); $crudOperationEntity->save();
It's exactly as I told, so please load the entity from the DB instead of creating it via new
.
A good rule of thumb is that you should never use new
outside of DependencyProvider and Factories in Spryker, except for Transfers.
ok
Thanks for your time and help
May you please guide me one more thing
what I can improve in this class
<?php namespace Pyz\Zed\CrudOperation\Persistence; use Generated\Shared\Transfer\CrudOperationTransfer; use Orm\Zed\CrudOperation\Persistence\PyzCrudOperation; use Spryker\Zed\Kernel\Persistence\AbstractEntityManager; use Orm\Zed\CrudOperation\Persistence\PyzCrudOperationQuery; /** * @method \Pyz\Zed\CrudOperation\Persistence\CrudOperationPersistenceFactory getFactory() */ class CrudOperationEntityManager extends AbstractEntityManager implements CrudOperationEntityManagerInterface { /** * @param \Generated\Shared\Transfer\CrudOperationTransfer $crudOperationTransfer * * @return \Generated\Shared\Transfer\CrudOperationTransfer */ public function saveEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer { $crudOperationEntity = new PyzCrudOperation(); $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray()); $crudOperationEntity->save(); $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true); return $crudOperationTransfer; } /** * @param \Generated\Shared\Transfer\CrudOperationTransfer $crudOperationTransfer * * @return \Generated\Shared\Transfer\CrudOperationTransfer */ public function updateEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer { $crudOperationEntity = PyzCrudOperationQuery::create()->filterById($crudOperationTransfer->getId())->findOneOrCreate(); $crudOperationEntity->fromArray($crudOperationTransfer->toArray()); $crudOperationEntity->save(); $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true); return $crudOperationTransfer; } /** * @param \Generated\Shared\Transfer\CrudOperationTransfer $crudOperationTransfer * * @return \Generated\Shared\Transfer\CrudOperationTransfer */ public function deleteEntity(CrudOperationTransfer $crudOperationTransfer): CrudOperationTransfer { $crudOperationEntity = PyzCrudOperationQuery::create()->filterById($crudOperationTransfer->getId())->findOne(); $crudOperationEntity->fromArray($crudOperationTransfer->modifiedToArray()); $crudOperationEntity->delete(); $crudOperationTransfer->fromArray($crudOperationEntity->toArray(), true); return $crudOperationTransfer; } }
except the new operator.
deleteEntity()
it makes no sense to fill the entity with data before it's deleted.
For a little bit more efficiency you could skip the loading of the entity and directly delete it:
PyzCrudOperationQuery::create()->filterById($crudOperationTransfer->delete();
Please be aware that this happens on DB level, so no events are triggered. If you relay on events for this entity, for example to publish and synchronize it, you need to load the whole entity before you delete it.
But I don't have time for a full code review here, sorry.
Thanks for your time.