I am relatively new to Doctrine, but fairly proficient in SQL. I can't seem to effectively convert the following MySQL query to Doctrine in a Symfony 2.3 application:
select
asset.id as asset_id,
orgAsset.organization_id,
districtAsset.district_id,
deptAsset.department_id,
subjectAsset.subject_id,
schoolAsset.school_id,
teacherAsset.teacher_id,
sectionAsset.section_id,
syllabusAsset.syllabus_id
from asset
left join organizations_assets orgAsset on asset.id = orgAsset.asset_id
left join districts_assets districtAsset on asset.id = districtAsset.asset_id
left join departments_assets deptAsset on asset.id = deptAsset.asset_id
left join subjects_assets subjectAsset on asset.id = subjectAsset.asset_id
left join schools_assets schoolAsset on asset.id = schoolAsset.asset_id
left join teachers_assets teacherAsset on asset.id = teacherAsset.asset_id
left join sections_assets sectionAsset on asset.id = sectionAsset.asset_id
left join syllabus_assets syllabusAsset on asset.id = syllabusAsset.asset_id
where asset.id = ?;
All the *_assets
tables are one-way many-to-many tables with the *
objects joined to Asset
objects.
My first goal is to just get this kind of query to work using Doctrine. My end-goal is for Doctrine to return only the objects that are associated with the asset. Here is an example of my one-way many-to-many object mapping. There is no reciprocal mapping in the Asset
object:
class Organization
{
...
/**
* @ORM\ManyToMany(targetEntity="Asset")
* @ORM\JoinTable(name="organizations_assets",
* joinColumns={@ORM\JoinColumn(name="organization_id", referencedColumnName="id", nullable=true)},
* inverseJoinColumns={@ORM\JoinColumn(name="asset_id", referencedColumnName="id")}
* )
*
* @var ArrayCollection|Asset[]
*/
protected $assets;
...
}
The objects that extend Asset
are too complex to realistically refactor to single table inheritance.
Is the one-way mapping the issue? Am I going to need to create a native query to handle this? I find it difficult to believe that Doctrine can't natively handle this, so I hope I'm overlooking something simple.
As I'm learning more about Doctrine, there is a simple reason this does not work. There are no mappings in Asset
back to any of the organizational entities. In other words, while an Organization
has Assets
, an Asset
does not have an Organization
, School
, District
, etc..
As I see it, here are a couple of solutions to this problem:
1) Create the association to each organizational object in Asset
. This is not sexy, and may be inefficient.
2) Create an AssetContainer
and leverage inheritance (probably single-table) for each organizational object. This is sexy, but would involve some refactoring. It would look something like this:
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({"organization" = "OrganizationAsset", "district" = "DistrictAsset"})
*/
class AssetContainer
{
protected $id;
protected $asset; // join to Asset
}
class OrganizationAsset extends AssetContainer
{
protected $organization; // join to Organization
}
class DistrictAsset extends AssetContainer
{
protected $district; // join to District
}
class Asset
{
...
protected $assetContainers; // join to AssetContainer
...
}
3) Run a simple SQL query (see OP) and hydrate as necessary. Not quite as sexy as #2, but a good quick-fix without refactoring.
I'm pretty sure I'm going with #2 or #3. If I go with #2, I will report back on the results.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.