unable to find function call_user_func() in laravel

144 Views Asked by At

i am using an smpp library from https://github.com/onlinecity/php-smpp/tree/windows-compatible on windows to send message via smpp but I encounter a problem in smppclient.class I am told that

call_user_func(): Argument #1 ($callback) must be a valid callback, function "printDebug" not found or invalid function name

so I need help to be able to implement this function for sending messages.

here is my send message controller

<?php
namespace App\Http\Controllers;
use Exception;
use GsmEncoder;
use SMPP;
use SmppAddress;
use SmppClient;
use TSocket;

$GLOBALS['SMPP_ROOT'] = dirname(__FILE__); // assumes this file is in the root
require_once $GLOBALS['SMPP_ROOT'].'/protocol/smppclient.class.php';
require_once $GLOBALS['SMPP_ROOT'].'/protocol/gsmencoder.class.php';
require_once $GLOBALS['SMPP_ROOT'].'/transport/tsocket.class.php';

class apiSmsSmppController extends Controller{
    
    public function sendSmsSmpp($message,$tel){
        // Simple debug callback
        function printDebug($str) {
            echo date('Ymd H:i:s ').$str."\r\n";
        }
        try {
            // Construct transport and client, customize settings
            $transport = new TSocket('xxx.xxx.xx.xx',2775,false,'printDebug'); // hostname/ip (ie. localhost) and port (ie. 2775)
            $transport->setRecvTimeout(10000);
            $transport->setSendTimeout(10000);
            $smpp = new SmppClient($transport,'printDebug');
            
            // Activate debug of server interaction
            $smpp->debug = true;        // binary hex-output
            $transport->setDebug(true); // also get TSocket debug
            
            // Open the connection
            $transport->open();
            $smpp->bindTransmitter("xxxxx","xxxx");
            
            // Optional: If you get errors during sendSMS, try this. Needed for ie. opensmpp.logica.com based servers.
            //SmppClient::$sms_null_terminate_octetstrings = false;
            
            // Optional: If your provider supports it, you can let them do CSMS (concatenated SMS) 
            //SmppClient::$sms_use_msg_payload_for_csms = true;
            
            // Prepare message
            $message = 'H€llo world';
            $encodedMessage = GsmEncoder::utf8_to_gsm0338($message);
            $from = new SmppAddress(GsmEncoder::utf8_to_gsm0338('SMPP Tést'),SMPP::TON_ALPHANUMERIC);
            $to = new SmppAddress(22670530377,SMPP::TON_INTERNATIONAL,SMPP::NPI_E164);
            
            // Send
            $smpp->sendSMS($from,$to,$encodedMessage);
            
            // Close connection
            $smpp->close();
            
        } catch (Exception $e) {
            // Try to unbind
            try {
                $smpp->close();
            } catch (Exception $ue) {
                // if that fails just close the transport
                printDebug("Failed to unbind; '".$ue->getMessage()."' closing transport");
                if ($transport->isOpen()) $transport->close();
            }
            
            // Rethrow exception, now we are unbound or transport is closed
            throw $e; 
        }
    }
}

?>

here is the function call in smppclient.class

if($this->debug) 
    call_user_func($this->debugHandler, "Received sms:\n".print_r($sms,true));

if($this->debug) {
            call_user_func($this->debugHandler, "Send PDU         : $length bytes");
    call_user_func($this->debugHandler, ' '.chunk_split(bin2hex($header.$pdu->body),2," "));
    call_user_func($this->debugHandler, ' command_id      : 0x'.dechex($pdu->id));
    call_user_func($this->debugHandler, ' sequence number : '.$pdu->sequence);
}
1

There are 1 best solutions below

0
Sammitch On

For one, please don't define functions like this.

While PHP technically allows you to, it is confusing at best, and will break your app at worst. All functions are created at the global level, regardless of where they're defined, so calling the method more than once would try to declare the same function a second time, causing your app to break.

For two, you're defining the function inside of a namespaced file, so you would need to namespace the call, eg:

$transport = new TSocket('xxx.xxx.xx.xx',2775,false,'App\Http\Controllers\printDebug');

Though this is still subject to the multiple-declaration problem above.

For three, anonymous functions exist make far more sense in this context.

$debug = function($str) {
    echo date('Ymd H:i:s ').$str."\r\n";
}
// ...
$transport = new TSocket('xxx.xxx.xx.xx',2775,false,$debug);

Or, not as easily reusable but still valid:

$transport = new TSocket('xxx.xxx.xx.xx',2775,false,function($str){echo date('Ymd H:i:s ').$str."\r\n";});

Though the way to implement this that would most satisfy various coding styles/standards would be:

class apiSmsSmppController extends Controller{
    protected function printDebug($str) {
        echo date('Ymd H:i:s ').$str."\r\n";
    }
    
    public function sendSmsSmpp($message,$tel){
        // ...
        $transport = new TSocket('xxx.xxx.xx.xx',2775,false,[$this, 'printDebug']);
        // ...
    }
}

Ref: