简体   繁体   中英

Doctrine2 / Symfony2: One-Way Many-to-Many Query with Left Join

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM