Doctrine 2 - How can I add a CHECK .. IN constraint - doctrine-orm

How can I add a CHECK .. IN constraint, like in the code below, in Doctrine 2?
CREATE TABLE table_name (
colum_name VARCHAR(1)
CHECK (column_name IN ('A','B','C'))
);
-- edit: I use annotations to define my entities

This is not supported by the ORM itself. You can define custom DDL to be used for those columns through your metadata driver. For instance, in the AnnotationDriver you can use /** #Column(type="string", columnDefinition="VARCHAR(1) CHECK (column_name IN ('A','B','C'))") */ as defined in the Annotations Reference.
I would avoid it anyway and keep those checks on application level.

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 2.5 GUID field default value

I am trying to set a default value for an UUID type field
/**
* #var int
*
* #ORM\Column(name="uuid", type="guid", options={"default"="uuid_generate_v4()"})
* #ORM\Id()
* #ORM\GeneratedValue(strategy="UUID")
*/
private $uuid;
However this sets executes
ALTER TABLE store ALTER uuid SET DEFAULT 'uuid_generate_v4()';
and takes it as text. How do I define a DB function as default in doctrine annotations?
On creation table you can use this annotation
/**
* #ORM\Column(name="uuid", type="guid", columnDefinition="DEFAULT uuid_generate_v4()", options={"comment"="Column Comment Here"})
* #ORM\Id()
* #ORM\GeneratedValue(strategy="UUID")
*/
private $uuid;
The ColumnDefinition append the content to DDL see Doctrine Documentation
The SQL output for this config is
ALTER TABLE table_name ADD uuid DEFAULT uuid_generate_v4();
COMMENT ON COLUMN table_name.uuid IS 'Column Comment Here';
These annotation does nothing on CHANGE COLUMN. Only works on ADD COLUMN generated SQL. You must recreate the column or change your table by hand.
IMPORTANT NOTE:
For those that looking for create UUID Column Type in PostgreSQL, keep in mind that you need to enable some Extension to use functions that create uuid-hashes.
In the example, uuid_generate_v4() is derived from UUID-OSSP and older versions of PostgreSQL don't support it.
Instead UUID-OSSP you can use gen_random_uuid() function from PGCRYPTO. The UUID resultant is the same version (v4). Again, older versions doesn't support it.
Just remember to Install the Extension with Create Extension.
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; // OR
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
ANOTHER IMPORTANT NOTE: In some PostgreSQL installations (like CentOS), extensions are not included by default. You must install them.
For CentOS/RHEL you need to install postgresql-contrib. Pay attention to the version of your PostgreSQL. I.e. for version 9.5 you must use postgresql95-contrib
My Privileges are weak
There's a trick to create uuid hashes without extensions. Just use the instruction above.
uuid_in(md5(random()::text || clock_timestamp()::text)::cstring);
If your version suport ::UUID casting, use
md5(random()::text || clock_timestamp()::text)::uuid

Determine if target entity is a foreign key in Doctrine filter

Doctrine passes a $targetEntity and $targetTableAlias to the filter constraint like so:
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{ ...
It appears that all entities pass through the filter when a query is being built. Is there any way to determine if $targetEntity is a foreign key or not? I'd like to write a filter that works on the "primary" entity (what Doctrine calls the "base" table) but not its foreign keys.
Your question is not very clear and I am not sure if this will answer your question, but in the Doctrine 2 documentation chapter 30. Filters you can read the following:
In the case of joined or single table inheritance, you always get passed the ClassMetadata of the inheritance root. This is necessary to avoid edge cases that would break the SQL when applying the filters.
So I would say the $targetEntity is always the root entity (so never a foreign key).
If this doesn't answer your question I would like to ask you to be a bit more specific on what exactly you want to do or what you want to find out.

The differences between GeneratedValue strategies

In the Doctrine docs they mention that there exists a few different strategies for the #GeneratedValue annotation:
AUTO
SEQUENCE
TABLE
IDENTITY
UUID
CUSTOM
NONE
Would someone please explain the differences between all thees strategies?
Check the latest doctrine documentation
Here is a summary :
the list of possible generation strategies:
AUTO (default): Tells Doctrine to pick the strategy that is preferred by the used database platform. The preferred strategies are IDENTITY for MySQL, SQLite and MsSQL and SEQUENCE for Oracle and PostgreSQL. This strategy provides full portability.
SEQUENCE: Tells Doctrine to use a database sequence for ID generation. This strategy does currently not provide full portability. Sequences are supported by Oracle and PostgreSql and SQL Anywhere.
IDENTITY: Tells Doctrine to use special identity columns in the database that generate a value on insertion of a row. This strategy does currently not provide full portability and is supported by the following platforms:
MySQL/SQLite/SQL Anywhere => AUTO_INCREMENT
MSSQL => IDENTITY
PostgreSQL => SERIAL
TABLE: Tells Doctrine to use a separate table for ID generation. This strategy provides full portability. This strategy is not yet implemented!
NONE: Tells Doctrine that the identifiers are assigned, and thus generated, by your code. The assignment must take place before a new entity is passed to EntityManager#persist. NONE is the same as leaving off the #GeneratedValue entirely.
SINCE VERSION 2.3 :
UUID: Tells Doctrine to use the built-in Universally Unique Identifier generator. This strategy provides full portability.
Ofcourse the accepted answer is correct, but it needs a minor update as follows:
According to Annotation section of the documentation:
This annotation is optional and only has meaning when used in conjunction with #Id.
If this annotation is not specified with #Id the NONE strategy is used as default.
The strategy attribute is optional.
According to Basic Mapping section of the documentation:
SEQUENCE: Tells Doctrine to use a database sequence for ID generation. This strategy does currently not provide full portability. Sequences are supported by Oracle, PostgreSql and SQL Anywhere.
IDENTITY: Tells Doctrine to use special identity columns in the database that generate a value on insertion of a row. This strategy does currently not provide full portability and is supported by the following platforms:
MySQL/SQLite/SQL Anywhere (AUTO_INCREMENT)
MSSQL (IDENTITY)
PostgreSQL (SERIAL).
Downvote
Regarding the downvote given by someone, it should be noted that SQL Anywhere has been added and the accepted answer needs a minor update.
From the perspective of a programmer, they all achieve the same result: that is to provide a UNIQUE value for the primary key field. Strictly speaking, there are two further conditions which are also met, namely: the key must also be mandatory and not null.
The only differences lie in the internal implementations which provide the primary key value. In addition, there are performance and database-compatibility factors which also need to be considered. Different databases support different strategies.
The easiest one to understand is SEQUENCE and this is generally also the one which yields the best performance advantage. Here, the database maintains an internal sequence whose nextval is accessed by an additional SQL call as illustrated below:
SELECT nextval ('hibernate_sequence')
The next value is allocated during insertion of each new row. Despite the additional SQL call, there is negligible performance impact. With SEQUENCE, it is possible to specify the initial value (default is 1) and also the allocation size (default=50) using the #SequenceGenerator annotation:
#SequenceGenerator(name="seq", initialValue=1, allocationSize=100)
The IDENTITY strategy relies on the database to generate the primary key by maintaining an additional column in the table whose next value is automatically generated whenever a new row is inserted. A separate identity generator is required for each type hierarchy.
The TABLE strategy relies on a separate table to store and update the sequence with each new row insertion. It uses pessimistic locks to maintain the sequence and as a result is the slowest strategy of all these options. It may be worth noting that an #TableGenerator annotation can be used to specify generator name, table name and schema for this strategy:
#TableGenerator(name="book_generator", table="id_generator", schema="bookstore")
With the UUID option, the persistence provider (eg Hibernate) generates a universally unique ID of the form: '8dd5f315-9788-4d00-87bb-10eed9eff566'. To select this option, simply apply the #GeneratedValue annotation above a field declaration whose data type is UUID; eg:
#Entity
public class UUIDDemo {
#Id
#GeneratedValue
private UUID uuid;
// ...
}
Finally, the AUTO strategy is the default and with this option, the persistence provider selects the optimal strategy for the database being used.

Doctrine ORM error : Unknown column type varchar requested

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