I'm working on a web project that contains a mixture of Doctrine and traditional inline SQL for database access. We're migrating from the latter to the former over time.
One of the database tables (Table A) has an informal foreign key (i.e. there are no actual constraints in the SQL table definition) column. The value in this column is nullable, but sometimes the value in this column refers to a another table's (Table B) primary key that has since been deleted.
Table A's relationship with Table B is formalised in Table A's entity definition in Doctrine. When I create an instance of an entity from an existing row in Table A and the informal foreign key column has a value that is no longer in Table B, then it seems an invalid Table B entity is created. I.e. the object is set, and I can query it's id through the TableB->getId() method we have authored, but any other TableB->getProperty() fails and throws an error.
Since I'm already working with historic data, I need a run-time solution to this. I need to identify via a check if the Table B entity is valid.
I could put it in a try-catch loop, but this is not a common pattern in our code base and does not seem very elegant.
Is there a canonical method for checking the validatity of a Doctrine entity to solve this problem?
Thank you
As I see it, there are 2 things you should do.
First fix your data corruption, this is a must. If A points to a non-existing B, then A should not be pointing at all. SELECT a.id FROM table_a a LEFT JOIN table_b b ON b.id = a.table_b_id WHERE b.id IS NULL. This query will select all FK that are not existing anymore, you can simply update the a.table_b_id to NULL with that list.
Second, you should (not in your getter) take care of the relation issue in your code. I'm not sure if Doctrine throws an EntityNotFoundException or only does this with find($pk), but I'm sure you can check if the return of your getter is null or catch that exception.
Related
As to implement a N:M relationship of tables USERS (PK: user_id which is auto increment INT) and REQUESTS(PK: request_id which is auto increment INT), I've created the intermediate table USERS_GROUPS (PKs: two FKs US_userid, US_requestid which coincide with the PKs of USERS and REQUESTS). When a user creates a new request I have to create a new record inside REQUESTS.
INSERT INTO REQUESTS (...) VALUES (...);
At the same time I want to create a new record inside USERS_GROUPS as to join USERS_GROUPS with USERS and REQUESTS. The value of the first FK pointed to USERS is known to me, however how may I find the value of the second FK pointed to the record I've just created?
In other words, I want to find the value of the field request_id of the record I've just created. This seems a little bit confusing to me and I don't know how to implement it.
INSERT INTO USERS_GROUPS (US_userid,US_request_id) VALUES (...,?????);
This is my first serious db schema I've ever created and my first n:m relationship I have to manage. Is my point of view correct? If yes, I 'd appreciate your help in how to realise it. If not which is the right approach?
You can use last-insert-id to retrieve the newly created id.
The library you use to connect to database usually has a function for it, such as mysqli_insert_id or PDO::lastInsertId.
Sidenote: Because you are performing multiple (independent) queries on the database it may be necessary to wrap it all in transaction.
I have a use case where I have to execute a set of alter table queries on my DB and all the queries are to do with adding foreign key constraints.
Let's say there are 2 tables A and B, A.id references B.id, but some A.id are not present in B.id which I can just delete as I'm not interested in such records.
But I can't just delete them since there are few tables that are referencing table A's columns.
This dependency grows like a tree. Now I want to resolve this dependency programmatically.
Is there any existing library I can use for this (preferably php)?
I should be able to interpret the SQL errors and construct the appropriate query based on the errors and execute them.
We can safely assume that all these errors are foreign key constraints which are conflicting.
SELECT
*
FROM table1
LEFT JOIN table2
ON table1.id=table2.ref
How to distinctly identify column which are from table1 or table2. Is there anyway to get table name in alias which can be used to identify column by table name?If it matters i am using PHP to fetch from database.
Well, your reason is fair but the implementation is unusual.
When each table represents a class in php, it is called ORM - Object-relational mapping.
And when it is used, an object already knows it's fields, because each table being only a reflection of the class properties. Frankly, with ORM nobody is going to create tables manually - they are created (or altered) based on the object properties.
So, an object always can tell it's fields from others.
As for your literal question - no, there is no way to get such info, as far as I know
Having the follow basic tables (one-to-many relationship)
Client - Has many users.
Users - Each user belongs to single client.
In a very simple example if I query the user entity (Querybuilder)
with getArrayResult() I see the following:
The actual generated SQL contains the foreign key field to be
returned (i.e. ClientID)
The actual returned data array does NOT contain the foreign key
field.
At this stage I do not need to return foreign data and so do not need
to join to the associated table.
So question is...
What or how do I return the foreign key value in my array?
Query is:
$qb = $this->_em->createQueryBuilder();
$qb->select('e');
$qb->from('Entity\User', 'e');
SQL is:
SELECT w0_.Id AS Id0, w0_.Name AS Name2, w0_.ClientID AS ClientID7
FROM users w0_
Try to set the HINT_INCLUDE_META_COLUMNS query hint on the query (not the builder) before you execute it.
$q->setHint(Query::HINT_INCLUDE_META_COLUMNS, true);
As far as I know, you can't do this, because ClientID is not a property of User. User has a property like $client, and that client entity has an $id.
This is confusing you because you're dealing with Entites but you're still thinking in SQL.
The solution, though slightly less efficient, would probably be to join the Client entity into your DQL query, and then get $results[N]['client']['id'] (or similar, I'm not too familiar with getResultArray())
I can't find how to insert a row that doesn't have a PK. This isn't possible with a class that is extending Zend_Db_Table_Abstract, so how should I do this?
The table I in which I want to insert records is a join table.
The only two columns in it could serve as a PK, but I don't know how I should let Zend know that neither.
Any suggestions?
Zend doesn't really care if the table have in fact a PK (or an index) or not. The primary_key option in a Zend_Db_Table_Abstract is really just to know which column the 'WHERE' clause will search for when using find and find* methods, etc. So, basically, just specify which columns to use as reference columns for your db model. I can't give you more details since I don't know the details of the said table.