Rest API v4_1 is not working with php 8.1 and 8.2

Hello there,

I am currently working on SuiteCRM version 8.2, utilizing PHP 8.1. In the course of my work, I’ve developed custom API files to handle various API calls. However, I’ve encountered an issue where certain API calls are only running successfully on PHP version 7.4, not on PHP 8.1 or 8.2.

I would greatly appreciate your assistance in resolving this matter.

Thank you in advance.

You’re not saying what your troubles are. Do you have any error messages, any reproducible errors?

Hello @pgr

Thanks for replying.

I have created a custom API file public/legacy/custom/service/mob_v4/SugarWebServiceImplcustom_v4.php with this API function;

function custom_setEntry($session, $user_id, $module_name, $nameValueList) {
        $error = new SoapError();
        if (!self::$helperObject->checkSessionAndModuleAccess($session, 'invalid_session', '', '', '', $error)) {
            $GLOBALS['log']->info('End: SugarWebServiceImplmob_v4->mob_setUserProfile.');
            return false;
        }
        global $sugar_config;
        require_once('service/v4_1/SugarWebServiceImplv4_1.php');

        $objModule = BeanFactory::getBean($module_name);
        $objUsers = BeanFactory::getBean('Users', $user_id);

        $field_defination = $objModule->getFieldDefinitions();
        $user_dec_sep = $objUsers->getPreference('dec_sep');
        $user_num_grp_sep = $objUsers->getPreference('num_grp_sep');
        $currencyDigits = $objUsers->getPreference('default_currency_significant_digits');

        foreach ($nameValueList as $keynumber => $NameValueArray) {
            if ($field_defination[$NameValueArray['name']]['type'] == 'currency' || $field_defination[$NameValueArray['name']]['type'] == 'decimal' || $field_defination[$NameValueArray['name']]['type'] == 'float') {
                $actualValue = number_format($NameValueArray['value'], $currencyDigits, $user_dec_sep, $user_num_grp_sep);
                $nameValueList[$keynumber]['value'] = $actualValue;
            }
        }
        $objV4_1 = new SugarWebServiceImplv4_1();
        $setEntryResponse = $objV4_1->set_entry($session, $module_name, $nameValueList);
        $getEntryResponse = $objV4_1->get_entry($session, $module_name, $setEntryResponse['id'], array(), array());

        $ReturnResponse['id'] = $setEntryResponse['id'];
        foreach ($getEntryResponse['entry_list'] as $response) {
            foreach ($response as $setEntyResponse) {
                if ($setEntyResponse != 'id' && $setEntyResponse != 'module_name') {
                    $ReturnResponse['entry_list'] = $setEntyResponse;
                }
            }
        }

        if ($module_name == 'AOS_Products' || $module_name == 'Mob_followups') {
            $moduleObj = BeanFactory::getBean($module_name, $setEntryResponse['id']);
            if ($module_name == 'AOS_Products') {
                $moduleObj->product_image = $sugar_config['site_url'] . '/upload/' . $filename;
            } else {
                $moduleObj->filename = $filename;
                $filename = $setEntryResponse['id'];
            }
            $moduleObj->save();
            $myfile = fopen('upload/' . $filename, 'w');
            $actualContent = base64_decode($imageContent);
            fwrite($myfile, $actualContent);
            fclose($myfile);
            $ReturnResponse['imageContent'] = $imageContent;
        }
        return $ReturnResponse;
    }

Also, I have created one API request in POSTMAN APIs with this form data:

method:custom_setEntry
input_type:JSON
response_type:JSON
rest_data:{"session":"cl0ki83cnb0r8dd3oqr549aams","user_id":"1","module_name":"Calls_Reschedule","name_value_list":[{"name":"call_id","value":"3e372359-ea80-10f6-a7d5-6576fab952ae"},{"name":"reason","value":"In a Meeting"}],"recordId":"3e372359-ea80-10f6-a7d5-6576fab952ae"}

Apart from this, I have debugged this file code: public/legacy/service/core/REST/SugarRestJSON.php

public function serve(){
		$GLOBALS['log']->info('Begin: SugarRestJSON->serve');
		$json_data = !empty($_REQUEST['rest_data'])? $GLOBALS['RAW_REQUEST']['rest_data']: '';
		print_r($json_data);exit;

		if(empty($_REQUEST['method']) || !method_exists($this->implementation, $_REQUEST['method'])){
			$er = new SoapError();
			$er->set_error('invalid_call');
			$this->fault($er);
		}else{
			$method = $_REQUEST['method'];
			
			$json = getJSONObj();
			$data = $json->decode($json_data);
			if(!is_array($data))$data = array($data);
            if (!isset($data['application_name']) && isset($data['application'])){
				$data['application_name'] = $data['application'];
            }
			$res = call_user_func_array(array( $this->implementation, $method),$data);

			$GLOBALS['log']->info('End: SugarRestJSON->serve');
			return $res;
		} // else
	} // fn

But when I print the $res every time I get 500 internal server errors in POSTMAN APIs and get an error:

Fatal error:  Uncaught Error: Unknown named parameter $name_value_list in /var/www/html/crm/crm84_v2_1/public/legacy/service/core/REST/SugarRestJSON.php:106
Stack trace:
#0 /var/www/html/crm/crm84_v2_1/public/legacy/service/core/SugarRestService.php(137): SugarRestJSON->serve()
#1 /var/www/html/crm/crm84_v2_1/public/legacy/service/core/webservice.php(70): SugarRestService->serve()
#2 /var/www/html/crm/crm84_v2_1/public/legacy/custom/service/mob_v4/rest.php(15): require_once('...')
#3 {main}
  thrown in /var/www/html/crm/crm84_v2_1/public/legacy/service/core/REST/SugarRestJSON.php on line 106

and when I call custom_setEntry() directly via POSTMAN, it doesn’t call the function and gives a 500 error every time. and no error is coming in the php log or suitecrm log.

For reference, I checked these links but didn’t find a solution.

  1. Rest API v4_1 is not working with my new setup i.e. php 8.0, SuiteCRM 7.13
  2. REST API v2 issue with suitecrm7.13 and php8

Sorry, I had a look but I couldn’t find anything helpful to tell you… :man_shrugging:

That looks like the problem I had. Here’s the solution that worked for me in this thread.

1 Like

Hey @pstevens,

Great job! I figured out the solution. In the file public/legacy/service/core/REST/SugarRestJSON.php, I made some tweaks in the serve() function.

Just comment on line 106:
$res = call_user_func_array(array($this->implementation, $method),$data);

Replace it with this line:
$res = $this->implementation->{$method}(...array_values($data));

:tada: It’s working perfectly.

Huge thanks to @pgr and @pstevens for your fantastic help and support!

2 Likes

Nice work @chirag_biz309
Do you expect this fix to work on PHP 7.x, 8.x, and Suite 7.x, 8.x?

Yes @chris001, the fix is expected to work on PHP 7.x, 8.x, Suite 7.x, and 8.x.

Would you make a Pull Request on github? To get the fix added into Suite 7.x and 8.x

Sure, @chris001

Certainly! Can you guide me on the process?

Some instructions here:

Error creating Activities relationship form module builder - #4 by pgr

That’s the basic thing, editing a single file directly on Github. The proper thing for more complex scenarios would be to set a local git fork and work from there.

As you can see from the instructions above. Here’s the source file to edit (you click pencil :pencil2: button, change that line of code, click Save button, and follow the steps to make your first Pull Request to branch hotfix).

Good! Now you just need to sign the CLA.

Hello @chris001

Great news! I’ve already signed the CLA, and I’ve submitted a pull request with the changes. If there’s anything else needed from my end, please let me know. Looking forward to contributing more!

Thanks.

Hi,

I don’t think this change is necessary.

You have defined your entry as

function custom_setEntry($session, $user_id, $module_name, $nameValueList)

and you call it with

rest_data:{"session":"cl0ki83cnb0r8dd3oqr549aams","user_id":"1","module_name":"Calls_Reschedule","name_value_list":[{"name":"call_id","value":"3e372359-ea80-10f6-a7d5-6576fab952ae"},{"name":"reason","value":"In a Meeting"}],"recordId":"3e372359-ea80-10f6-a7d5-6576fab952ae"}

If you had defined your entry with

function custom_setEntry($session, $user_id, $module_name, $name_value_list)

it is very likely it would have worked

Hello @blqt

Thank you for your feedback. I appreciate your insights. Just a quick note, the current implementation works seamlessly with PHP 7.4 and 8.0. However, I would recommend checking the custom API calls with PHP 8.1 and 8.2 versions to ensure compatibility. If you encounter any issues or if the solution provided doesn’t address the problem, feel free to reach out. Your collaboration is valuable, and together, we can ensure a smooth experience across different PHP versions.

Hello @blqt

I implemented your suggested solution, and I am pleased to report that it was successful.

I appreciate your assistance.

Thanks.

Hello All,

For this issue, there are 2 solutions.

  1. Change in the SugarRestJSON.php file - Solution
  2. Just change the variable in the custom call - Solution

You can use either solution, but I recommend you go with the second solution. Because SugarRestJSON.php is the main file. So I do not recommend that you modify this file.

Thanks.

1 Like