<![CDATA[ Working with related objects causing error - My Forums]]> https://forums.modx.com/thread/?thread=98268 <![CDATA[Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531312
this is my schema:

<?xml version="1.0" encoding="UTF-8"?>
<model package="storefinder" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" phpdoc-package="storefinder" phpdoc-subpackage="model" version="1.1">
  <object class="sfStore" table="sfinder_stores" extends="xPDOSimpleObject">
    <field key="name" dbtype="varchar" precision="100" phptype="string" null="false" default="" index="index" />
    <field key="address" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
    <field key="city" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
    <field key="state" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
    <field key="zip" dbtype="varchar" precision="10" phptype="string" null="false" default="0" index="index" />
    <field key="country" dbtype="varchar" precision="20" phptype="string" null="false" default="" />
    <field key="phone" dbtype="varchar" precision="20" phptype="string" null="false" default="" />
    <field key="fax" dbtype="varchar" precision="20" phptype="string" null="false" default="" />
    <field key="active" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="false" default="0" />
    <alias key="postalcode" field="zip" />
    <index alias="name" name="name" primary="false" unique="false" type="BTREE">
        <column key="name" length="" collation="A" null="false" />
    </index>
    <index alias="zip" name="zip" primary="false" unique="false" type="BTREE">
        <column key="zip" length="" collation="A" null="false" />
    </index>
<composite alias="StoreOwners" class="sfStoreOwner" local="id" foreign="store" cardinality="many" owner="local" />
  </object>
  <object class="sfOwner" table="sfinder_owners" extends="xPDOSimpleObject">
    <field key="name" dbtype="varchar" precision="100" phptype="string" null="false" default="" index="index" />
    <field key="email" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
    <index alias="name" name="name" primary="false" unique="false" type="BTREE">
        <column key="name" length="" collation="A" null="false" />
    </index>
<composite alias="StoreOwners" class="sfStoreOwner" local="id" foreign="owner" cardinality="many" owner="local" />
  </object>
  <object class="sfStoreOwner" table="sfinder_store_owners" extends="xPDOSimpleObject">
    <field key="store" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" index="index" />
    <field key="owner" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" index="index" />
    <index alias="store" name="store" primary="false" unique="false" type="BTREE">
        <column key="store" length="" collation="A" null="false" />
    </index>
    <index alias="owner" name="owner" primary="false" unique="false" type="BTREE">
        <column key="owner" length="" collation="A" null="false" />
    </index>
<aggregate alias="Store" class="sfStore" local="store" foreign="id" cardinality="one" owner="foreign" />
<aggregate alias="Owner" class="sfOwner" local="owner" foreign="id" cardinality="one" owner="foreign" />
  </object>
</model>


This is my snippet to join all owners to a certain store:

$modx->addPackage('storefinder', MODX_CORE_PATH . 'components/storefinder/model/');

$store = $modx->getObject('sfStore', 1);
$owners = $modx->getCollection('sfOwner');

$store->addMany($owners);
$store->save();


The snippet call is not successful and returns the following error:

[2015-09-10 13:51:14] (ERROR @ /index.php) No foreign key definition for parentClass: sfStore using relation alias: sfOwner

Any idea why this is happening? All of my other test cases like removing related objects etc are working fine...]]>
mojorisin Sep 10, 2015, 07:24 AM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531312
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531823
- sfStore
-- StoreOwners relation to sfStoreOwner (id=store)
- sfOwner
-- StoreOwners relation to sfStoreOwner (id=owner)
- sfStoreOwner
-- Store relation to sfStore (store=id)
-- Owner relation to sfOwner (owner=id)

These are the only relations xPDO knows off, as those are in your schema and model.

What you're trying to do in this code:
$modx->addPackage('storefinder', MODX_CORE_PATH . 'components/storefinder/model/');
 
$store = $modx->getObject('sfStore', 1);
$owners = $modx->getCollection('sfOwner');
 
$store->addMany($owners);
$store->save();


is add a bunch of sfOwner records directly to sfStore records. However, there is no direct relation between sfStore and sfOwner - there is only sfStore -> StoreOwners relation -> sfStoreOwner -> Owner relation -> sfOwner. That's what the error message is telling you, it doesn't know what to do with the sfOwner records you are trying to add. It only knows what to do with sfStoreOwner records.

Bobs example code for your other schema is the right way to go about this; managing the sfStoreOwner records directly.

$modx->addPackage('storefinder', MODX_CORE_PATH . 'components/storefinder/model/');
 
$store = $modx->getObject('sfStore', 1);
$owners = $modx->getCollection('sfOwner');
$storeOwners = array();
foreach ($owners as $owner) {
  // before adding a new record, check if it's already there
  $so = $modx->getObject('sfStoreOwner', array('owner' => $owner->get('id'), 'store' => $store->get('id')));
  if (!$so) {
    $so = $modx->newObject('sfStoreOwner');
    $so->fromArray(array('owner' => $owner->get('id')));
    // as xPDO can manage the relation for you from this point on, supplying store is optional:
    // $so->fromArray(array('owner' => $owner->get('id'), 'store' => $store->get('id')));
    $storeOwners[] = $so;
  }
}
 
$store->addMany($storeOwners);
$store->save();


Does this mean that addMany() and addOne() is not working for custom DB tables and I need to code this manually? What is the whole point of defining relationships in the schema when xpdo doesn't take care of it? I am confused...

addMany and addOne work great for custom db tables; it just doesn't automatically deal with many-to-many intersect tables like sfStoreOwner because the relation is to the intersect table, and not the other actual data table.

If you had a one-to-many relation like this where each store has a single owner:
<?xml version="1.0" encoding="UTF-8"?>
<model package="storefinder" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" phpdoc-package="storefinder" phpdoc-subpackage="model" version="1.1">
  <object class="sfStore" table="sfinder_stores" extends="xPDOSimpleObject">
    <!-- .. insert fields and stuff .. -->
    <field key="owner" dbtype="int" precision="10" attributes="unsigned" phptype="integer" null="false" default="0" />
    <index alias="owner" name="owner" primary="false" unique="false" type="BTREE">
        <column key="owner" length="" collation="A" null="false" />
    </index>
    <aggregate alias="Owner" class="sfOwner" local="owner" foreign="id" cardinality="one" owner="foreign" />
  </object>
  <object class="sfOwner" table="sfinder_owners" extends="xPDOSimpleObject">
    <field key="name" dbtype="varchar" precision="100" phptype="string" null="false" default="" index="index" />
    <field key="email" dbtype="varchar" precision="255" phptype="string" null="false" default="" />
    <index alias="name" name="name" primary="false" unique="false" type="BTREE">
        <column key="name" length="" collation="A" null="false" />
    </index>
    <composite alias="Stores" class="sfStore" local="id" foreign="owner" cardinality="many" owner="local" />
  </object>
</model>


then your first example code would have worked perfectly.]]>
markh Sep 20, 2015, 03:05 AM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531823
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531739
That post from OpenGeek is almost 5 years old.

You might take a look at your class and map files and compare them to the ones for MODX objects like modResource, modTemplateVar, and modTemplateVarResource, to see if yours are missing something. The MODX ones are in in core/model/modx/mysql.]]>
BobRay Sep 18, 2015, 03:36 PM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531739
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531709 I did some comprehensive investigation last night and here are my results...

First of all loadClass() on all three classes is returning true

$ofcModelPath = MODX_CORE_PATH . 'components/ofc/model/';

$success = $modx->loadClass('ofc.classTags', $ofcModelPath, true, false);
if (!$success) {return 'Could not load class classTags';}

$success = $modx->loadClass('ofc.classBlogposts', $ofcModelPath, true, false);
if (!$success) {return 'Could not load class classBlogposts';}

$success = $modx->loadClass('ofc.classBlogpostsTags', $ofcModelPath, true, false);
if (!$success) {return 'Could not load class classBlogpostsTags';}


Secondly calling loadClass() on all classes involved is returning the foreign key error again

$modx->addPackage('ofc', MODX_CORE_PATH . 'components/ofc/model/');

$ofcModelPath = MODX_CORE_PATH . 'components/ofc/model/';

$success = $modx->loadClass('ofc.classTags', $ofcModelPath, true, false);
if (!$success) {return 'Could not load class classTags';}

$success = $modx->loadClass('ofc.classBlogposts', $ofcModelPath, true, false);
if (!$success) {return 'Could not load class classBlogposts';}

$success = $modx->loadClass('ofc.classBlogpostsTags', $ofcModelPath, true, false);
if (!$success) {return 'Could not load class classBlogpostsTags';}
 
$blogpost = $modx->getObject('classBlogposts', 1);
$tags = $modx->getCollection('classTags');
 
$blogpost->addMany($tags);
$blogpost->save();


[2015-09-18 09:02:33] (ERROR @ /index.php) No foreign key definition for parentClass: classBlogposts using relation alias: classTags
[2015-09-18 09:02:33] (ERROR @ /index.php) No foreign key definition for parentClass: classBlogposts using relation alias: classTags

This is pretty interesting. When leaving out the second parameter of the addMany() the error msg prints the classname of the parentClass ('classTags') where it should use the alias of the composite relationship ('aliasBlogpostsTags'). This doesn't make any sense at all. Is my code wrong?

$blogpost = $modx->getObject('classBlogposts', 1);
$tags = $modx->getCollection('classTags');
 
$blogpost->addMany($tags, 'aliasBlogpostsTags'); // the correct alias of the composite relationship
$blogpost->save();


No error msgs but also no database transactions.

$blogpost = $modx->getObject('classBlogposts', 1);
$tags = $modx->getCollection('classTags');
 
$blogpost->addMany($tags, 'classBlogpostsTags'); // class name of the composite relationship
$blogpost->save();


[2015-09-18 09:12:58] (ERROR @ /index.php) No foreign key definition for parentClass: classBlogposts using relation alias: classBlogpostsTags
[2015-09-18 09:12:58] (ERROR @ /index.php) No foreign key definition for parentClass: classBlogposts using relation alias: classBlogpostsTags

So _getAliases() is not processing or not picking up the correct relationship alias. The question is why...

I also did some further investigation in the forums and exactly the same error msg is mentioned in a couple of threads related to xpdo with many-to-many relationships and without any solution. E.g. http://forums.modx.com/thread/90890/migxdb-cmp---creating-many-to-many-relationships?page=2#dis-post-505965

Then I came across this post by opengeek http://forums.modx.com/thread/31879/starting-with-xpdo-addmany-not-working?page=2#dis-post-172412 which states that xpdo doesn't include any automatic functionality for managing intersection tables. Does this mean that addMany() and addOne() is not working for custom DB tables and I need to code this manually? What is the whole point of defining relationships in the schema when xpdo doesn't take care of it? I am confused...



]]>
mojorisin Sep 18, 2015, 02:47 AM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531709
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531670
A couple of things to try:

First, check the return value of loadClass(). It returns false on failure.

Second, it shouldn't be necessary, but you could try calling
loadClass() on the classes involved. They are supposed to be loaded automatically when needed after loadClass(), but addMany() may not trigger that for all of them. loadClass() also returns false on failure, so be sure to check that as well.]]>
BobRay Sep 17, 2015, 01:12 PM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error?page=2#dis-post-531670
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531634
Your example is working fine and doing exactly what I wanted to do.

Interestingly using an alias with addMany is not causing any error msgs in the MODx error log, but the database joins are also not coming through...soo strange.

$blogpost->addMany($tags, 'aliasBlogpostsTags');


Additionally I figured out that the "No foreign key definition for parentClass" error is printed as many times as there are objects in addMany function.

Any idea how I can investigate further why my relationships are not working? I did almost anything to debug this, but no success so far and using your provided workaround seems to be very complicated to deploy for a way more complicated schema that I have in mind for my production system. Therefore it would be much easier if the default xpdo relationship model would work...any more ideas?]]>
mojorisin Sep 17, 2015, 02:08 AM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531634
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531550
$blogpost = $modx->getObject('classBlogposts', 1);
$blogpostId = $blogPost->get('id');
$tags = $modx->getCollection('classTags');
 
foreach ($tags as $tag) {
    $tagId = $tag->get('id');
    $bpt = $modx->newObject('classBlogpostsTags');
    $bpt->set('blogpost', $blogpostId);
    $bpt->set('tag', $tagId);
    $bpt->save();
}


This should actually be a little faster than using addMany() and does essentially what it would do if it were working.

BTW, it's possible that your method would work with the addition of an alias:

$blogpost->addMany($tags, 'aliasBlogpostsTags');



]]>
BobRay Sep 15, 2015, 05:24 PM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531550
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531486
Schema:

<?xml version="1.0" encoding="UTF-8"?>
<model package="ofc" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
<object class="classBlogposts" table="test_blogposts" extends="xPDOSimpleObject">

        <field key="content" dbtype="text" phptype="string" null="true" />

        <composite alias="aliasBlogpostsTags" class="classBlogpostsTags" local="id" foreign="blogpost" cardinality="many" owner="local" />
</object>
<object class="classTags" table="test_tags" extends="xPDOSimpleObject">

        <field key="name" dbtype="varchar" precision="255" phptype="string" null="true" />

        <composite alias="aliasTagsBlogposts" class="classBlogpostsTags" local="id" foreign="tag" cardinality="many" owner="local" />
</object>
<object class="classBlogpostsTags" table="test_blogposts_tags" extends="xPDOSimpleObject">
        <field key="blogpost" dbtype="int" precision="11" phptype="integer" null="true" />
        <field key="tag" dbtype="int" precision="11" phptype="integer" null="true" />
 
        <aggregate alias="Tags" class="classTags" local="tag" foreign="id" cardinality="one" owner="foreign" />
        <aggregate alias="Blogposts" class="classBlogposts" local="blogpost" foreign="id" cardinality="one" owner="foreign" />
</object>
</model>


Snippet:

$modx->addPackage('ofc', MODX_CORE_PATH . 'components/ofc/model/');

$blogpost = $modx->getObject('classBlogposts', 1);
$tags = $modx->getCollection('classTags');

$blogpost->addMany($tags);
$blogpost->save();


Error log:

[2015-09-14 15:54:13] (ERROR @ /index.php) No foreign key definition for parentClass: classBlogposts using relation alias: classTags
[2015-09-14 15:54:13] (ERROR @ /index.php) No foreign key definition for parentClass: classBlogposts using relation alias: classTags

Maybe it is important to mention that the error msg is always printed twice as shown above...no idea if this is somehow related to my problem.]]>
mojorisin Sep 14, 2015, 09:03 AM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531486
<![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531464 https://rtfm.modx.com/xpdo/2.x/getting-started/creating-a-model-with-xpdo/defining-a-schema/more-examples-of-xpdo-xml-schema-files are leading to the same error when trying to create new related objects. However the removal of related objects is working fine. I have absolutely no idea what I am doing wrong. I am running MODx 2.4.0.]]> mojorisin Sep 14, 2015, 01:55 AM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531464 <![CDATA[Re: Working with related objects causing error]]> https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531414 BobRay Sep 11, 2015, 07:48 PM https://forums.modx.com/thread/98268/working-with-related-objects-causing-error#dis-post-531414