getArrayResult on entity with ManyToOne association - php

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())

Related

Using Laravels Eloquent with database views

I have two database tables, expenses and incomes and I created a MySQL view, transactions, which basically is an UNION between the two tables, selecting the fields I am interested in.
The transactions view contains the following columns:
transaction_id
user_id
amount
note
transaction_type
updated_at
created_at
I created an Eloquent Model for the view, called Transactions.
The problem is when I want to retrieve transactions based on certain criteria.
E.g. I want to get all transactions for a User. Normally, if transactions was a table, I would define a foreign key relationship and I would simply call $user->hasMany('App\Models\Transaction').
Since foreign keys are not possible for views, I tried using the 'where' method: Transaction::where('user_id', $user->id). This query does not return anything, neither do any other queries I tested. The only method that returned data is Transaction::all(), but this doesn't help me very much.
What am I doing wrong?
For where statement in Eloquent you must to end up with get, try this:
$transactions = Transaction::where('user_id', $user->id)->get();

PHP implementation of n:m relationship

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.

Invalid Doctrine Entity being created

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.

Getting table name in joined mysql query result

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

PHP Sorting from Serialized data

I have a MySQL table with clients in it, the usual data, names, addresses, phone numbers etc etc i also have a field which is called 'roles' in which a client ticks off what they like to do i.e coding, graphic design, illustrations etc etc .. this data gets pushed into the field serialized with each roles code, the following is an example.
a:3:{s:4:"_wfa";s:2:"on";s:3:"_CS";s:2:"on";s:3:"_CM";s:2:"on";}
On a 'viewall' page, i need to output all the details for a user that has ticked a specific box, as an example, i need to output all users that have ticked the '_wfa' box.
I hope this makes sense, i cant seem to figure out how to do it.
I hope someone can shed some light on this.
Cheers,
You should never have more than one value in a single column of a row. Store the roles in their own database table, with the user's ID, and you will be able to simply ask MySQL for the users with a role as desired.
CREATE TABLE user_roles (user_id INT, role_name VARCHAR(100));
INSERT INTO user_roles (1, '_wfa');
INSERT INTO user_roles (1, '_CS');
INSERT INTO user_roles (1, '_CM');
SELECT users.id FROM users INNER JOIN user_roles ON users.id = user_roles.user_id WHERE user_roles.role_name = '_wfa';
You should normalise that into a table. Having it serialised means you can not use any of the benefits of SQL on it, and also that parsing it requires PHP (or custom code for other language).
MySQL, or any database, can not unserialize data performed by an external programming language. The only way to get the data out, is to pull it out and unserialize in PHP before you can use the data.
The only way to get any value out of using a database is to store data in it, using tables and native data types to enforce data consistency. Normalization and referential integrity work to minimize data duplication while enforcing business rules.
Transitioning to SQL, objects become tables -- they're like arrays. Object attributes become columns, but when an object contains an array of other objects - that attribute gets promoted to being a table... Normalization means taking things like roles, and making a code table for them that you can refer to in other tables.

Categories