We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 813 ☆ A M B ☆
    • 326 Posts
    I've seen this problem elsewhere on the forums, but can't seem to get any of the solutions to work in my situation and was hoping for some personalized help.

    I've got two tables in my DB: an Articles table, and a Versions table. Whenever an article is saved, it should log a new row in the Versions table. I'm able to save to the Article table just fine, but the new version is never added, and my error log says "No foreign key definition for parentClass: Article using relation alias: Version".

    Here's the XML schema I used to build my model:

    <?xml version="1.0" encoding="UTF-8"?>
    <model package="myArticles" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" version="1.1">
    	<object class="Article" table="custom_article" extends="xPDOObject">
    		<field key="article_id" dbtype="int" precision="10" phptype="integer" null="false" index="pk"  generated="native" />
    		<field key="title" dbtype="varchar" precision="256" phptype="string" null="false" />
    		<field key="subtitle" dbtype="varchar" precision="512" phptype="string" null="true" />
    		<field key="summary" dbtype="varchar" precision="512" phptype="string" null="false" />
    		<field key="published" dbtype="int" precision="1" phptype="integer" null="false" />
    		<field key="ku_elevated" dbtype="int" precision="1" phptype="integer" null="false" />
    		<field key="start_time" dbtype="int" precision="32" phptype="integer" null="false" />
    		<field key="end_time" dbtype="int" precision="32" phptype="integer" null="false" />
    		<field key="created_userid" dbtype="int" precision="4" phptype="integer" null="false" />
    		<field key="created_timestamp" dbtype="int" precision="32" phptype="integer" null="false" />
    		<composite alias="Versions" class="Version" local="article_id" foreign="article" cardinality="many" owner="local" />
    	</object>
    	<object class="Version" table="custom_version" extends="xPDOObject">
    		<field key="version_id" dbtype="int" precision="10" phptype="integer" null="false" index="pk"  generated="native" />
    		<field key="article" dbtype="int" precision="10" phptype="integer" null="true" />
    		<field key="version_content" dbtype="mediumtext" phptype="string" null="true" />
    		<field key="version_userid" dbtype="int" precision="4" phptype="integer" null="false" />
    		<field key="version_timestamp" dbtype="int" precision="32" phptype="integer" null="false" />
    		<aggregate alias="VersionArticles" class="Article" local="article" foreign="article_id" cardinality="one" owner="foreign" />
    	</object></model>


    I'm using this script as a Formit hook to do the actual saving:

    <?php
    $title = $hook->getValue('title');
    $article_id = $hook->getValue('article_id');
    
    $path = MODX_CORE_PATH . 'components/myArticles/';
    $result = $modx->addPackage('myArticles',$path . 'model/','modx_');
    
    $article = $modx->getObject('Article',array(
       'article_id' => $article_id,
    ));
    if ($article == null) {
      $article = $modx->newObject('Article',array(
        'title' => $title,
        'created_timestamp' => time(),
        'created_userid' => 555
      ));
      $version = $modx->newObject('Version');
      $version->set('version_content','blah blah blah');
      $article->addOne($version);
    }
    else {
      $article->set('title',$title);
    }
    
    $article->save();
    return true;


    At the moment, you'll see I've just hard-coded some values to try to get it working. Can anyone spot the problem, or possibly a typo? I can provide any other schema or PHP examples you need. Thanks!
      • 813 ☆ A M B ☆
      • 326 Posts
      Oops -- just realized the errors may be coming from this script, not the Formit hook:

      // Set defaults
      $output = '';
      $crit = '';
      
      // Get and sanitize query string parameters
      $article_id = filter_var($_GET['article_id'], FILTER_SANITIZE_STRING);
      $user_id = filter_var($_GET['article_id'], FILTER_SANITIZE_STRING);
      
      // Get fields from the current resource
      $resource_id = $modx->resource->get('id');
      
      // Add Amyrticles package
      $path = MODX_CORE_PATH . 'components/myArticles/';
      $result = $modx->addPackage('myArticles',$path . 'model/','modx_');
      
      
      if ($result) {
        if (($resource_id == '4') && (empty($article_id))) {
          $output .= $modx->getChunk('editRowTpl',$rowFields);
        }
        else {
          switch ($resource_id) {
            case '1': // Generate a list of all articles for the dashboard
            	$rowName = 'dashboardRowTpl';
            break;
            
            
            case '4': // View/Create template
              $crit = $modx->newQuery('Article');
      	$crit->where(array ('article_id:=' => $article_id));
            	$rowName = 'editRowTpl';
            break;
            
          
          }
          
          $articles = $modx->getCollectionGraph('Article', '{ "Version":{},"User":{} }', $crit);
          if ($articles) {
            foreach ($articles as $article) {
      	$rowFields = $article->toArray();
      	
      	$user = $article->getOne('ArticleUsers');
      	$rowFields['article_user_name'] = $user->get('name');
      	$rowFields['article_user_email'] = $user->get('email');
      	
      	$c = $modx->newQuery('Version');
      	$c->sortby('version_timestamp','DESC');
      	$c->limit('1');
      	foreach ($article->getMany('Versions', $c) as $version) {
      	  $rowFields['version_content'] = $version->get('version_content');
      	  $rowFields['version_userid'] = $version->get('version_userid');
      	  $rowFields['version_timestamp'] = $version->get('version_timestamp');
      	  
      	  $vuser = $version->getOne('VersionUsers');
      	  $rowFields['version_user_name'] = $vuser->get('name');
      	  $rowFields['version_user_email'] = $vuser->get('email');
      	}
      	$rowOutput .= $modx->getChunk($rowName,$rowFields);
            }
          }
          
          if ($resource_id == '1') {
            $output .= $modx->getChunk('dashboardOuterTpl', array(
      	'rowOutput' => $rowOutput
            ));
          }
          if ($resource_id == '4') {
            $output .= $rowOutput;
          }
        }
      }
      
      return $output;


      What's weird is, I can actually retrieve related objects with that script. But it's still generating that error, and I can't save to the related object with either script.
        • 28215
        • 4,149 Posts
        For one, why are you using addOne, when the Article -> Versions is a one-to-many relationship? You should be doing:

          $version = $modx->newObject('Version');
          $version->set('version_content','blah blah blah');
          $article->addMany($version);
        


        Also, I don't see this relationship defined anywhere in your schema file:

        $user = $article->getOne('ArticleUsers');


        nor this one:

        $vuser = $version->getOne('VersionUsers');

          shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
          • 813 ☆ A M B ☆
          • 326 Posts
          Yes, that was it! Thanks so much. I'm still a little confused by addOne vs. addMany, but working through it on my own projects is starting to make it click.

          Oh, and those last two relationships are fine. I was trying to strip them out of my example code completely for simplicity, but I guess I missed a few.
            • 28215
            • 4,149 Posts
            addOne means there's only *one* possible record that could be associated with it. Think this example:

            car -> wheels is a one-to-many relationship, since there can be many wheels on a car. You'd do:

            $car->addMany($wheels);
            // or
            $car->addMany($wheel);
            


            However, with the wheel -> car relationship, there's only one car for those wheels. So:

            $wheel->addOne($car);
            
              shaun mccormick | bigcommerce mgr of software engineering, former modx co-architect | github | splittingred.com
              • 813 ☆ A M B ☆
              • 326 Posts
              I think where I get hung up with my project is, an article CAN have multiple versions, but it never WILL have more than one added at a time. So it seems like an addOne in my head, but it's obviously not. Thanks for the additional explanation.