May 30

PHPClasses: VirtualCron, GoogleMaps i InsertFTP

Reading time: 2 – 2 minutes

A través de PHPClasses he trobat aquestes tres classes de PHP que tenen bona pinta així que espero que algún dia li facin servei a algú o a mi mateix:

  • Insert FTP: This class can be used to manage FTP user accounts stored in a MySQL database.It can connect to a MySQL server that has a database of FTP user accounts used by FTP servers like pure-ftpd. It can: add new user accounts, block an user, change account quotas, retrieve the details of an FTP user account.
  • Karatag Google Maps HTTP Request: The Google Maps API is mostly known for being able to present maps of anywhere in the world in any Web site. However, Google Maps API is also able to provide other interesting features, like determining the geographic coordinates of a given address. This class uses the Google Maps API just for the purpose of determining the location associated to an address from PHP programs.
  • Virtual Cron: Many Web applications need to execute periodical tasks, like sending newsletters, processing pending e-commerce orders, etc. Some operating systems come with programs, like cron or at, to execute scheduled tasks. However, under some Web hosting environments these programs cannot be used. This class provides an alternative solution that can be used in more restricted hosting environments. It uses files to keep track of the last time when a periodical task was executed. The site Web page scripts can use the class to check these files. The class can tell when it is time to execute a task again. When it is time, the same script can execute the scheduled task without depending on external programs.
Feb 08

PHP: notes sobre arrays i tres classes (myCurl, barcodes, WSSoapClient)

Reading time: 2 – 3 minutes

A HowtoForge han publicat un howto (local) sobre com funcionen els arrays en PHP que esta molt bé. Realment el que més valoro són les notes sobre les funcions que menys s’acostumen a usar i per tant, les menys documentades o més mal documentades. Tot i que sovint quan les descobreixes ja no pots viure sense elles, funcions de búsqueda, de push, pop, var_dump per depurar, etc.

A més a través de phpClasses he trobat tres classes que els hi he de donar un bon cop d’ull ja que tenen molt bona pinta:

  • MyCurl This class provides an alternative implementation of the cURL extension functions in pure PHP. It automatically detects whether the cURL library is available. If it is not available, it defines several functions with the same names of the cURL extension that use the class to emulate part the original functionality. Currently it implements the functions: curl_init, curl_exec, curl_setopt and curl_close. Several of the most important options can be set with the curl_setopt function.
  • HTML Bar Codes This package can be used to display bar codes using only HTML with CSS styles. It takes a code to represent and generates CSS style definitions and HTML tags to render that code in an HTML page. There are two classes that can render bar codes using the Code39 and Interleave 2 of 5 standards respectively.
  • WSSoapClient This class can add WSSecurity authentication support to SOAP clients implemented with the PHP 5 SOAP extension. It extends the PHP 5 SOAP client support to add the necessary XML tags to the SOAP client requests in order to authenticate on behalf of a given user with a given password. This class was tested with Axis and WSS4J servers.
May 13

PHP5: passant i tornant objectes com a paràmetre en una crida SOAP (Part II)

Reading time: 5 – 8 minutes

El mes de març vaig escriure un article titulat gairebé igual que aquest, en aquell article explicava com s’ho feia el PHP5 per rebre i retornar tipus complexes (p.e. objectes) com a paràmetres de crides SOAP. Doncs bé havia trobat una cosa que em tenia una mica mosca i és que quan enviava una objecte del client cap al servidor o alrevés en perdia el tipus. Doncs bé aquesta tarda he descobert com aconseguir fer això sense perdren el tipus. Ja sabeu que quan se’m posa una cosa al cap…

El tema no és senzill i el generador de WSDL del ZendStudio és una mica tiquis-miquis fent aquestes coses així doncs s’ha de fer tot molt maco perquè ho entengui el generador WSDL. De fet, la gràcia esta en definir el tipus complexe dins del fitxer WSDL, per això el generador necessita que li donem tota la informació com ell vol sinó no és capaç de generar bé el fitxer.

En l’exemple que us poso a continuació he creat la classe persona amb tres atributs dos de públics i un de privat. El privat al contrari del que comentava en l’article anterior no perd el seu valor. Així doncs, en principi tenim l’objecte 100% replicat amb el mètode que ara us explicaré.

La classe persona:

<?php
/**
 * classe persona
 *
 */
class persona {
	/**
	 * propietat nom
	 *
	 * @var string $nom
	 * @var string $cognom
	 * @var string $dni
	 */
	public $nom;
	private $cognom;
	public $dni;
	/**
	 * setter function
	 *
	 * @param string $nom
	 */
	function set($nom) {
		$this-?>nom=$nom;
	}
	/**
	 * setter cognom
	 *
	 *  @param string $cognom
	 */
	function setCognom($cognom)
	{
		$this-?>cognom=$cognom;
	}
	/**
	 * getter function
	 *
	 * @return string valor a tornar
	 */
	function get()
	{
		return $this-?>nom;
	}
	/**
	 * getter cognom
	 *
	 * @return string valor a tornar
	 */
	function getCognom()
	{
		return $this-?>cognom;
	}
}
?>

Fixeu-vos que comentem el codi segons la sintaxis del phpDoc això es fa perquè és d’aquests comentaris d’on el generador WSDL extreurà els tipus de les variables per poder-les exportar sense perdre informació. La propietat dni no té ni getter ni setter perquè hi accedirem directament. Per la resta de coses és una classe completament normal i senzilla.

El servidor és força simple:

<?php
require_once("persona.class.php");
/**
 * servidor soap
 *
 */
class soapservice {
	/**
	 * funcio soap publicada
	 *
	 * @param persona $per
	 * @return persona
	 */
	function peticion($per) {
		$per->dni="38147000x";
		return $per;
  }
}
	$server = new SoapServer("server.wsdl",array("classmap"=>array("persona"=>"persona")));
$server->setClass("soapservice");
$server->handle();
?>

Comentar que la classe soapservice rep un objecte de tipus persona afegeix un valor a la propietat dni i retorna el mateix objecte. Aquí també hem de documentar el codi segons la sintaxis del phpDoc així el model WSDL ens dirà explicitament el tipus dels objectes que rep i torna el mètode peticion.

Pel que fa a la creació de l’objecte server del tipus SoapServer fixeu-vos que mapegem amb l’opció classmap l’objecte de tipus persona que es passa com a paràmetre amb la classe local també anomenada persona. Gràcies a aquest mapeig quan rebem l’objecte per al soapservice aquest ja és del tipus persona.

Ara toca veure el codi del client, aquest codi també té un mapeig igual que el servidor de SOAP, però en aquest cas serveix per capturar la sortida del servidor i com que l’objecte que es torna a la sortida també és del tipus persona el classmap és igual que el del servidor.

<?php
require_once("persona.class.php");
// creem objecte tipus persona
$myPersona=new persona;
$myPersona->set("el_nom");
$myPersona->setCognom("el_cognom");
	$client = new SoapClient("server.wsdl",array("classmap"=>array("persona"=>"persona")));
	$localPersona=$client->peticion($myPersona);
	var_dump($client->__getFunctions());
print_r($localPersona);
echo $localPersona->getCognom();
?>

Una de les coses interssants que fem és preguntar quines funcions s’estan publicant al servidor SOAP. Aquesta informació esta descrita al WSDL i la funció __getFunctions() ens la formateja per humans. Així doncs podem veure que hi ha disponible la funció peticion que té com a paràmetre un objecte del tipus persona i que retorna un altre objecte de tipus.

array(1) {
  [0]=>
  string(30) "persona peticion(persona $per)"
}

Després mostrem (print_r) l’objecte localPersona que ens ha tornat la crida al mètode peticion ($localPersona=$client->peticion($myPersona);):

persona Object
(
    [nom] => el_nom
)

Finalment fem una prova de concepte i obtenim el valor de la propietat nom a través del getter, o sigui, echo $localPersona->getCognom();:

el_nom 

Com podeu veure ha quedat ben demostrat que és relativament senzill enviar i rebre tipus complexes a través dels serveis SOAP. Tota la gràcia esta en el fitxer WSDL, a continuació us enganxo el que m’ha generat el Zend Studio per fer aquestes proves fixeu-vos com al prinicipi de tot el primer que fa és declarar el tipus complexe de dades que ha de traspassar, en el nostre cas la classe persona.

<?xml version='1.0' encoding='UTF-8'?>
	<!-- WSDL file generated by Zend Studio. -->
	<definitions name="server" targetNamespace="urn:server" xmlns:typens="urn:server" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:typens0="http://oriol.joor.net/fotoprix/web/cu.php/soap/server">
	<types>
		<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:server">
			<xsd:complexType name="persona">
				<xsd:all>
					<xsd:element name="nom" type="xsd:string"/>
					<xsd:element name="cognom" type="xsd:string"/>
					<xsd:element name="dni" type="xsd:string"/>
				</xsd:all>
			</xsd:complexType>
		</xsd:schema>
	</types>
	<message name="peticion">
		<part name="per" type="typens:persona"/>
	</message>
	<message name="peticionResponse">
		<part name="peticionReturn" type="typens:persona"/>
	</message>
	<portType name="soapservicePortType">
		<documentation>
			servidor soap
		</documentation>
		<operation name="peticion">
			<documentation>
				provem de descriure
			</documentation>
			<input message="typens:peticion"/>
			<output message="typens:peticionResponse"/>
		</operation>
	</portType>
	<binding name="soapserviceBinding" type="typens:soapservicePortType">
		<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
		<operation name="peticion">
			<soap:operation soapAction="urn:soapserviceAction"/>
			<input>
				<soap:body namespace="urn:server" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
			</input>
			<output>
				<soap:body namespace="urn:server" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
			</output>
		</operation>
	</binding>
	<service name="serverService">
		<port name="soapservicePort" binding="typens:soapserviceBinding">
			<soap:address location="http://oriol.joor.net/soap/server.php"/>
		</port>
	</service>
</definitions>
Apr 23

PHP5: passant objectes com a paràmetre en una crida SOAP

Reading time: 2 – 3 minutes

Update: LES CONCLUSIONS D’AQUEST ARTICLE SÓN ERRONEES MIREU: PHP5: passant i tornant objectes com a paràmetre en una crida SOAP (Part II)

Treballant en un projecte que estem programant en PHP5 em va sortir aquest dubte, sobretot després de llegir les limitacions dels servidors SOAP que implementa PHP5. El tema finalment té una resposta positiva: SI, PERO…. A continuació us poso un exemple de com funciona aquest tema amb el PHP5 i quines limitacions té.

Definim el servidor SOAP que com podeu veure és senzillissim, l’únic que fa el servidor és re-enviar el mateix objecte que ha rebut.

<php
class SOAPservice {
        function peticion($per) {
                return $per;
  }
}
$server = new SoapServer("server.wsdl");
$server->setClass("SOAPservice");
$server->handle();
?>

A continuació podeu veure el codi del client, és un codi molt senzill de només dues línies. Com podem veure primer definim la classe persona i abans de cridar el client SOAP instanciem la classe, després usem aquest objecte com a paràmetre a la crida SOAP. Capturem l’objecte que ens retorna el servidor SOAP i a continuació mostrem el seu contingut amb l’ordre print_r.

<?php
/*
 definim classe persona
*/
class persona {
        public $nom;
        function setNom($nom) {
                $this->nom=$nom;
        }
        function setCognom($cognom) {
                $this->cognom=$cognom;
        }
        function getNom() {
                return $this->nom;
        }
        function getCognom() {
                return $this->cognom;
        }
}
/*
 creem objecte tipus persona
*/
$myPersona=new persona;
$myPersona->setNom("el_nom");
$myPersona->setCognom("el_cognom");
/*
 fem una crida SOAP amb un objecte com a parametre
*/
$client = new SoapClient("server.wsdl");
$myObj=$client->peticion($myPersona);
/*
 mostrem objecte generic que retorna la crida SOAP
*/
print_r($myObj);
?>

Si mirem la sortida que ens dona quan cridem el client podem veure que l’objecte que torna no és del tipus persona sinó d’un tipus intern del PHP5 anomenat stdClass. Aquest objecte només disposa dels atributs públics. No podem accedir als atributs privats o protegits i hem perdut tots els mètodes siguin del tipus que siguin.

stdClass Object
(
    [nom] => el_nom
    [cognom] => el_cognom
)

Això és tot el que he pogut aconseguir, no és gaire però com a mínim a mi m’ha estat suficient.