How to load model with Codeigniter Webservice - Nusoap Server? - php

I am trying to load a model to a webservice (Nusoap) as follows:
Controller:
class Addition extends CI_Controller{
public function Addition(){
parent::__construct();
$ns = base_url().'addition/';
$endpoint = base_url().'addition/';
$this->load->library("nusoap_library"); // load nusoap toolkit library in controller
$this->nusoap_server = new soap_server(); // create soap server object
$this->nusoap_server->configureWSDL("SMS SOAP", $ns, $endpoint); // wsdl cinfiguration
$this->nusoap_server->wsdl->schemaTargetNamespace = $ns; // server namespace
// REGISTER FUNCTIONS
$input_array = array ('var1' => "xsd:string", 'var2' => "xsd:string"); // "addnumbers" method parameters
$return_array = array ("var3" => "xsd:int", 'var4' => "xsd:string");
$this->nusoap_server->register('send', $input_array, $return_array, "urn:SOAPServerWSDL", "urn:".$ns."send", "rpc", "encoded", "My Addition WS");
}
function index(){
function send($var1, $var2){
$this->load->model('mymodel'); // THIS IS MY MODEL
$data['var1'] = $this->mymodel->addnumbers($var1, $var2);
$data['var2'] = "yes";
return $data;
}
$this->nusoap_server->service(file_get_contents("php://input"));
}
}
The problem is that if I take out the model and just add directly, it will work perfectly, but with the model it returns nothing.
Any help will be greatly appresiated.

I think I solved my own question.
Apparently you cannot invoke directly the model. A way to do it is the following:
class Addition extends CI_Controller{
public function Addition(){
parent::__construct();
$ns = base_url().'addition/';
$endpoint = base_url().'addition/';
$this->load->library("nusoap_library"); // load nusoap toolkit library in controller
$this->nusoap_server = new soap_server(); // create soap server object
$this->nusoap_server->configureWSDL("SMS SOAP", $ns, $endpoint); // wsdl cinfiguration
$this->nusoap_server->wsdl->schemaTargetNamespace = $ns; // server namespace
// REGISTER FUNCTIONS
$input_array = array ('var1' => "xsd:string", 'var2' => "xsd:string"); // "addnumbers" method parameters
$return_array = array ("var3" => "xsd:int", 'var4' => "xsd:string");
$this->nusoap_server->register('send', $input_array, $return_array, "urn:SOAPServerWSDL", "urn:".$ns."send", "rpc", "encoded", "My Addition WS");
}
function index(){
function send($var1, $var2){
$CI =& get_instance();
$CI->load->model('mymodel'); // THIS IS MY MODEL
$data['var1'] = $CI->mymodel->addnumbers($var1, $var2);
$data['var2'] = "yes";
return $data;
}
$this->nusoap_server->service(file_get_contents("php://input"));
}
I know this may not be the best solution but it works perfectly and you are able to load any model using Codeigniter Framework with Nusoap.
Hope this helps as future reference.
If anyone has a better way to load the model please let us know.

Related

Drupal 8 PHPUnit testing Invalid Credentials

I have a class I want to test that uses this module PHP HTTP client for Emarsys webservice, but when I try to test it, I will always get $response as "Credentials are invalid" from the module itself.
Here's a snippet of my code: (Given that I was able to correctly create my setUp() for Test Class since I was able to use it for other tests)
Test.php
Class TestClass extends UnitTestCase {
public function testCreateWithValidEmail() {
$newsletter = new Newsletter();
$form = new FormState();
$form->setValue('email', 'abc#def.ghi');
$response = $newsletter->register($form);
// Assertion here
}
}
Class.php
use Snowcap\Emarsys\CurlClient;
use Snowcap\Emarsys\Client;
Class Newsletter {
public function register(FormStateInterface $state){
$emailData = $state->getValue('email');
$httpClient = new CurlClient();
$client = new Client($httpClient, $api_username, $api_secret);
$someData = [
"3" => $emailData, // since 3 is the index ID for email
// ...more data here
];
$response = $client->createContact($someData);
}
}
Do I have to create a mock of something here to pass a dummy api and secret then force a valid response from createContact?
You are in the good direction. But that Newsletter class needs the $httpClient injected.
So you will be able to do:
$client = $this->getMockBuilder(Snowcap\Emarsys\CurlClient::class)
->disableOriginalConstructor()
->getMock();
$response = $this->getMockBuilder(ResponseInterface::class)
->disableOriginalConstructor()
->getMock();
$response->expects($this->any())
->method('getStatusCode')
->willReturn(Response::HTTP_OK);
$client->expects($this->any())
->method('createContact')
->with($someData)
->will($this->returnValue($response));
$newsletter = new Newsletter($client);
$response = $newsletter->register($form);
// Assertion here

Is not reusing created SOAP client object

Can anyone tell me why the SOAP client is not being re-used? It keeps getting initialized where it should have been reused from the last call.
When I print out the SOAP client object after it was initialized it is there but it is forgotten at the next call.
So the php script keeps initializing the connection.
My code:
class EcoAPI {
private $client;
public function getClient() {
if (empty($this->client)) {
echo "<br>initializing...";
$this->initClient();
}
return $this->client;
}
private function initClient() {
$settingsOld = Settings::GetOld();
$this->client = new SoapClient("https://api.e-conomic.com/secure/api1/EconomicWebservice.asmx?WSDL", array("trace" => 1, "exceptions" => 1));
$this->client->ConnectWithToken(array('token' => $settingsOld->economic_token_secret, 'appToken' => $settingsOld->economic_token_app));
}
}
I connect by:
$ecoApi = new EcoAPI();
$result = $ecoApi->getClient()->Account_GetVatAccount(array('accountHandle' => (object) array('Number' => (string) $VatAccount)));
Every time you're creating a new EcoAPI object, it won't have any SOAP client information. Using $ecoApi->getClient()->... throughout your code SHOULD work as long as you're using injecting the same $ecoApi object.
If you want to ensure that every EcoAPI object has the same connection object, no matter what, you could try making the client a static property with static methods to manipulate the SOAP object.
class EcoAPI {
static private $client;
static public function getClient() {
if (empty(self::$client)) {
echo "<br>initializing...";
self::initClient();
}
return self::$client;
}
static private function initClient() {
$settingsOld = Settings::GetOld();
self::$client = new SoapClient("https://api.e-conomic.com/secure/api1/EconomicWebservice.asmx?WSDL", array("trace" => 1, "exceptions" => 1));
self::$client->ConnectWithToken(array('token' => $settingsOld->economic_token_secret, 'appToken' => $settingsOld->economic_token_app));
}
}
And connect by:
$result = EcoAPI::getClient()->Account_GetVatAccount(array('accountHandle' => (object) array('Number' => (string) $VatAccount)));
Granted, I would advise against using static objects and methods and it can lead to tight coupling. The best method, in my opinion, is injecting your instantiated objects on an as-needed basis.

How to access a PHP variable from one function in another function

I have already written an application in a procedural way and am trying to move into into a Laravel framework. I'm having trouble with the SOAP exchange section as I am getting an ID value that authenticates the user but cannot access that value (as a cookie) later in the program to authenticate the search.
Here is my code so far:
<?php namespace App;
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
use Illuminate\Http\RedirectResponse;
class SoapController {
private $auth_response;
private $cookie;
private $search_client;
private $search_response;
public function soapExchange() {
// create SOAP client and add service details
SoapWrapper::add(function ($service) {
$service
->name('WoSAuthenticate')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WOKMWSAuthenticate?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
SoapWrapper::service('WoSAuthenticate', function($service) {
// call authenticate() method to get SID cookie
$auth_response = $service->call('authenticate', []);
$cookie = $auth_response->return;
// test for cookie return
// print($cookie);
});
// create SOAP client and add service details
$search_client = new SoapWrapper;
$search_client::add(function ($service) {
$service
->name('WoSSearch')
->wsdl('http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl')
->trace(true)
->cache(WSDL_CACHE_NONE);
});
if (isset($auth_response->return)) {
// if there is an SID returned then add it to the cookie attribute of the search client
$search_client->__setCookie('SID', $cookie);
} else {
// route to relevant view to display throttle error
return redirect('throttle');
}
}
}
I am successfully retrieving the response from the Web API call and getting a code to authenticate the user, saved as $cookie. However, I need then to create another SoapWrapper for performing the search and this needs the ID code attached by using the __setCookie method. If nothing is returned by the authenticate call then it redirects to an error message via throttle.blade.php elsewhere.
Surely there is a way to return a value created from a function so that it can be used elsewhere?
** EDIT **
Looked into employing SoapClient instead and including all operations within a single function. It all relates to a specific Web API anyway so I guess separation of concerns is not so much of an issue. FYI the new class I am trying is this:
<?php namespace App\Models;
use SoapClient;
use Illuminate\Http\RedirectResponse;
class SoapWrapper {
public function soapExchange() {
// set WSDL for authentication and create new SOAP client
$auth_url = "http://search.webofknowledge.com/esti/wokmws/ws/WOKMWSAuthenticate?wsdl";
// array options are temporary and used to track request & response data
$auth_client = #new SoapClient($auth_url);
// set WSDL for search and create new SOAP client
$search_url = "http://search.webofknowledge.com/esti/wokmws/ws/WokSearch?wsdl";
// array options are temporary and used to track request & response data
$search_client = #new SoapClient($search_url);
// run 'authenticate' method and store as variable
$auth_response = $auth_client->authenticate();
// call 'setCookie' method on '$search_client' storing SID (Session ID) as the response (value) given from the 'authenticate' method
// check if an SID has been set, if not it means Throttle server has stopped the query, therefore display error message
if (isset($auth_response->return)) {
$search_client->__setCookie('SID',$auth_response->return);
} else {
return Redirect::route('throttle');
}
}
}
Maybe try $GLOBALS?
<?php
$GLOBALS[data] = "something";
function abc(){
echo $GLOBALS[data];
}
?>
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
class SoapController extends Controller {
public $resultSoapStatus;
public $resultSoapAuthority;
public function heySoap{
SoapWrapper::add(function ($service) ...
$data = [
'MerchantID' => $MerchantID,
'Amount' => $Amount,
'Description' => $Description,
'Email' => $Email,
'Mobile' => $Mobile,
'CallbackURL' => $CallbackURL
];
SoapWrapper::service('test', function ($service) use ($data) {
$resultSoap = $service->call('PaymentRequest', [$data]);
$this->resultSoapStatus = $resultSoap->Status;
$this->resultSoapAuthority = $resultSoap->Authority;
});
if($this->resultSoapStatus == 100 && strlen($this->resultSoapAuthority) == 36)
{
//Do Something
}
else
{
return Redirect::back();
}
}
}
Enjoy bro

Zend soap call for method with hyphen

I rewrite soap client file using Zend framework.
This is old method. it is working.
function getBassaService(){
global $service;
$h="127.0.0.1";
$p="8000";
if($service==null){
$service = new SoapClient("/test/php/bassa.wsdl", array(
"soap_version" => SOAP_1_2,
"trace" => 1,
"exceptions" => 1,
"location" => "http://".$h.":".$p));
}
return $service;
}
function getAllDownloads(){
global $service;
$client = getService();
try{
$results = $client->__soapCall("list-all", array());
}catch(SoapFault $e){
print($e->faultstring);
}
return $result;
}
This is my new code. I use Zend_Soap_Client.
const HOST = "127.0.0.1";
const PORT = "8095";
protected $_client;
public function __construct()
{
$this->_client = new Zend_Soap_Client(APPLICATION_PATH ."/services/bassa.wsdl",
array(
"soap_version" => SOAP_1_2,
"uri" => "http://". self::HOST .":". self::PORT
)
);
}
public function getAllDownloads()
{
$result = $this->_client->list-all();
return $result;
}
My soap server has list-all method. I want soap call to that method. But following error has occurred. Because method name has hyphen.
Notice: Undefined property: Zend_Soap_Client::$list in /home/dinuka/workspace/testzend/application/services/SoapClient.php on line 57
Fatal error: Call to undefined function all() in /home/dinuka/workspace/testzend/application/services/SoapClient.php on line 57
How i fixed it. Please help me.
strange. that's should work. it might be a a bug in ZF framework. maybe it's trying to convert the function name into a camel case function name with variables.
Try to use the magic function directly by calling:
$this->_client->__call('list-all', array('param1' => $param1))

cakephp webservice

I have problem in creating web-service using cakephp .
this what i do to create this web-service .
I use NuSOAP - Web Services Toolkit for PHP for this.
I create a controller called WsController and import the library on it.
class WsController extends AppController{
var $uses = array();
function info() {
$this->layout= null;
$ns="http://www.techvoicellc.com/Tutorials//";
$server = new soap_server();
$server->configureWSDL('mostafa',$ns);
$server->wsdl->schemaTargetNamespace=$ns;
$server->wsdl->addComplexType('ArrayOfstring','complexType',
'array','','SOAP-ENC:Array',array()
,array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]')),
'xsd:string');
$server->register('sum',
array('x' => 'xsd:integer','y' => 'xsd:integer'),
array('z' => 'xsd:integer'),
$ns,
"$ns#sum",
'rpc',
'encoded',
'documentation' // documentation
);
$server->service($HTTP_RAW_POST_DATA);
}
function sum($x,$y){
$z=$x+$y;
return new soapval('return','xsd:integer',$z);
}
}
and i create the clint in controller action like this
function index() {
$wsdl = 'http://localhost/asd/ws/info?wsdl';
$client = new nusoap_client ( $wsdl, true );
$this->client = new nusoap_client($wsdl, true);
$param1 = array ('x' => 2, 'y' => 1 );
$a = $client->call ( 'sum', $param1 );
echo $a;
}
it don't do any thins although that i create this in non cake project and its work very well
hope some one tell me what is the best practise to create web-service in cake php
This is quite Easy to develop web services in CakePHP. I have done it several times. Check the below steps.
class MyWebServicesController extends AppController {
var $name = 'MyWebServices';
var $layout = "ajax";
function index() {
$server = new SoapServer(null);
$server->setObject($this);
$server->handle();
exit(0);
}
public function addNumbers($a,$b) {
return $a+$b
}
}
Now your web service is hosted at http://webroot/MyWebServices
Now you can call addNumbers like below.
$client = new SoapClient(null, array('location' => "http://webroot/MyWebServices");
$sum = $client->addNumbers(1+2);
It is best to create restful web service. CakePHP has everything built in for REST. All you have to do is enable it and create json/xml views.
Here is a link with your starting point: http://book.cakephp.org/2.0/en/development/rest.html
Is there a reason you want SOAP web service?
It will be so much harder to create and test SOAP web service
SOAP will require external libraries
It will be harder for users to use the SOAP web service

Categories