关系的getBeans()返回空数组

I am creating a custom ACL class that would check whether the relationship exists between the records and if so load all the related records to that particular bean. I have looked at the sugar documentation which says to use load_relationship($relationshipName) for checking if relationship exists and getBeans() to load all the related records (as an array of objects). I have implemented this into my class but for some reason whichever module and relationship I use it always returns an empty array.

The data I use for checking has 3 parts:

  1. The Module accessing the data
  2. The relationship name with the target module (not module name)
  3. The ID of the record accessing the data

The link here at sugar community shows a similar problem that I'm having, but the answer to this does not so solve my problem

Here is my custom ACL:

namespace Sugarcrm\Sugarcrm\custom\clients\base;

class CustomACL
{
    const ACL_NONE = 0;
    const ACL_READ_ONLY = 1;
    const ACL_READ_WRITE = 2;

    public static function checkRelated($module, $linkedRelationshipName, $id)
    {
        $bean = \BeanFactory::getBean($module);
        if ($bean->load_relationship($linkedRelationshipName)) {
            return self::checkRecordRelated($bean, $id,$linkedRelationshipName);
        } else {
            return false;
        }
    }

    /**
     * Checks if record is related
     * @param $bean
     * @param $id
     * @param $linkedModule
     * @return bool
     */
    protected static function checkRecordRelated($bean, $id, $linkedModule)
    {
        $bean->retrieve_by_string_fields(array(
            "id" => $id
        ));
        if ($bean->load_relationship($linkedModule)) {
            $relatedRecords = $bean->$linkedModule->getBeans();
            return $relatedRecords;
        } else {
            return false;
        }
    }

}

This class should be working for any module, even if it is custom or non custom. I have tried using my custom module and even the default modules (leads, accounts etc) but none of them returns anything except an empty array.

I suspect the problem is that you are reusing the previously empty bean, for which you already loaded the same link using load_relationship() before.
On the second load_relationship() call, Sugar probably returns the cached result from the first call (as the link is already internally flagged as having been loaded), therefore returning the same empty array again.

Therefore instead of using

$bean->retrieve_by_string_fields(array(
        "id" => $id
    ));

I'd suggest creating a new bean e.g. using

if (empty($id)) {
    return false;
}
$bean = BeanFactory::retrieveBean($module, $id);
if (!$bean) {
    return false;
}

(which should actually not be too slow, as the bean is probably cached already)

Notes:

  • Your variable names are somewhat confusing. $linkedRelationshipName and $linkedModule should contain neither the relationship name nor the module name, but the name of the link-type field.

EDIT:

To reiterate: The documentation may be misleading there, but load_relationship() does not expect the relationship name as parameter. What it expects is the link name!.

from data/SugarBean.php:

/**
 * Loads the request relationship. This method should be called before performing any operations on the related data.
 *
 * This method searches the vardef array for the requested attribute's definition. If the attribute is of the type
 * link then it creates a similary named variable and loads the relationship definition.
 *
 * @param string $link_name link/attribute name.
 *
 *@return nothing.
 */
function load_relationship($link_name)

So make sure to check the VarDefs of each module for the correct link name.

E.g.

  • relationship name: accounts_contacts
  • link field for this relationship in account: contacts,
    so you should be calling $accountBean->load_relationship('contacts')
  • link field for this relationship in contact: accounts,
    so you should be calling $contactBean->load_relationship('accounts')

Note: link names are basically arbitrary across different modules, don't rely on them being lowercase singular/plural of the linked module. In some cases (and for custom relationships) they will not be.