Calling a WCF service from PHP

The WCF service needs to use basicHttpBinding.

The PHP code:

define('NEWLINE', "<br />\n");

// SOAP client

$wsdl = 'http://example.com/SampleWcfService.SampleService.Service?wsdl';
$soapClient = new SoapClient($wsdl, array('cache_wsdl' => 0));

// SOAP call

$sampleData->SampleProperty = "abc";

$parameters->sampleId = 123;
$parameters->sampleData = $sampleData;

try
{
	$result = $soapClient->GetData($parameters);
}
catch (SoapFault $fault)
{
	echo "Fault code: {$fault->faultcode}" . NEWLINE;
	echo "Fault string: {$fault->faultstring}" . NEWLINE;
	if ($soapClient != null)
	{
		$soapClient = null;
	}
	exit();
}
$soapClient = null;

//echo "<pre>\n";
//print_r($result);
//echo "</pre>\n";

echo "Return value: {$result->GetDataResult}" . NEWLINE;

IService.cs:

using System.ServiceModel;

namespace SampleWcfService.SampleService
{
    [ServiceContract(Namespace = "http://example.com/SampleWcfService/SampleService")]
    public interface IService
    {
        [OperationContract(Name = "GetData")]
        string GetData(int sampleId, SampleType sampleData);
    }
}

Service.cs:

namespace SampleWcfService.SampleService
{
    public class Service : IService
    {
        public string GetData(int sampleId, SampleType sampleData)
        {
            return string.Format("sampleId = {0}, sampleType.SampleProperty = {1}", sampleId, sampleData.SampleProperty);
        }
    }
}

SampleType.cs:

using System.Runtime.Serialization;

namespace SampleWcfService.SampleService
{
    [DataContract(Namespace = "http://example.com/SampleWcfService/SampleService", Name = "SampleType")]
    public class SampleType
    {
        [DataMember(Name = "SampleProperty")]
        public string SampleProperty { get; set; }
    }
}

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<system.serviceModel>
		<services>
			<service
				behaviorConfiguration="SampleWcfService.SampleService.Service.Behavior"
				name="SampleWcfService.SampleService.Service">
				<endpoint address=""
						  binding="basicHttpBinding"
						  contract="SampleWcfService.SampleService.IService" />
				<host>
					<baseAddresses>
						<add baseAddress="http://example.com/SampleWcfService.SampleService.Service" />
					</baseAddresses>
				</host>
			</service>
		</services>
		<behaviors>
			<serviceBehaviors>
				<behavior name="SampleWcfService.SampleService.Service.Behavior" >
					<serviceMetadata httpGetEnabled="true" />
				</behavior>
			</serviceBehaviors>
		</behaviors>
	</system.serviceModel>
</configuration>

8 April 2010 | .NET, PHP | 1 Comment

Using log4php

A how-to for the excellent log4php:

  1. Rolling daily file
  2. Log error statements into one file, and info statements into another
  3. Send emails

Usage

include_once('/var/www/example/components/log4php/2.0.0/Logger.php');

class Example
{
	private $logger;

	function __construct()
	{
		$loggerConfig = '/var/www/example/config/log4php.xml';
		Logger::configure($loggerConfig);
		$this->logger = Logger::getLogger('example');
	}

	public function doSomething()
	{
		$var = $this->getSomeValue();
		$this->logger->debug('in doSomething: $var = ' . $var);
		try
		{
			$this->doSomethingSpecific();
		}
		catch (Exception $ex)
		{
			$this->logger->error($ex->getMessage());
			throw new Exception("There is a problem with Something. We apologize for any inconvenience caused.");
		}
		$this->logger->info("doSomething successful");
	}
}

log4php.xml

<log4php:configuration xmlns:log4php="http://logging.apache.org/log4php/">
    <appender name="default" class="LoggerAppenderDailyFile">
        <param name="file" value="/var/www/example/logs/%s.log" />
        <param name="datePattern" value="Ymd" />
        <layout class="LoggerLayoutPattern">
            <param name="ConversionPattern" value="%d{Y-m-d H:i:s} [%p] %c: %m (at %F line %L)%n" />
        </layout>
    </appender>
    <appender name="exampleDebugLog" class="LoggerAppenderDailyFile">
        <param name="file" value="/var/www/example/logs/debug.%s.log" />
        <param name="datePattern" value="Ymd" />
        <layout class="LoggerLayoutPattern">
            <param name="ConversionPattern" value="%d{Y-m-d H:i:s} [%p] %c: %m%n" />
        </layout>
        <filter class="LoggerFilterLevelRange">
            <param name="LevelMin" value="debug" />
            <param name="LevelMax" value="debug" />
        </filter>
        <filter class="LoggerFilterDenyAll" />
    </appender>
    <appender name="exampleInfoLog" class="LoggerAppenderDailyFile">
        <param name="file" value="/var/www/example/logs/info.%s.log" />
        <param name="datePattern" value="Ymd" />
        <layout class="LoggerLayoutPattern">
            <param name="ConversionPattern" value="%d{Y-m-d H:i:s} [%p] %c: %m%n" />
        </layout>
        <filter class="LoggerFilterLevelRange">
            <param name="LevelMin" value="info" />
            <param name="LevelMax" value="info" />
        </filter>
        <filter class="LoggerFilterDenyAll" />
    </appender>
    <appender name="exampleErrorLog" class="LoggerAppenderDailyFile">
        <param name="file" value="/var/www/example/logs/errors.%s.log" />
        <param name="datePattern" value="Ymd" />
        <layout class="LoggerLayoutPattern">
            <param name="ConversionPattern" value="%d{Y-m-d H:i:s} [%p] %c: %m (at %F line %L)%n" />
        </layout>
        <filter class="LoggerFilterLevelRange">
            <param name="LevelMin" value="error" />
            <param name="LevelMax" value="fatal" />
        </filter>
        <filter class="LoggerFilterDenyAll" />
    </appender>
    <appender name="exampleErrorEmail" class="LoggerAppenderMail">
        <param name="from" value="sys@example.com" />
        <param name="to" value="support@example.com" />
        <param name="subject" value="Error" />
        <layout class="LoggerLayoutPattern">
            <param name="ConversionPattern" value="%d{Y-m-d H:i:s} [%p] %c: %m (at %F line %L)%n" />
        </layout>
        <filter class="LoggerFilterLevelRange">
            <param name="LevelMin" value="error" />
            <param name="LevelMax" value="fatal" />
        </filter>
        <filter class="LoggerFilterDenyAll" />
    </appender>
    <root>
        <level value="DEBUG" />
        <appender_ref ref="default" />
    </root>
    <logger name="example" additivity="false">
        <level value="INFO" />
        <appender_ref ref="exampleInfoLog" />
        <appender_ref ref="exampleErrorLog" />
        <appender_ref ref="exampleErrorEmail" />
    </logger>
</log4php:configuration>

27 March 2010 | PHP | No Comments

Calling a .NET asmx web service over https from PHP

  1. Enable SOAP by uncommenting “extension=php_soap.dll” in php.ini
  2. https should be included in “Registered PHP Streams” (phpinfo) – uncomment “extension=php_openssl.dll” in php.ini
// SOAP client

$wsdl = 'https://www.example.com/services/ProductManagement.asmx?wsdl';
$endpoint = array
(
	'location' => 'https://www.example.com/services/ProductManagement.asmx'
);
$soapClient = new SoapClient($wsdl, $endpoint);

// SOAP header

$soapHeaders = array();

$namespace = 'http://www.example.com/services/ProductManagement';
$elementName = 'Authentication';
$authenticationHeader = array
(
	'Username' => 'user9',
	'Password' => 'pass1234',
);
$soapHeader = new SoapHeader($namespace, $elementName, $authenticationHeader);
$soapHeaders[] = $soapHeader;

$soapClient->__setSoapHeaders($soapHeaders);

// SOAP call

$parameters->productCode = '9555170408350';

try
{
	$result = $soapClient->GetProduct($parameters);
}
catch (SoapFault $fault)
{
	echo "Fault code: {$fault->faultcode}<br />\n";
	echo "Fault string: {$fault->faultstring}<br />\n";
	if ($soapClient != null)
	{
		$soapClient = null;
	}
	exit();
}
$soapClient = null;

//echo "<pre>\n";
//print_r($result);
//echo "</pre>\n";

echo "Product code: {$result->GetProductResult->ProductCode}<br />\n";
echo "Name: {$result->GetProductResult->Name}<br />\n";
echo "Description: {$result->GetProductResult->Description}<br />\n";
echo "Category: {$result->GetProductResult->Category}<br />\n";
echo "SKU: {$result->GetProductResult->SKU}<br />\n";
echo "Manufacturer: {$result->GetProductResult->Manufacturer}<br />\n" ;
echo "Brand: {$result->GetProductResult->Brand}<br />\n";
echo "In stock: ";
echo ($result->GetProductResult->IsInStock ? "Yes" : "No") . "<br />\n";

26 March 2010 | PHP | No Comments

Data Sanitizer

I wrote a C# console app to sanitize CSV files. It replaces numbers with X’s so that social security number 123456 becomes XXXXXX and the address “49 Main St” becomes “XX Main St”. Both the input and the output are streamed to ensure that the program won’t run out of memory even with arbitrarily large files.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace DataSanitizer
{
    class Program
    {
        private const string Delimiter = "|";
        private const string ReplacementCharacter = "X";
        private const int NumFields = 15;

        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.WriteLine("Usage: DataSanitizer.exe input_file output_file");
                return;
            }

            string inputFilePathAndName = args[0];
            string outputFilePathAndName = args[1];

            using (StreamReader sr = new StreamReader(inputFilePathAndName))
            using (StreamWriter sw = new StreamWriter(outputFilePathAndName, true))
            {
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    string[] fields = line.Split(Delimiter.ToCharArray());
                    string ssn = fields[2];
                    string addressLine1 = fields[4];
                    string addressLine2 = fields[5];
                    string addressLine3 = fields[6];
                    string telHome = fields[9];
                    string telOffice = fields[10];
                    string telMobile = fields[11];
                    Regex alphanumeric = new Regex(@"\w");
                    Regex numeric = new Regex(@"\d");
                    string ssnSanitized = alphanumeric.Replace(ssn, ReplacementCharacter);
                    string addressLine1Sanitized = numeric.Replace(addressLine1, ReplacementCharacter);
                    string addressLine2Sanitized = numeric.Replace(addressLine2, ReplacementCharacter);
                    string addressLine3Sanitized = numeric.Replace(addressLine3, ReplacementCharacter);
                    string telHomeSanitized = alphanumeric.Replace(telHome, ReplacementCharacter);
                    string telOfficeSanitized = alphanumeric.Replace(telOffice, ReplacementCharacter);
                    string telMobileSanitized = alphanumeric.Replace(telMobile, ReplacementCharacter);
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < NumFields; i++)
                    {
                        if (i > 0)
                        {
                            sb.Append(Delimiter);
                        }
                        switch (i)
                        {
                            case 2:
                                sb.Append(ssnSanitized);
                                break;
                            case 4:
                                sb.Append(addressLine1Sanitized);
                                break;
                            case 5:
                                sb.Append(addressLine2Sanitized);
                                break;
                            case 6:
                                sb.Append(addressLine3Sanitized);
                                break;
                            case 9:
                                sb.Append(telHomeSanitized);
                                break;
                            case 10:
                                sb.Append(telOfficeSanitized);
                                break;
                            case 11:
                                sb.Append(telMobileSanitized);
                                break;
                            default:
                                sb.Append(fields[i]);
                                break;
                        }
                    }
                    sw.WriteLine(sb.ToString());
                }
            }
        }
    }
}

19 March 2010 | C# | 1 Comment

Urgent

You don’t know the meaning of urgent until you’re stuck in a traffic jam with a small child who has just started potty training, who urgently needs to go …

17 March 2010 | Uncategorized | No Comments