Formit hook to save form to resource

i have a hook that saves formit form to a resource.

all is working nicly however I can not seem to save tagger tags.

I have the following snippet



$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget('FILE');

// Load the Tagger service
$tagger = $modx->getService('tagger', 'Tagger', $modx->getOption('tagger.core_path', null, $modx->getOption('core_path').'components/tagger/').'model/tagger/');
if (!$tagger) {
    $modx->log(modX::LOG_LEVEL_ERROR, 'Could not load Tagger service.');
    return false;
}

// Create new resource
$doc = $modx->newObject('modResource');
$doc->set('createdby', $modx->user->get('id'));

$allFormFields = $hook->getValues();

// Set core fields
foreach ($allFormFields as $field => $value) {
    if (in_array($field, ['pagetitle', 'content'])) {
        $doc->set($field, $value);
    }
}

// Set other resource properties
$doc->set('parent', 290);
$doc->set('alias', time());
$doc->set('template', '2'); 
$doc->set('published', '0');

if (!$doc->save()) {
    $modx->log(modX::LOG_LEVEL_ERROR, 'Failed to save resource');
    return false;
}

$resourceId = $doc->get('id');
$modx->log(modX::LOG_LEVEL_ERROR, "Resource saved with ID: $resourceId");

// Loop to save template variables (TVs)
foreach ($allFormFields as $field => $value) {
    if ($tv = $modx->getObject('modTemplateVar', ['name' => $field])) {
        if (is_array($value)) {
            $value = implode('||', $value);
        }
        $tv->setValue($resourceId, $value);
        if (!$tv->save()) {
            $modx->log(modX::LOG_LEVEL_ERROR, "Failed to save TV: $field for Resource ID: $resourceId");
        }
    }
}

// Add tags using Tagger for each tag type
$tagFields = [
    'subject_tags' => 'subject_tagger_group_id',
    'topic_tags' => 'topic_tagger_group_id',
    'grade_tags' => 'grade_tagger_group_id',
    'material_type_tags' => 'material_type_tagger_group_id',
    'editor_tags' => 'editor_tagger_group_id',
    'language_tags' => 'language_tagger_group_id',
];

foreach ($tagFields as $tagField => $groupField) {
    if (!empty($allFormFields[$tagField]) && !empty($allFormFields[$groupField])) {
        $tags = explode(',', $allFormFields[$tagField]);
        $taggerGroupId = (int) $allFormFields[$groupField];

        $modx->log(modX::LOG_LEVEL_ERROR, "Processing tags for $tagField in group $taggerGroupId");

        foreach ($tags as $tag) {
            $tag = trim($tag);
            if (!empty($tag)) {
                $tagObject = $modx->getObject('TaggerTag', [
                    'tag' => $tag,
                    'group' => $taggerGroupId,
                ]);

                if (!$tagObject) {
                    $tagObject = $modx->newObject('TaggerTag');
                    $tagObject->set('tag', $tag);
                    $tagObject->set('group', $taggerGroupId);
                    if (!$tagObject->save()) {
                        $modx->log(modX::LOG_LEVEL_ERROR, "Failed to create Tag: $tag in Group: $taggerGroupId");
                    }
                }

                // Link the tag to the resource
                if (!$tagObject->addMany($doc)) {
                    $modx->log(modX::LOG_LEVEL_ERROR, "Failed to link Tag: $tag to Resource ID: $resourceId");
                } else {
                    $modx->log(modX::LOG_LEVEL_ERROR, "Linked Tag: $tag to Resource ID: $resourceId");
                }
            }
        }
    }
}

return true;

getting following errors

Processing tags for subject_tags in group 1

Could not load class: TaggerTag from mysql.taggertag

TaggerTag::load() is not a valid static method.

Could not load class: TaggerTag from mysql.taggertag

input form i got as an example

<input id="input-tag2" type="text" class="input-tags"
                                                    value="[[TaggerGetTags? &groups=`1` &rowTpl=`tag_tpl`]]"
                                                    autocomplete="off" name="subject_tags"
                                                    >
                                                <input type="hidden" name="subject_tagger_group_id" value="1">

Are you using MODX 3 or MODX 2.x?

1 Like

using modx 3 latest version

With the Tagger version for MODX 3, you have to use the “TaggerTag” class with the namespace → Tagger\Model\TaggerTag.


I don’t think it’s necessary anymore (in MODX 3) to use getService(), as the service already gets added (in bootstrap.php) on every request:

1 Like

thanks for the help that definatly got me closer.

however i am still getting an tagger error that I am trying to figure out

<?php

$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget('FILE');

$defaultParentId=290;
$defaultPublished=0;
$defaultTemplate=2;
$defaultUser=732;


// Create new resource
$doc = $modx->newObject('modResource');
$userId = $modx->user->get('id') ? $modx->user->get('id') : $defaultUser;
$doc->set('createdby', $userId);

$allFormFields = $hook->getValues();

// Set core fields
foreach ($allFormFields as $field => $value) {
    if (in_array($field, ['pagetitle', 'content'])) {
        $doc->set($field, $value);
    }
}

// Set other resource properties
$doc->set('parent', $defaultParentId); // Using integer value, which is suitable for IDs
$doc->set('alias', time());
$doc->set('template', $defaultTemplate); 
$doc->set('published', $defaultPublished);

if (!$doc->save()) {
    $modx->log(modX::LOG_LEVEL_ERROR, 'Failed to save resource');
    return false;
}

$resourceId = $doc->get('id');
$modx->log(modX::LOG_LEVEL_ERROR, "Resource saved with ID: $resourceId");

// Loop to save template variables (TVs)
foreach ($allFormFields as $field => $value) {
    if ($tv = $modx->getObject('modTemplateVar', ['name' => $field])) {
        if (is_array($value)) {
            $value = implode('||', $value);
        }
        $tv->setValue($resourceId, $value);
        if (!$tv->save()) {
            $modx->log(modX::LOG_LEVEL_ERROR, "Failed to save TV: $field for Resource ID: $resourceId");
        }
    }
}

// Add tags using Tagger for each tag type
$tagFields = [
    'subject_tags' => 'subject_tagger_group_id',
    'topic_tags' => 'topic_tagger_group_id',
    'grade_tags' => 'grade_tagger_group_id',
    'material_type_tags' => 'material_type_tagger_group_id',
    'editor_tags' => 'editor_tagger_group_id',
    'language_tags' => 'language_tagger_group_id',
];

foreach ($tagFields as $tagField => $groupField) {
    if (!empty($allFormFields[$tagField]) && !empty($allFormFields[$groupField])) {
        $tags = explode(',', $allFormFields[$tagField]);
        $taggerGroupId = (int) $allFormFields[$groupField];

        $modx->log(modX::LOG_LEVEL_ERROR, "Processing tags for $tagField in group $taggerGroupId");

        foreach ($tags as $tag) {
            $tag = trim($tag);
            if (!empty($tag)) {
                // Check if the tag already exists
                $tagObject = $modx->getObject('Tagger\Model\TaggerTag', [
                    'tag' => $tag,
                    'group' => $taggerGroupId,
                ]);

                // If the tag does not exist, create it
                if (!$tagObject) {
                    $tagObject = $modx->newObject('Tagger\Model\TaggerTag');
                    $tagObject->set('tag', $tag);
                    $tagObject->set('group', $taggerGroupId);
                    if (!$tagObject->save()) {
                        $modx->log(modX::LOG_LEVEL_ERROR, "Failed to create Tag: $tag in Group: $taggerGroupId");
                        continue; // Skip linking if tag creation failed
                    }
                }

                // Set the resource ID on the tag object
                $tagObject->set('resource_id', $resourceId); // Ensure resource ID is set

                // Link the tag to the resource
                if (!$tagObject->addMany($doc)) {
                    $modx->log(modX::LOG_LEVEL_ERROR, "Failed to link Tag: $tag to Resource ID: $resourceId");
                } else {
                    $modx->log(modX::LOG_LEVEL_ERROR, "Linked Tag: $tag to Resource ID: $resourceId");
                }
            }
        }
    }
}

return true;

so basically the errors is

ERROR @ core/vendor/xpdo/xpdo/src/xPDO/xPDO.php : 1852) No foreign key definition for parentClass: Tagger\Model\TaggerTag using relation alias: MODX\Revolution\modResource

so not sure why it is not automatically creating the foreign keys are not added. I battled to force it in the snippet.

Did you write this code yourself or did you copy it from somewhere (or use one of those AI tools)?


// Set the resource ID on the tag object
$tagObject->set('resource_id', $resourceId); // Ensure resource ID is set

The class Tagger\Model\TaggerTag has no field resource_id.

There are two classes involves here. Tagger\Model\TaggerTag stores the value of a tag and to what Tagger-group it belongs.

The class Tagger\Model\TaggerTagResource stores the assignment of a tag (field = tag) to a certain resource (field = resource):

1 Like

yes lol

i am using cursor and I thought it would give me a solution but nothing beats humans and nothing beats @halftrainedharry :slight_smile:

thanks so much its working:

here is the cleaned up code if someone wants to do something similar added comments etc:

This is for a Formit hook to create a new resource that includes tagger fields:

<?php

/*
html example:

[[!FormIt?
&hooks=`resource2formitSubmit`
&submitvar=`submittheexampleform`
]]
<form action="[[~[[*id]]]]" method="post">
    <input type="text" name="pagetitle" placeholder="ADD MORE INPUTS THAT YOU NEED BELOW" value="[[!+fi.pagetitle]]">
    <textarea name="introtext" id="introtext">[[!+fi.introtext]]</textarea>
    <textarea name="content">[[!+fi.content]]</textarea>
    <input id="input-tag2" type="text" value="[[TaggerGetTags? &groups=`1` &rowTpl=`tag_tpl`]]" name="subject_tags">
    <input type="hidden" name="subject_tagger_group_id" value="1">
    <input id="input-tag3" type="text" value="[[TaggerGetTags? &groups=`3` &rowTpl=`tag_tpl`]]" name="topic_tags">
    <input type="hidden" name="topic_tagger_group_id" value="3">
    <input id="input-tag4" type="text" value="[[TaggerGetTags? &groups=`4` &rowTpl=`tag_tpl`]]" name="grade_tags">
    <input type="text" name="name" value="[[!+fi.name]]">
    <input type="email" name="email" value="[[!+fi.email]]">
    <input name="submittheexampleform" type="submit" value="Send">
</form>

*/




// Set the logging level to ERROR and log target to FILE
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget('FILE');

// Set default values for resource properties
$defaultParentId = 290; // Default parent ID where the resource will be saved
$defaultPublished = 0; // Default published status (0 = unpublished)
$defaultTemplate = 2; // Default template ID
$defaultUser = 732; // Default user ID if no user is logged in

// Create a new resource object
$doc = $modx->newObject('modResource');

// Determine the user ID, using the logged-in user or default if not available
$userId = $modx->user->get('id') ? $modx->user->get('id') : $defaultUser;
$doc->set('createdby', $userId); // Set the creator of the resource

// Retrieve all form field values
$allFormFields = $hook->getValues();

// Set core fields for the resource
foreach ($allFormFields as $field => $value) {
    if (in_array($field, ['pagetitle', 'content', 'introtext'])) {
        $doc->set($field, $value); // Set the page title and content
    }
}

// Set additional properties for the resource
$doc->set('parent', $defaultParentId); // Set the parent ID
$doc->set('alias', time()); // Set a unique alias using the current timestamp
$doc->set('template', $defaultTemplate); // Set the template ID
$doc->set('published', $defaultPublished); // Set the published status

// Attempt to save the resource and log an error if it fails
if (!$doc->save()) {
    $modx->log(modX::LOG_LEVEL_ERROR, 'Failed to save resource');
    return false; // Exit the script if saving fails
}

$resourceId = $doc->get('id'); // Get the ID of the newly saved resource
// $modx->log(modX::LOG_LEVEL_ERROR, "Resource saved with ID: $resourceId"); //comment out for debugging

// Loop through form fields to save template variables (TVs)
foreach ($allFormFields as $field => $value) {
    if ($tv = $modx->getObject('modTemplateVar', ['name' => $field])) {
        if (is_array($value)) {
            $value = implode('||', $value); // Convert array values to a string
        }
        $tv->setValue($resourceId, $value); // Set the TV value for the resource
        if (!$tv->save()) {
            $modx->log(modX::LOG_LEVEL_ERROR, "Failed to save TV: $field for Resource ID: $resourceId");
        }
    }
}

// Define tag fields and their corresponding group IDs these correspond to your input details see html
$tagFields = [
    'subject_tags' => 'subject_tagger_group_id',
    'topic_tags' => 'topic_tagger_group_id',
    'grade_tags' => 'grade_tagger_group_id',
    'material_type_tags' => 'material_type_tagger_group_id',
    'editor_tags' => 'editor_tagger_group_id',
    'language_tags' => 'language_tagger_group_id',
];

// Process each tagger field
foreach ($tagFields as $tagField => $groupField) {
    if (!empty($allFormFields[$tagField]) && !empty($allFormFields[$groupField])) {
        $tags = explode(',', $allFormFields[$tagField]); // Split tags into an array
        $taggerGroupId = (int) $allFormFields[$groupField]; // Get the tagger group ID

       // $modx->log(modX::LOG_LEVEL_ERROR, "Processing tags for $tagField in group $taggerGroupId"); comment out for debugging

        foreach ($tags as $tag) {
            $tag = trim($tag); // Remove whitespace from the tag
            if (!empty($tag)) {
                // Check if the tag already exists in the database
                $tagObject = $modx->getObject('Tagger\Model\TaggerTag', [
                    'tag' => $tag,
                    'group' => $taggerGroupId,
                ]);

                // If the tag does not exist, create a new tag object
                if (!$tagObject) {
                    $tagObject = $modx->newObject('Tagger\Model\TaggerTag');
                    $tagObject->set('tag', $tag);
                    $tagObject->set('group', $taggerGroupId);
                    if (!$tagObject->save()) {
                        $modx->log(modX::LOG_LEVEL_ERROR, "Failed to create Tag: $tag in Group: $taggerGroupId");
                        continue; // Skip linking if tag creation failed
                    }
                }

                // Get the ID of the tag
                $tagId = $tagObject->get('id');

                // Check if a link between the tag and resource already exists
                $tagResourceLink = $modx->getObject('Tagger\Model\TaggerTagResource', [
                    'tag' => $tagId,
                    'resource' => $resourceId,
                ]);

                // If no link exists, create a new link
                if (!$tagResourceLink) {
                    $tagResourceLink = $modx->newObject('Tagger\Model\TaggerTagResource');
                    $tagResourceLink->set('tag', $tagId);
                    $tagResourceLink->set('resource', $resourceId);

                    // Attempt to save the link and log the result
                    if (!$tagResourceLink->save()) {
                        $modx->log(modX::LOG_LEVEL_ERROR, "Failed to link Tag: $tagId to Resource ID: $resourceId");
                    } else {
                      //  $modx->log(modX::LOG_LEVEL_ERROR, "Linked Tag: $tagId to Resource ID: $resourceId"); comment out for debug
                    }
                }
            }
        }
    }
}

return true; // Return true to indicate successful execution

This topic was automatically closed 2 days after discussion ended and a solution was marked. New replies are no longer allowed. You can open a new topic by clicking the link icon below the original post or solution and selecting “+ New Topic”.