I have a basic Symfony2/Doctrine2 question. I have two entities the first called "Column" that has OneToMany issues, entity "Issue". And the Issue entity has a ManyToOne relationship with the entity Column. When I create a new Issue I wish to assign a default value for the column.
If I create a hidden field in IssueType.php and assigned a default value I cannot save the submitted form because I get an error about assigning a string to setColumn and not an instance of the Column entity as defined in my Issue entity (see below).
public function setColumn(\WebConfection\ServiceDeskBundle\Entity\Column $column)
{
$this->column = $column;
return $this;
}
Can anybody please advise on the best way to accomplish this? I have read a few articles but am a tad confused and not sure which way to jump. An idiot friendly answer would be greatly appreciated.
You don't really need a hidden field for this to work. Just set the right (default) Column on the Issue you want to add within your action,
// ...
$issue = new Issue();
$issue->setColumn($yourDefaultColumn);
$form = $this->createForm('your_issue_form', $issue);
// ...
Related
I use doctrine entity manager in my script, select and update works always, so entity manager is initialized correctly:
$article = $entityManager->find('Models\Article', 5);
echo $article->getTitle();
or:
$article->setTitle('Updated!');
but when I try to create/save new element then the page breaks, the code is:
$item = new Article();
$item->setAuthorId(1);
$item->setTitle('Created item!');
$entityManager->persist($item);
$entityManager->flush();
It's created like on official documentation page
What I do wrong here?
Seems you can't specify the relation of the object with the Author entity:
$item->setAuthorId(1);
Probably your entity Article Have a relation with the entity Author. In this case you should have a proper setter method (simple setAuthor(Author $author) ) that assign the reference of an Author object. In this case you could use the following:
$item->setAuthor($entityManager->find('Models\Author', 1););
Or Better
$item->setAuthor($entityManager->getReference('Models\Author', 1););
You could also use a short way of reference the class object with the class keyword, as example:
$item->setAuthor($entityManager->getReference(Author::class, 1););
Hope this help
I've soft deletable and a uniqueentity field. It works great but...
If the record is deleted "softdeleted", I can't create the same record. I think it's because the record is not realy deleted in the DB. But I need to that.
So what is the best way to dothis ?
Totaly deleted the record ? So is softdeletable a good choice ?
Find a way that if the record is softdeleted, I can create again the same record
Thanks for your advices
After you removed the unique constraint from the database level, You can set to your entity this.
#UniqueEntity(fields={"name", "deleteTime"}, ignoreNull=false)
In this case the validation will fail if you already have a "non-soft deleted" row with the given name in your database, but it won't if the deleteTime is setted.
since you are using soft delete and unique constraints, you can't actually use a unique constraint on the database level.
I suggest you handle the unique constraint check manually, this could be done in a doctrine life cycle event
One way to do this is by creating a callback function in your entity and annotate it to fire on the event:
/** #PrePersist */
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getObject();
$entityManager = $args->getObjectManager();
// check if this entity's unique field is OK
}
This will only ensure you don't save anything incorrect in the database, but it won't handle your forms nicely. So in addition, you probably want to use the UniqueEntity validator for this, and create a custom repositoryMethod to check the uniqueness.
This custom repository method can be used by both the prePersist and the UniqueEntity validator.
You have three choices
Hard Delete the item
Remove the Unique (and handle it in doctrine)
When you create the new entity, you deactivate the softdeletable filter
$em->getFilters()->disable('soft-deleteable');
This will let you find the "deleted" items. Then you can do things like overwrite the old entry, harddelete it manually or whatever your app needs you to do with it.
In my case, I used this way
Remove the unique index of the column on the Database
public function up(Schema $schema) : void
{
$this->addSql('DROP INDEX UNIQ_A2E0150FE7927C74 ON admins');
$this->addSql('CREATE UNIQUE INDEX UNIQ_A2E0150FE7927333 ON
admins (email,deleted_at)');
}
Add this constraint on your Entity
/**
* #ORM\Entity(repositoryClass=AdminRepository::class)
* #ORM\Table(name="admins",
* uniqueConstraints={
* #UniqueConstraint(name="admins",
* columns={"email", "deleted_at"})
* })
It means that you make the pair email (unique column) and deleted_at unique, instead of just the email field. And now, I can create another admin with the same email, if the old one was deleted (Using soft delete)
i have function
private function updateCharacters($oApiKeyInfo) // argument is base entity
{
$aXmlCharacter = $this->fXml->getXmlRowset($this->oXml, 'row');
// insert new
foreach ($aXmlCharacter as $oXmlCharacter)
{
$loopData = $this->fXml->getXmlAttributesAsArray($oXmlCharacter);
$oApiKeyInfoCharacters = new apiKeyInfoCharacters();
$oApiKeyInfoCharacters
->setKeyID($this->keyID)
->setCharacterID($loopData['characterID'])
->setCharacterName($loopData['characterName'])
->setCorporationID($loopData['corporationID'])
->setCorporationName($loopData['corporationName'])
->set_apiKeyInfo_byKeyID($oApiKeyInfo);
$this->em->persist($oApiKeyInfoCharacters);
}
// $this->em->flush() is in main (public) function
}
but, it creates dublicates... and i want that in db was ONLY that entries that is in $aXmlCharacter (array), others must be deleted
now code above is only adding new entries, but i need remove previous
can someone help to deal with it? and please show working examples
Dublicate entries i can not see any definition for uniquenes.
Deleting an Object vom database is simple as the documentation shows.
$product = $em->getRepository('YourBundle::apiKeyInfoCharacters')->find($id);
$em->remove($product);
$em->flush();
But why do you want to delete the existing one instead of updating?
I want to create a form using some fields from multiple entities. I have all the distinct entites needed already created and i am not using form classes. I need to know how to do to render a form and handle its data so i can save them to the correct tables in my database.
Here is a part of my controller in charge of doing that
public function createPublicSpaceAction() {
//My entities
$Room = new Room();
$GuestList = new GuestList();
$Guest = new Guest();
//I need to know what to do from here
return $this -> render('AcmeUserBundle:Default:Forms/createPublicSpace.html.twig', array());
}
I kept trying to find a solution and i came up with the idea that one form needs one entity. So maybe the solution would be to merge those entities in one so i can build the form easily. I would then have to persist data to corresponding tables. But i can't think of how to merge entities.
I figured out a temporary solution. For those who want to know, I manually created an entity that looks like a merge of all the entity I need. This new entity has no link with Doctrine therefore it cannot create a table. Its goal is simply to allow me to build up a form and be able to manipulate data through that form. I then assign all data submitted to corresponding entities fields and persist them to the database.
Once again i know this is not the best solution. But for some reasons I won't tell, it is for me at this moment. I hope this can help some that are in the same situation than me and do not hesitate to post links that could help or better ways to do that.
It is highly recommended to use form classes http://symfony.com/doc/current/book/forms.html#creating-form-classes
They are designed to save time and make a lot of things just easier.
However to answer your question consider the following. Your action needs to handel a post request. So catch the request object with the post data:
use Symfony\Component\HttpFoundation\Request;
public function createPublicSpaceAction(Request $request)
Then get a form builder intance and create the form:
$builder = $this->createFormBuilder();
$builder->add('floor', 'text', array(
'label' => 'Room floor',
'data' => $room->getFloor()
));
add as much form fields as you need. There are several built-in field types: http://symfony.com/doc/current/book/forms.html#built-in-field-types
Create the form:
$form = $builder->getForm();
Pass the form to your template:
return $this -> render('AcmeUserBundle:Default:Forms/
createPublicSpace.html.twig', array(
'roomForm' = $form
));
To get posted data within your action:
if ('POST' == $request->getMethod()) {
$data = $request->request->get("form");
}
And in your template you can render the form by yourself or let twig do the job:
{{ form_widget(form.floor)}}
So this are the most importend things to mention. However you should go through http://symfony.com/doc/current/book/forms.html They actually tell you everything I wrote down.
Good luck ;)
if i have two product collections is there a way to merge them into one?
for example (my final intent isn't to actually just get a collection of 2 cats, this is just to illustrate the issue):
$collection1 = Mage::getModel('catalog/category')->load(148)->getProductCollection();
$collection2 = Mage::getModel('catalog/category')->load(149)->getProductCollection();
$merged_collection = merge_collections($collection1,$collection2);
any help would be appreciated!
Assuming the items you wish to group together are of the same type and exist in the database then you can do this:
$collection1 = Mage::getModel('catalog/category')->load(148)->getProductCollection();
$collection2 = Mage::getModel('catalog/category')->load(149)->getProductCollection();
$merged_ids = array_merge($collection1->getAllIds(), $collection2->getAllIds());
// can sometimes use "getLoadedIds()" as well
$merged_collection = Mage::getResourceModel('catalog/product_collection')
->addFieldToFilter('entity_id', array('in' => $merged_ids))
->addAttributeToSelect('*');
Here I know to filter by entity_id because that is products' key field, like it is for most entity types, some flat tables have a different primary key. Often you can generalise that with one of the collection's getIdFieldName() method. Products are a bad example in this case because it's ID field name isn't filled out correctly.
Almost every (or every?) collection in Magento inherits from a Varien Data Collection. A collection is a special object that holds objects of another type. There's no method for merging collections, but you can add additional items of the appropriate type to the collection.
Code like this should get you where you want to go, although there's probably more efficient ways to loop and do the actual merging.
$collection1 = Mage::getModel('catalog/category')->load(148)->getProductCollection();
$collection2 = Mage::getModel('catalog/category')->load(149)->getProductCollection();
//load an empty collection (filter-less collections will auto-lazy-load everything)
$merged = Mage::getModel('catalog/product')->getCollection()->addFieldToFilter('entity_id',-1);
//add items from the first collection
foreach($collection1 as $item)
{
$merged->addItem($item);
}
//add items from the second collection
foreach($collection2 as $item)
{
//magento won't let you add two of the same thing to a collection
//so make sure the item doesn't already exist
if(!$merged->getItemById($item->getId()))
{
$merged->addItem($item);
}
}
//lets make sure we got something
foreach($merged as $product)
{
var_dump($product->getName());
}
I don't think there is such a method, but you can probably do something like that :
foreach ($collection1 as $item){
$collection2->addElem($item);
}
you can filter your collection directly without using 2.
$products = Mage::getModel('catalog/product');
$_collection = $products->getCollection();
->addCategoryFilter(2)
->load();
or try using 'addItem' to add your results to a collection. See also in Magento wiki
for the collection of products of several categories, you can use the following code
$collection = Mage::getModel('catalog/product')->getCollection()
->addAttributeToSelect('name')
->addAttributeToSelect('sku');
$collection->getSelect()
->join(
'catalog_category_product',
'product_id=entity_id',
array('category_id')
)
->where('catalog_category_product.category_id IN (?)', $categories);