using soap in php and laravel

Manipulating Soap Web Services With PHP and Laravel

Working with web services is an important aspect if every modern web application. In this article i will demonstrate how to deal with Web services based on Soap xml.

 

 

Perhaps you heard about the term Soap before in the world of web services and you asked what is soap. Soap is a protocol for making remote procedure calls (RPC) using xml, so unlike the Rest web services which uses json, Soap web services expressed as xml documents that have a specific structure understandable by the Soap Engine.

To make a Soap Api you need two components, (a soap server and a soap client). The server which has the actual api functions that for example fetch data from the database. The client makes requests to the server component and calls the appropriate api using it’s name.

Most programming languages have already built in classes to deal with Soap clients and servers and php among them have the native Soap classes and also there are other php libraries like the nusoap and zend-soap library so we don’t need to worry about generating the Soap xml documents as they are generated automatically.

 

Anatomy of Soap Messages

Example Soap Request

Example Soap Response

The anatomy shown above show an example of a Soap message whether it’s a response or request the soap generate and sends those messages behind the scenes when it makes a request and receives a response.

As you see Soap document must be a valid xml document that have root element SOAP-ENV:Envelope. Inside this element there are SOAP-ENV:Header element this element not mandatory and it can contain optional things like authentication data.

The most important element is SOAP-ENV:Body and this have two forms depending on whether this is a request message or response message.

On request messages SOAP-ENV:Body element holds the actual function or api names and their arguments, in the above example there are a function “<getProduct>” and inside it an “<id>” and this calls function getProduct($id) in php. On response messages the SOAP-ENV:Body holds the return values of the functions as shown above the “<getProductResponse>

 

Example

Let’s see an example to demonstrate Soap in pure php first then i will show you how to implement this in laravel framework. In this example we will create a simple api for retrieving products and their details so create a new database with this table:

Next create a new folder called soap in your web root directory with the following files:

server.php will hold the php code for creating the real apis, connecting to the database and calling the soap server. client.php hold the php code for initializing the soap client and connecting to the soap server in server.php.

The api.php file represent the front controller that you already navigate to it in your browser to access the api. in fact you can omit it and use client.php directly but to make things clean.

server.php

As you see above the best approach to use is to add a class with all the apis that we need, in the example above we have two apis  getAllProducts() and getProduct(), remember the api names as we will use them when creating the client.

After that we initialized the soap server using php SoapServer() class passing two arguments, the first is null in that case and the other parameter is an array of options with a uri item that pointing to the server.php file.

PHP SoapServer() and SoapClient() have two cases, the first case is to provide one parameter only which is a url to .wsdl file. working with .wsdl files is another topic so we will stick with the second case which is to pass null as the first parameters and a second parameter for an options array.

Then we call $soapServer->setClass(‘server’), this we take our class and maps all the functions in it to an xml document entries corresponding to each function. Finally the most important call $soapServer->handle() to turn on the soap server.

 

client.php

We initialized the soap client in the constructor above passing the same options as the soap server using php SoapClient() class, the second parameter must be an array of options with a uri and location, the third parameter trace=1 will display any error messages if they occur.

Then we created two functions getAll() and getById() and those functions call the soap server getAllProducts() and getProduct() respectively using this syntax:

You can also call a soap server function using another way with __soapCall(‘func name’, parameters) like this:

Now let’s move to calling the apis this will be achieved in the api.php file:

 

api.php

As you see in the code above i have made some simple checks to check for the “op” parameter, this represent the method name in the client class that we need to call, in that case we have two methods only which is getAll() and getById(). Then we called the apis using a switch statement using simple OOP call $client->getAll() or $client->getById([‘id’ => $id]).

 

Now navigate to http://localhost/soap/api.php?op=getAll, and http://localhost/soap/api.php?op=getById&id=1 you will see the results of both apis.

 

When the client calls any of the functions in the server the client sends an xml request and receives xml response. The request and response similar to the xml structure described above.  To output the request or the response you may use any of the functions below:

 

Nice isn’t it, in a real world application you don’t need to create the soap server in fact you will only create the client and use a soap server for an existing api like this apis US Holidays Web Service. I created a simple example for one of this apis below:

Using Soap in Laravel

To use soap with laravel you can use the native php Soap classes or you can use a package dedicated for this, one of those packages is artisanweb/laravel-soap. First to install it using composer:

Installation for Laravel 5.2 and above:

Add the service provider in app/config/app.php.

To use the alias, add this to the aliases in app/config/app.php.

Installation for Laravel 5.1 and below :

 

To use it create a new controller and call the soap wrapper, i have rewritten the previous example using like this:

I have injected the SoapWrapper into the constructor, then to call a soap server, this must be done in two steps,

The first step is to add a service like this:

Here i added a service called “Holidays” this can be any name and this represents a namespace for all the services that you will call, next inside the callback i provided the wsdl() url and specified the tracing to be true. If you don’t want to use wsdl url you can use the location uri using ->location(url) function.

The second step is to call a service:

Here i have called the service “GetHolidaysForYear“, this is the same service name as the previous example.

Notice that i have added the namespace name then a dot then the service name like this “Holidays.GetHolidaysForYear“. If you omit the namespace name you will get an error.

routes/web.php

Now navigate to http://project url/public?year=2018 you will see the same results in the previous example.

 

 

Share this: