Doctrine relation betwen two tables - doctrine

I have two tables A and B. A have one or more registers in B.
I want to join two tables and extract all information about A.
I do that:
Schema.yml
A:
fields.....
B:
fields...
relations:
A: { onDelete: CASCADE, local: a.id, foreign: b.id, foreignalias: AB }
And i try to do that...
$q = Doctrine_Query::create()
->from('A a')
->leftJoin('a.AB b')
->where('a.field = "D"')
->andWhere('b.codzon = ?', $this->cp);
It prints me error: Unknown relation alias AB
What i am doing wrong?

Your query seems to be ok, errors are in you sheme definition. You need to define relations on both sides: A and B. I am not very comfortable with YML, but it should look like this:
A:
relations:
B:
local: id
foreign: id
foreignAlias: AB
foreignType: many
type: one
See also http://www.doctrine-project.org/documentation/manual/1_0/ru/yaml-schema-files#relationships:one-to-many for detect_relations option.

Remove table names from schema:
...
A: { onDelete: CASCADE, local: id, foreign: id, foreignalias: AB }
...

Related

Laravel & relationships

I am building a web app using Laravel (5.7). At some point, the user must input his location that is comprised of:
Country
State
City
So for this, I created 4 tables:
Countries table:
Columns: id, name
Relations: hasMany states
States table:
Columns: id, country_id, name
Relations: hasMany cities, belongsTo country
Cities table:
Columns: id, state_id , name
Relations: hasMany Locations, belongsTo state
Locations table:
Columns: id, city_id, name
Relations: belongsTo City
My questions are:
1) Is this the correct approach?
2) Obviously, there are countries out there without the "state" segmentation. If this is the case, how are we going to move up to the Country (using relationships) when the state is not present?
3) How do we know the minimum Eloquent relationships we can use on each model? Because a country also has a lot of cities. Do we use this relationship as well, or is it OK because states has a lot of cities?
I would be very happy if someone helped me clear this out. Its been bothering me for quite some time.
Thanks in advance.

How to avoid duplicate field name in query result

I am developing a padrino web application. I have two tables:
User table: Has id, name, address fields
Post table: Has id, user_id, content
If I join them,
User.join(:posts, user_id:, :id)
they return two fields with the same name id:
id name address id user_id content
1 jim *** 3 1 post1
I would like to rename each of these ids. I want the result to be:
u_id name address p_id user_id content
1 jim *** 3 1 post1
I am using Sequel adapter for postgresql db in padrino project.
In mysql query, it will be like this:
select u.id as u_id,
u.name,
u.address,
p.id as p_id,
p.user_id as user_id,
p.content
from users u
join posts p on u.id = p.user_id
what should I do?
What I want is not sql query, but code of ruby language. Thanks.
You should use Dataset#select to set which columns are being selected:
User.from{users.as(:u)}.join(Sequel[:posts].as(:p), user_id: :id).
select{[u[:id].as(:u_id), u[:name], u[:address],
p[:id].as(:p_id), p[:user_id].as(:user_id), p[:content]]}

How to fetch records using predicate from A having relationship with A<-->B<-->C with coredata

I have three entities A,B,C.
EntityA:
Properties:
Id,Name
Relationships:
ABRelation(A-->>B)
EntityB:
Properties:
Id,Name
Relationships:
BARelation(B-->A)
BCRelation(B-->>C)
EntityC:
RoleId
CBRelation(C-->>B)
Now I need to fetch records from Entity A having some RoleId = 23 which is contain in C.
Could you please help me quickly.Thanks in Advance.
SELECT a.Id, a.Name,
FROM EntityA a INNER JOIN EntityB b
ON a.Id= b.EntityA_Id(foriegn key) JOIN EntityC as c
ON b.EntityC_Id(foriegn key) = c.Id
WHERE c.RoleId=23

translate raw MySQL into Doctrine 1.2

I'm having a heck of a time translating the following raw MySQL query, which has been tested and works very well, into doctrine 1.2:
SELECT
r.name AS regionname,
s.name AS statename
FROM
job j
LEFT JOIN
community c ON c.id = j.community_id
LEFT JOIN
state s ON s.id = c.state_id
LEFT JOIN
region r ON r.id = s.region_id
WHERE
r.id = 1
This does not work:
$q = Doctrine_Query::create()
->select('r.name AS regionname', 's.name AS statename')
->from('job j')
->leftJoin('community c ON c.id = j.community_id')
->leftJoin('state s ON s.id = c.state_id')
->leftJoin('region r ON r.id = s.region_id')
->where('r.id = 1')
->execute();
Here's my db structure, if it is useful:
job:
columns:
id
community_id
relations:
community: local_key: community_id, foreign_key: id, foreignAlias: Communitys
community:
columns:
id
state_id
relations:
state: local_key: state_id, foreign_key: id, foreignAlias: States
state:
columns:
id
name
region_id
relations:
region: local_key: region_id, foreign_key: id, foreignAlias: Regions
region:
columns:
id
name
I have noticed the same thing as well. Doing joins in Doctrine 1.2 is a little bit different from mysql. To do a join, you have to take advantage of the relationships that Doctrine creates in each component in your case the job class.
You can check the job's base class for these relationships I am talking about. In the setup method, they look like this for example for a community foreign key id in the job table:
$this->hasOne('community as Communitys', array(
'local' => 'community_id',
'foreign' => 'id'));
Back to your question, to do a join you have to reference the alias of the table where the foreign key belongs to. For example if you want to join on the community table with the alias Community:
->leftJoin('j.Community')
instead of
community c ON c.id = j.community_id
Notice that I didn't say join on id because in Doctrine 1.2 that is implied already. You can however choose to join on something else.
Likewise if tables you have previously joined to need to be joined to other tables they have foreign keys to you have to
1.use their alias in the current queryand
2.reference the component as stated in THEIR base class as well.
So you said that you want to join community to states in the current query the way you should do it is
// join job and community first
->from('job j')
->leftJoin('j.Community c')
// join community to state since they are the ones that are related
->leftjoin('c.States s')
From here I hope you can see the pattern. At the end of the day if you look at it the idea of joining is still the same with raw sql, the only difference is the syntax:
SQL syntax:
LEFT JOIN
community c ON c.id = j.community_id
DQL syntax:
->leftJoin('j.Community c')
Anyway to answer your question, here is how the join should somewhat be done:
$q = Doctrine_Query::create()
->select('*')
->from('job j')
->leftJoin('j.Community c')
->leftJoin('c.State s')
->leftJoin('s.Region r')
->where('r.id = 1')
->execute();

Views in Doctrine ORM

I encountered a problem dealing with views in Doctrine.
I have the following view in my database:
$q = Doctrine_Query::create()
->select('c.id, c.name, m.id, m.name, m.status,
m.modified, m.entered, m.accountid')
->from('Category c')
->leftJoin('c.Mailing m');
$view = new Doctrine_View($q, 'view_mailings');
$q->execute(array(), Doctrine::HYDRATE_ARRAY);
The result comprises of all records. However I need to fetch a subset
based on different value for accountid and ordered by different
columns. How can I achieve this?
Thanks for your help.
A different solution could be creating a schema for the view inside config/doctrine/ like this:
objective:
tableName: objective
columns:
id:
type: integer
zone:
type: string(50)
province:
type: string(30)
city:
type: string(100)
population:
type: integer
city_obj_id:
type: integer
clinic_number:
type: integer
clinic_obj:
type: integer
comments:
type: string(255)
and then put a objective_view.sql inside data/sql/ like this:
DROP VIEW IF EXISTS objective;
DROP TABLE IF EXISTS objective;
CREATE VIEW objective AS
SELECT
c.id as id,
z.name as zone,
p.name as province,
c.name as city,
cs.amount as population,
co.id as city_obj_id,
co.clinic_num as clinic_number,
co.clinic_obj as clinic_obj,
co.comments as comments
FROM
city c left join city_objective co on co.city_id = c.id
left join city_census cs on (cs.city_id = c.id and cs.year = 2009)
left join province p on p.id = c.province_id
left join zone z on z.id = p.zone_id;
In this way the objective table will get populated with updated data and you can execute query on it to get relevant info with ease.
You are just executing the query $q, without using the view you have created.

Resources