Doctrine ORM error : Unknown column type varchar requested - doctrine-orm

Ok, so i just assigned a new project which uses Doctrine and Zend. This is my first time using Doctrine, and i came upon an error for which google didn't came up with any answer.
I added a new field (VARCHAR 17) to a table, added getter/setter functions in the Entity for that table, then ran orm:generate-proxies.
All good, except now i am getting this error when trying to save anything: Unknown column type varchar requested.
Any thoughts?

The problem is, that doctrine annotation doesn't know about the underlying database. So what you have to do is mark your field as type string with length of 17 in your case:
/**
* mySuperField
* \ORM\Column(name="mySuperField", type="string", length=17)
*/
$mySuperField;
For reference about how to map entity properties see also Doctrine Basic Mapping

At first learn about doctrine commands
orm:generate-entities to write getter/setter functions in the Entity files,
orm:schema-tool:update to update db tables,
you should not do this work manually, just write yaml/xml/php schema and run them.
If you use Bisna library to integrate doctrine2 with zf, there must be "adapterClass" and "mappingDirs[]" options in application.ini file to describe where schema files are.
Use type "string" instead of varchar in entity and schema files.
I prefer yaml schemas:
username:
type: string
length: 17

Related

Doctrine Nothing to update after adding onDelete="CASCADE"

I want to add the option onDelete="CASCADE" on one of my attributes via the #JoinColumn annotation:
/**
* #ORM\OneToMany(targetEntity="AppBundle\Entity\Product",mappedBy="category",fetch="EAGER")
* #ORM\JoinColumn(onDelete="CASCADE")
*/
private $products;
But when I try to update with php bin/console doctrine:schema:update --force , I always get:
nothing to uptade - database already sync.
I tried to add some other attributes and I got the same issue. However, if I intentionally add a mistake I get an error as expected.
How can I fix this?
The #OneToMany annotation is the one you use on the inverse side of your many-to-one association. The table storing the entities on this side of the association does not hold any foreign key pointing to the table storing your Product entities, thus there is no "join column" there.
The documentation states the following about #JoinColumn:
This annotation is used in the context of relations in #ManyToOne, #OneToOne fields and in the Context of #JoinTable nested inside a #ManyToMany.
In your case, the annotation does not apply to any column at all and consequently, your database does not need to be updated.
If you wish to have Product entities related to a given Category removed through cascade operations by your database, you have to add a #JoinColumn(onDelete="CASCADE") on the owning side of the association, next to the #ManyToOne annotation of the category attribute of Product.

Doctrine swap out table at runtime

Typically when you implement a entity using Doctrine you map it to a table explicitly:
<?php
/**
* #Entity
* #Table(name="message")
*/
class Message
{
//...
}
Or you reply on doctrine to implicitly map your class name to a table...I have several tables which are identical in schema but I do not wish to re-create the class for each time...there fore at runtime (dynamically) I would like to change the table name accordingly.
Where do I start or what would I look into overriding to implement this odd requirement???
Surprisingly (to me), the solution is very simple. All you have to do is to get the ClassMetadata of your entity and change the name of the table it maps to:
/** #var EntityManager $em */
$class = $em->getClassMetadata('Message');
$class->setPrimaryTable(['name' => 'message_23']);
You need to be careful and do not change the table name after you have loaded some entities of type Message and changed them. It's a big chance it will either produce SQL errors on saving (because of table constraints, for example), if you are lucky or it will modify the wrong row (from the new table).
I suggest the following workflow:
set the desired table name;
load some entities;
modify them at will;
save them;
detach them from the entity manager (the method EntityManager::clear() is a quick way to start over);
go back to step 1 (i.e. repeat using another table).
The step #5 (detach the entities from the entity manager) is useful even if you don't change or don't save the entities. It allows the entity manager use less memory and work faster.
This is just one of the many methods you can use to dynamically set/change the mapping. Take a look at the documentation of class ClassMetadata for the rest of them. You can find more inspiration in the documentation page of the PHP mapping.

merge in doctrine 2 not working giving error

I am trying to update a row in a table. I am using doctrine 2 ORM. I am trying to update a row using merge(), which is said can be used to update a row. But it gives a error saying
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry
I am new to doctrine 2. please suggest what can i do?
When to merge
First off: You only need $em->merge() when you have an entity that isn't managed by the EntityManager, but you want it to be. A common use-case is when you have a serialized entity, and want the EntityManager to start managing it.
So merging entities is not directly related to updating entities in the database.
If you simply find (using $repo->find*()) an entity and make changes, calling $em-flush() is sufficient. The entity is already managed by the EntityManager and there's no need to merge it.
How to merge
A common mistake when using $em->merge() is that the passed entity itself becomes managed. This isn't true, $em->merge() returns a new object that represents the managed entity.
$managedEntity = $em->merge($detachedEntity);
After this line of code, $detachedEntity is still detached (meaning it still isn't managed by the EntityManager). It's $managedEntity which you can start using to make changes.
Your code
Given the code you've put in the comments, you probably want to do something like this:
$user = $entityManager->getRepository('User')->find($_REQUEST['id']);
$user->setName($_REQUEST['name']);
$user->setPassword($_REQUEST['pass']);
$entityManager->flush();
PS: It looks like you're saving the the plain-text password in the database. That's never a good idea.

Can you define a maybe property that is not nullable in Yesod Persist?

I am still quite new to Yesod so I might be missing something essential.
My understanding is that adding the Maybe attribute to a Persist Entity field seems to both make the attribute non nullable in the database as well as wrapping it in a Maybe in the Data definition. I tried creating a test Entity with a timestamp that has a default=CURRENT_TIME. If I now send a JSON representation of this entity without the timestamp, I get an error about the missing timestamp when I try to use requireJsonBody. I guess I could add Maybe to the timestamp to get the JSON parsing to succeed. But then I would not have the non null constraint for the column in the database anymore?

Using column length to validate

/**
* #Column(type="string", length=10)
*/
protected $name;
What exactly is the purpose of 'length'?
http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/annotations-reference.html#annref-column
At the above URL it states: "length: Used by the 'string' type to determine its maximum length in the database. Doctrine does not validate the length of a string values for you."
I have the length defined in my database, so what is the point of adding 'length' in Doctrine? Does 'length' have anything to do with validation?
The only thing I can figure out is it cuts off the excess characters before trying to insert it into the database. Very annoying when I want an exception or error.
Thanks :D
Doctrine does not apply any kind of validation on your entities: it just loads and saves data applying the required type conversions (and fails if something is wrong with your objects).
The length attribute is there just to aid during schema generation when you use Doctrine's schema tools.
You can still extract that value with the metadata API of Doctrine 2 ORM eventually, but consider using a proper validation library for such tasks.