Archive

Posts Tagged ‘php5’

Conferencia Zend PHP 5 del Fesoli 2010

November 22, 2010 Leave a comment

Las diapositivas de la conferencia sobre la certificación Zend se pueden descargar aquí. Gracias a todos por su participación.

Categories: Conferences, Spanish Tags: ,

Conferencia certificación Zend PHP5

August 21, 2010 Leave a comment

Las diapositivas de la conferencia sobre la certificación Zend PHP5 dado en la Universidad San Martin de Porres durante el V Freedom Open Source Day se pueden descargar siguiendo este enlace.

Categories: Conferences, php, PHP Perú, Spanish Tags: , ,

Preguntas y respuestas del Test Zend

December 15, 2009 6 comments

1. Cual de las siguientes no es un código de PHP ?

A. $_10

B. ${“MyVar”}

C. &$something

D. $10_somethings

E. $aVaR

Resp: $10_somethings

2. Cual es la diferencia entre print() y echo()?

A. print () puede utilizarse como parte de una expresión, mientras que echo () no puede

B. echo () puede utilizarse como parte de una expresión, mientras que print () no puede

C. echo () puede ser utilizado en la versión CLI de PHP, mientras que print () no puede

D. print () puede ser utilizado en la versión CLI de PHP, mientras que echo () no puede

E. No hay ninguna diferencia: ambas funciones mostrarán algunos de texto!

Resp: No hay ninguna diferencia: ambas funciones mostrarán algunos de texto

3. El operador ____ devuelve verdadero si cualquiera de sus operaciones se puede evaluar como verdadera, pero no ambos.

Resp: XOR

4.¿Cuál es el valor que se muestra cuando se ejecuta lo siguiente?

Suponga que el código fue ejecutado utilizando la siguiente URL:  testscript.php? c = 25

<?php

function process($c, $d = 25){

global $e;

$retval = $c + $d – $_GET['c'] – $e;

return $retval;

}

$e = 10;

echo process(5);

?>

A. -5

B. 10

C. 5

D. 0

Resp: -5

5. ¿Se puede desactivar todos los informes de error dentro de un script PHP con una llamada a una función?

A. SI

B. No

Resp: No

Implementación de un carrusel de imágenes con Drupal 6

July 21, 2009 3 comments

Hola en esta ocasión voy a explicar como se implementó un efecto carrusel de imágenes y/o videos para un proyecto en Drupal, lo que se hizo es utilizar el plugin de jquery llamado jscrollable.min.js el cual me da una apariencia de carrusel (elegante), para ello se debe de instalar previamente Drupal, de forma correcta.

Cuando me refiero de forma correcta es saber ubicar donde se van a agregar temas, módulos, files, etc; para ordenarnos desde un principio, luego instalar los módulos necesarios para nuestro site.

Para poder implementar es prerrequisito tener instalado los módulos jquery_update, jquery_plugin para extender los plugins jquery que trae por defecto Drupal, además el CCK y el image upload para la gestión de subida de archivos, y si uno quiere un módulo para miniaturizar imágenes recomiendo Image Api  + Image Cache, y por supuesto pero no necesario un módulo personalizado.

Para más detalle visita este línk donde podrás descargar un ejemplo.

Implementación de un listado de categorías con Drupal 6 usando Taxonomy

July 20, 2009 1 comment

Hola ahora vengo a compartir con ustedes una experiencia que tuve con Drupal para un determinado proyecto, pues bien si no saben que es Drupal en líneas generales le puedo decir que es un CMS + Framework de desarrollo de webs estaticas y dinamicas, para mas información aquí.

Bueno comienzo …. para poder realizar este desarrollo voy a utilizar el modulo Taxonomy del core de Drupal, ayudándome de un módulo personalizado llamado projecto, lo primero que voy hacer es crear vocabularios en la interfaz del administrador de la plataforma previamente instalada.

vocabularios

Ahora comenzamos a crear los términos a los cuales vamos a enlazar a nuestros vocabularios, con los respectivos parentescos.

terminos

Seguidamente nos dirijimos  a nuestro modulo creado y usamos los hooks, para mas informacion aquí; usamos el hook_menu()para crearnos un menu y hook_block para posicionar nuestro listado en un bloque.

Nos creamos una función que se encargará de dibujar (con los estilos que quieras) el listado de cursos, productos, etc.

Y finalmente creamos otra función que imprime el array u objeto (depende), así:

function cies_show_categories() {
// The categories listed
$tree_category = cies_build_categories(); //función que contiene el listado de categorias
$data = ”;
if (!empty($tree_category)) {
foreach ($tree_category as $value) { // lo recorrp
$data .= $value;
}
}
return $data;
}

Espero haber ayudado, gracias y les dejo el link para que puedan acceder a mi presentación.

Categories: desarrollo, php Tags: , , , ,

Subir archivos usando AKelos Framework + validaciones respectivas

May 6, 2009 1 comment

En este post el objetivo es conocer un poco más sobre este poderoso Framework y todas sus bondades, para ello en esta sección voy a compartir con ustedes como subir archivos al servidor y las validaciones respectivas (tamaño, tipo, extension, etc).

Primero como todos sabemos interactuamos con la vista para cargar el archivo a subir, en formato Akelos:

<p><label for=”screenshot_file”>_{Image}</label><br />
<?= $form_tag_helper->file_field_tag(‘screenshot[file]‘); ?> <i>_{Only accepts JPG, JPEG, PNG or GIF (no animation)}</i>
</p>
<p><label for=”screenshot_title”>_{Image description}</label><br />
<?php  echo $active_record_helper->input(‘screenshot’, ‘title’,array(‘maxlength’=>50))?>
</p>

Luego interactúa el controlador primero guardando el nombre del archivo en BD y enviando los datos del archivo en un array a una función dentro del modelo, recojemos los valores POST:

@$fileuploaded = $this->params['screenshot']['file'];
@$this->params['screenshot']['file'] = $this->params['screenshot']['file']['name'];

Enviamos lo datos a la funció setUploadedFile:

$this->Screenshot->setUploadedFile($fileuploaded);

Seteamos la variable para realizar el save() en Akelos:

$this->Screenshot->setAttributes($this->params['screenshot']);

Finalmente ahora el trabajo depende del modelo screenshot.php:

function setUploadedFile($var) {
$this->uploadedfile = $var;
}

Ahora validamos:

function validateOnCreate() {
if ($this->getErrorsOn(‘file’) === false) {
try{
$safe_extension = array(‘png’,'jpeg’,'jpg’,'gif’,'JPG’,'GIF’);  // solo acepta estas extensiones (bueno para imagenes)

if ($this->uploadedfile['error'])
throw new Exception($this->t(‘Error while uploading file!’));

@$path_parts = pathinfo($this->uploadedfile['name']);
if (!empty($path_parts['extension'])) {
if (!in_array($path_parts['extension'],$safe_extension))
throw new Exception($this->t(‘Invalid file type in pictures.’));  // validamos la extension del file
}

} catch (Exception $e) {
$this->addError(‘file’,'<span style=”color:red”>’.$e->getMessage().’</span>’);
}
}
if ($this->hasErrors()) return false;
else return true;
}

Ahora creamos una funcion para parsee el nombre del archivo y lo guarde en el campo file (por ejempo) de la BD:

function beforeCreate(){
@$path_parts = pathinfo($this->uploadedfile['name']);
if (!empty($path_parts['basename'])) {
$name_length = 31 – strlen($path_parts['extension']);
$this->uploadedfile['name'] = AK::randomString($name_length).’.’.$path_parts['extension'];
$this->set(‘file’, $this->uploadedfile['name']);
}
return true;
}

Ahora usamos una función para guardar el file en nuestro servidor.

function afterCreate(){
$root = ‘ruta_path’;
$target_path_root = $root;
AK::make_dir(substr($target_path_root,0,-1)); // crea el directorio si no existe

$target_path = $target_path_root.basename($this->uploadedfile['name']);
move_uploaded_file($this->uploadedfile['tmp_name'], $target_path); // lo copia
return true;
}

Y por últomo una función para elimianr en caso de hacer un destroy():

function beforeDestroy(){
$path = ‘ruta_path’;
@unlink($path.$this->get(‘file’));
return true;
}

Ojo: no cambiar el nombre de las funciones (son propias de Akelos), y si quiero actualizar mi imagen uso en vez de Create -> Update.

Espero que sea de ayuda para aquellos que quieren iniciarse con Akelos, luego explicaré como convertir una imagen a thumbnail.

Instalar Phing y Xinc en Ubuntu

Este proceso de instalación es específico a Ubuntu 9.10. Puede que funcione con otros sistemas operativos o otras versiones, pero solo estamos seguros para esta configuración.

Instalar SimpleTest

Phing necesitará SimpleTest. En el paquete de Chamilo, SimpleTest está disponible como una carpeta con una de las últimas versiones de SimpleTest. Para evitar problemas luego con la versión instalada por el sistema es mejor de instalar la versión que está en Chamilo a nivel del sistema. Hay varias soluciones para hacerlo, de las cuales posiblemente la más limpia es de agregar la carpeta tests/simpletest de Chamilo en el include_path de la config de PHP. Si no quiere tomar el tiempo de hacerlo, en una Ubuntu, puede hacer un sudo apt-get install php-simpletest y después sobreescribir los ficheros en /usr/share/php/simpletest/ con los de Chamilo (es malo, lo sé, pero asumo que la máquina en la cual se hace la instalación es una máquina de desarrollo por ahora).

Instalar Phing

$ sudo pear channel-discover pear.phing.info
$ sudo pear install phing/phing

A este punto, prueba de ejecutar “phing” en la línea de comando. Si el sistema no encuentra el comando, prueba ejecutar el script de configuración de Phing

$ sudo pear run-scripts phing/phing

Esto debería crear un /var/www/phing dentro del cual se puede editar el build.xml para customisarlo. Un ejemplo de build.xml

<?xml version="1.0"?>
<project name="chamilo187" default="clean" basedir=".">
 <target name="empty">
  <echo msg="Cleaning working space..." />
  <delete file="chamilo*.tgz" />
 </target>
 <target name="prepare" depends="empty">
  <echo msg="Preparing build..." />
  <mkdir dir="./chamilo-1.8.7" />
 </target>
 <target name="copy" depends="prepare">
  <echo>Copying...</echo>
  <copy todir="./chamilo-1.8.7/">
   <fileset dir="/var/www/chamilohg">
    <exclude name="**/.svn" />
   </fileset>
  </copy>
  <delete file="**/.svn" />
 </target>
 <target name="syntax-check" depends="copy">
  <phplint>
   <fileset dir="./chamilo-1.8.7">
    <include name="**/*.php"/>
   </fileset>
  </phplint>
  <simpletest printsummary="true">
  <formatter todir="reports" type="plain" />
   <fileset dir="./chamilo-1.8.7/tests">
    <include name="dummy.test.php" />
   </fileset>
  </simpletest>
 </target>
 <target name="documentation" depends="syntax-check">
  <phpdoc title="Chamilo API" destdir="doc" output="HTML:Smarty:PHP">
   <fileset dir="./chamilo-1.8.7">
    <include name="**/*.php" />
   </fileset>
  </phpdoc>
 </target>
 <target name="dist" depends="documentation">
  <echo message="Creating archive..." />
  <tar destfile="chamilo-1.8.7.tgz" compression="gzip">
   <fileset dir="./chamilo-1.8.7">
    <exclude name="**/*.bak" />
   </fileset>
  </tar>
 </target>
 <target name="clean" depends="dist">
  <echo msg="Cleaning up..." />
  <delete dir="./chamilo-1.8.7" includeemptydirs="true" verbose="true" failonerror="true" />
 </target>
</project>

Una vez el proyecto Phing listo (dentro del build.xml), basta lanzar, en línea de comando, un “phing” para iniciar el proceso.

Phing executing in a terminal

Phing executing in a terminal

La documentación (en Inglés) de Phing esta disponible acá: http://phing.info/docs/guide/2.2.0/

Instalar Xinc

Xinc's first screen

Xinc's first screen

$ sudo pear channel-discover pear.xinc.eu
$ sudo pear install xinc/Xinc

El último comando ejecuta montones de cosas.

Según los resultados, es posible que sea necesario ejecutar una serie de comandos adicionales como:

$ sudo pear install channel://pear.xinc.eu/Xinc-2.0.0b196
$ sudo pear install channel://pear.php.net/VersionControl_SVN-0.3.3
$ sudo pear channel-discover components.ez.no
$ sudo pear install channel://components.ez.no/Base
$ sudo pear install channel://components.ez.no/Graph
$ sudo apt-get install php5-xsl

Posiblemente, este paso falla, pero en el mensaje de error aparece el URL que debería cargar en sitio de “xinc/Xinc” en el último comando.

Después de instalar, es necesario ejecutar el comando

$ sudo pear run-scripts xinc/Xinc

Lamentablemente, si ha tenido que usar el URL en lugar de xinc/Xinc, podría ser necesario cambiar este último comando también (algo como pear.xinc.eu/Xinc). Este comando debería retornar algo parecido a esto:

Including external post-installation script "/usr/share/php/Xinc/Postinstall/Nix.php" - any errors are in this script
Inclusion succeeded
running post-install script "Xinc_Postinstall_Nix_postinstall->init()"
init succeeded
 1. Directory to keep the Xinc config files                    : /etc/xinc
 2. Directory to keep the Xinc Projects and Status information : /var/xinc
 3. Directory to keep the Xinc log files                       : /var/log
 4. Directory to install the Xinc start/stop daemon            : /etc/init.d
 5. Directory for xinc`s temporary files                       : /tmp/xinc
 6. Do you want to install the SimpleProject example           : yes
 7. Directory to install the Xinc web-application              : /var/www/xinc
 8. IP of Xinc web-application                                 : 127.0.0.1
 9. Port of Xinc web-application                               : 8080

1-9, 'all', 'abort', or Enter to continue:
Successfully copied /usr/share/php/data/Xinc/xinc.ini.tpl  to: /usr/share/php/data/Xinc/xinc.ini
Successfully copied /usr/share/php/data/Xinc/etc/xinc/*  to: /etc/xinc
Successfully copied /usr/share/php/data/Xinc/examples/SimpleProject  to: /var/xinc/projects
Successfully copied /usr/share/php/data/Xinc/web/.htaccess  to: /var/www/xinc
Successfully copied /usr/share/php/data/Xinc/web/*  to: /var/www/xinc
Successfully copied /usr/share/php/data/Xinc/scripts/xinc-uninstall  to: /usr/bin/xinc-uninstall
Successfully copied /usr/share/php/data/Xinc/scripts/xinc-uninstall.php  to: /usr/bin/xinc-uninstall.php
Xinc installation complete.
- Please include /etc/xinc/www.conf in your apache virtual hosts.
- Please enable mod-rewrite.
- To add projects to Xinc, copy the project xml to /etc/xinc/conf.d
- To start xinc execute: sudo /etc/init.d/xinc start
UNINSTALL instructions:
- pear uninstall xinc/Xinc
- run: /usr/bin/xinc-uninstall to cleanup installed files
[OK] Saved ini settings
Install scripts complete

En este momento, es importante entender que Xinc debe ser el que maneja la actualización desde el repositorio de gestión de versiones. La razón es que xinc se va a encargar de la parte “integración contínua”. Si Xinc no puede manejar el mismo la actualización de mi código, como se va a dar cuenta si hubó un cambio? No puede! Entonces tiene el mismo que poder encontrar los cambios de versiones y darse cuenta si hubó un cambio. Esto implica sacar la parte de actualización automática del Phing, y dejarlo a Xinc.

Al fin de la instalación, es necesario reconfigurar y pasar el virtual host ubicado en /etc/xinc/www.conf dentro de /etc/apache2/sites-available/ y activarlo con

$ sudo cp /etc/xinc/www.conf /etc/apache2/sites-available/xinc.host.ext
$ sudo a2ensite xinc.host.ext
$ sudo /etc/init.d/apache2 reload

Para tener un resultado interesante en Xinc, es necesario tener unos scripts de prueba en SimpleTest o PHPUnit, y Phing instalado (más sobre las pruebas más tarde).

Antes de iniciar Xinc, es necesario configurar un proyecto. En nuestro caso, estaremos montando un proyecto llamado “chamilo” con un repositorio Mercurial en https://sources.beeznest.net/public/chamilo/

$ sudo mkdir -p /var/xinc/projects/chamilo
$ cd /var/xinc/projects/chamilo/
$ sudo hg clone https://sources.beeznest.net/public/chamilo/

Esto descargará la última versión de desarrollo de Chamilo.

Ahora el nuevo problema es que Xinc no soporta Mercurial… Una solución podría ser de ejecutar las cosas relativas a Mercurial en línea de comando desde la tarea Phing, pero lamentablemente Xinc necesita una visibilidad sobre las revisiones de Mercurial para poder devolver resultados interesantes. Por esto hemos desarrollado una versión básica del módulo de Hg para Xinc, que puede pedirnos por correo (no lo ponemos en línea todavía porque no está estable y no queremos que se moleste si le rompe su proyecto).

Configurar el proyecto Xinc

La configuración de Xinc en sí se hace dentro de /etc/xinc/conf.d, donde se encuentra un fichero simpleproject.xml que se puede modificar. Sino quiere tener un proyecto “simpleproject” fantasma, entonces mejor mover este fichero de otro lado y hacer una copia ahí, renombrar el archivo y editar sus detalles *antes* de iniciar Xinc por primera vez (después es bastante complicado de quitar este proyecto fantasma).

Por ejemplo, renombramos el archivo simpleproject.xml en chamilo.xml y le damos el contenido siguiente.

<?xml version="1.0"?>
<xinc engine="Sunrise">
 <project name="chamilo">
 <configuration>
 <setting name="loglevel" value="1"/>
 <setting name="timezone" value="America/Lima"/>
 </configuration>
 <property name="dir" value="${projectdir}/${project.name}"/>
 <schedule interval="3600" />
 <!--cron timer="* */2 * * *"/-->
 <modificationset>
 <hg directory="${dir}/chamilo/" update="true" />
 <!--buildalways/-->
 </modificationset>
 <builders>
 <phingBuilder buildfile="${dir}/build.xml" target="build"/>
 </builders>
 <publishers>
 <simpleTestTestResults file="${dir}/reports/testresults.txt"/>
 <onfailure>
 <email to="ywarnier@beeznest.org"
 subject="${project.name} build ${build.number} failed"
 message="The build failed."/>
 </onfailure>
 <onsuccess>
 </onsuccess>
 <onrecovery>
 <email to="ywarnier@beeznest.org"
 subject="${project.name} build ${build.number} was recovered"
 message="The build passed after having failed before."/>
 </onrecovery>
 </publishers>
 </project>
</xinc>

Analizemos un poco:

<project name="chamilo">

-> el proyecto se llama “chamilo”. Esto también define la variable ${project.name}

<schedule interval="3600" />

-> la actualización corre cada 3600 segundos

<hg directory="${dir}/chamilo/" update="true" />

-> definimos que la fuente del proyecto (hg=mercurial) se encuentra en ${dir} (definido antes), subcarpeta /chamilo/. Desde ahí, y con las tareas Xinc definidas,

<phingBuilder buildfile="${dir}/build.xml" target="build"/>

-> define donde encontrar el archivo de construcción del proyecto (construcción que se hace con Phing)

 <simpleTestTestResults file="${dir}/reports/testresults.txt"/>

-> define donde encontrar el archivo de reporte de las pruebas. Una vez más, faltaba integración para SimpleTest aquí, así que desarrollamos los scripts a partir de los de PHPUnit. Ver http://code.google.com/p/xinc/issues/detail?id=206

Lo demás define como generar reportes en caso de éxito, de falla o de recuperación. En caso de éxito, se podría definir que se ejecuta otro proyecto Phing, que sirve para la construcción del paquete (como por ejemplo hacer un archivo Zip, en la forma de un fichero de configuración Phing package.xml por ejemplo).

Por el hecho de tener el control de versiones hecho a nivel de xinc, podemos tener un build.xml de Phing muy reducido:

<?xml version="1.0"?>
<project name="chamilo" default="build" basedir=".">
 <property name="builddir" value="chamilo/" override="true" />

 <target name="order">
   <echo msg="Copying cli_install..." />
   <copy file="cli_install.php" tofile="./${builddir}main/install/cli_install.php" overwrite="true"/>
   <echo msg="Moving local simpletest copy to avoid using it (use system's library)..." />
   <move file="${builddir}tests/simpletest" todir="${builddir}tests/simpletestbak" includeemptydirs="true" />
 </target>

 <target name="install" depends="order">
   <echo msg="Installing Chamilo..." />
   <exec command="chmod -R 0777 *" dir="${builddir}" />
   <echo msg="Assigned development permissions..." />      
   <exec command="php5 cli_install.php -l admin -p admin -U chamilo -P chamilo -u 'http://phing.chamilo.net' -X 'chamilophing_'" dir="./${builddir}main/install/" />
   <echo msg="Hopefully installed..." />      
 </target>

 <target name="simple-tests" depends="install">
   <echo msg="Starting tests..." />
   <simpletest>
     <formatter todir="reports" type="plain"/>
     <fileset dir="${builddir}tests">
       <include name="all.test3.php" />
     </fileset>
   </simpletest>
 </target>

 <target name="build" depends="simple-tests">
   <echo msg="Cleaning up the database..." />
   <exec command="php5 cleandb.php" dir="." />
   <echo msg="Moving back local simpletest copy..." />
   <move file="${builddir}tests/simpletestbak" todir="${builddir}tests/simpletest" includeemptydirs="true" />
   <echo msg="All clean!" />
 </target>
</project>

Esta combinación de los proyectos Phing y Xinc implica que tenemos que tener una carpeta /var/xinc/projects/chamilo que contenga

  • un repositorio Mercurial de nuestro Chamilo (checkeado con el usuario root para poder hacer la actualización después via Xinc)
  • un script cli_install.php que instale un Chamilo en línea de comando
  • un script cleandb.php que limpie la base de datos después de las pruebas

Si ocurre un error en la construcción, probar de ver los logs de xinc así

$ sudo tail -f /var/log/xinc.log

Si ocurre un error en la construcción del paquete, es posible que tenga más detalles un archivo de log en /var/xinc/projects/chamilo/

Para iniciar Xinc

$ sudo /etc/init.d/xinc start

La documentación (en Inglés) de Xinc esta disponible acá: http://www.xinc.eu/api/documentation/get/file/xinc/latest-successful/Enduser/index.html

Cuando empieza a correr el Xinc, en general (si ha instalado como indicado arriba) en la version 2.0.0 tiene un problema para jalar la buena libreria para generar los graficos. Esto se puede arreglar editando un archivo de Xinc (como indicado en http://code.google.com/p/xinc/issues/detail?id=167):

sudo vim /usr/share/php/Xinc/Plugin/Repos/Gui/Statistics/Graph.php

y ahí, editar la línea 33 (después de un comentario vacío) para agregar

require 'ezc/Base/ezc_bootstrap.php';

y después reiniciar a Xinc con

/etc/init.d/xinc restart

Para parar Xinc

$ sudo /etc/init.d/xinc stop

Retornar arrays con NuSOAP

March 22, 2009 10 comments

Christian escribió un artículo hace unos días sobre la manera de usar NuSOAP para crear un servicio web. El artículo describe en detalles el procedimiento. No obstante, probar de retornar un arreglo es un trabajo bastante complejo en NuSOAP, o por lo menos esta mal documentado. Una excelente referencia (en Inglés) sobre el tema se puede encontrar en el blog de Lyingonthecovers, pero el artículo faltaba (he puesto un comentario ahí) una noción importante que es que NuSOAP debe tener un ‘return’ => ‘xsd:Array’ en su método register() para retornar el formato correcto.

En este artículo, revisaremos como retornar arreglos.

Retornar arreglos simples

Primero, imaginamos, como en el artículo en Inglés de Lyingonthecovers, que queremos hacer un servicio web que retorna, en el caso de Dokeos, detalles sobre un curso.

La función que se encargar de recojer la información se llamará getCourseDetails(), tomará solo un parámetro  tipo string en entrada (para parametros complejos, ver el ejemplo de Christian) y retornará un arreglo del tipo siguiente:

Array(

['code'] => ‘ABC’,

['title'] => ‘English alphabet’,

['url'] => ‘http://www.example.com/ABC&#8217;,

['teacher'] => ‘Yannick Warnier’,

['language'] => ‘english’

)

Hemos definido nuestras necesidades, ahora vamos más adelante y registramos el servicio mismo y sus tipos de datos:

$server = new soap_server();

$server->configureWSDL(‘WSCourse’, ‘urn:WSCourse’);

// definimos el tipo complejo (arreglo asociativo, =’struct’) de detalles de curso

$server->wsdl->addComplexType(
‘courseDetails’,
‘complexType’,
‘struct’,
‘all’,
”,
array(
‘name’=>’code’  , ‘type’=>’xsd:string’,
‘name’=>’title’  , ‘type’=>’xsd:string’,
‘name’=>’url’    , ‘type’=>’xsd:string’,
‘name’=>’teacher’, ‘type’=>’xsd:string’,
‘name’=>’language’,'type’=>’xsd:string’,
)
);

Por favor apunten que declaramos un tipo, pero no hay ninguna relación, al nivél de esta declaración, entre el tipo y un método. Este tipo podrá ser reutilizado para otros métodos también.

// Registramos el método y su parámetro de entrada
$server->register(‘getCourseDetails’,           // nombre método
array(‘username’ => ‘xsd:string’),            //  parametros entrantes al servicio
array(‘return’ => ‘tns:courseDetails’),     // valor(es) retornado(s)
‘urn:WSCourse’,                                            // namespace (espacio de nombre)
‘urn:WSCourse#getCourseDetails’,         // acción SOAP
‘rpc’,                                                                 // estílo
‘encoded’,                                                       // tipo de uso
‘This service returns a list of courses’    // documentación
);

En este caso, usamos directamente un ‘struct’ como valor de retorno. Usamos el marcador ‘tns:’ (probablemente Type NameSpace o algo así) para decir que es un tipo complejo definido por otro lado, y definimos que tipo exactamente queremos usar.

Esto es lo que debería ocurir y, para este caso (no verificado), tal vez funcionaría. Si no funciona, prueben remplazar tns:courseDetails por xsd:Array, simplemente (vemos más abajo casos probados).

En el caso un poco más complejo en que tenga que devolver un arreglo de estos courseDetails, como hago?

Arreglos de arreglos

Una estructura a dos niveles no se puede definir en solo una definición de ComplexType. En sí, se tiene que definir cada nivel como un ComplexType:

$server->wsdl->addComplexType(
‘courseDetails’,
‘complexType’,
‘struct’,
‘all’,
”,
array(
‘name’=>’code’  , ‘type’=>’xsd:string’,
‘name’=>’title’  , ‘type’=>’xsd:string’,
‘name’=>’url’    , ‘type’=>’xsd:string’,
‘name’=>’teacher’, ‘type’=>’xsd:string’,
‘name’=>’language’,'type’=>’xsd:string’,
)
);

Nada cambia para esta primera parte. Ahora definimos el arreglo que va a contener estos structs:

$server->wsdl->addComplexType(
‘courseList’,
‘complexType’,
‘array’,
”,
‘SOAP-ENC:Array’,
array(),
array(
array(‘ref’=>’SOAP:ENC:arrayType’,
‘wsdl:arrayType’=>’tns:courseDetails[]‘)
),
‘tns:courseDetails’
);

Bueno, hay mucho que todavía no hemos detallado ahí, pero no es directamente el objetivo de este artículo. Una cosa es importante: esto es la forma de declarar un arreglo (no asociativo, es decir con indices numéricos unicamente) del ComplexType courseDetails.

Una vez que tenemos esto listo, la lógica nos haría pensar que simplemente debería registrar este tipo complejo en mi servicio web:

// Registramos el método y su parámetro de entrada
$server->register(‘getCourseDetails’,           // nombre método
array(‘username’ => ‘xsd:string’),            //  parametros entrantes al servicio
array(‘return’ => ‘tns:courseList’),          // valor(es) retornado(s)
‘urn:WSCourse’,                                            // namespace (espacio de nombre)
‘urn:WSCourse#getCourseDetails’,         // acción SOAP
‘rpc’,                                                                 // estílo
‘encoded’,                                                       // tipo de uso
‘This service returns a list of courses’    // documentación
);

… y ahí es donde perdimos horas buscando. En realidad, parece que hay algo malo ahí, en la forma en que NuSOAP (a lo menos versión de Agosto de 2008) retorna este valor, que es incorrecto. Resulta que el cliente SOAP de PHP5 no entiende el valor retornado. Ni para este arreglo de structs, ni para el struct mismo.

Abandonar la definición de tipos complejos

La solución es de abandonar la idea de definir el tipo de valor retornado, y simplemente usar xsd:Array como valor de retorno:

// Registramos el método y su parámetro de entrada
$server->register(‘getCourseDetails’,           // nombre método
array(‘username’ => ‘xsd:string’),            //  parametros entrantes al servicio
array(‘return’ => ‘xsd:Array’),          // valor(es) retornado(s)
‘urn:WSCourse’,                                            // namespace (espacio de nombre)
‘urn:WSCourse#getCourseDetails’,         // acción SOAP
‘rpc’,                                                                 // estílo
‘encoded’,                                                       // tipo de uso
‘This service returns a list of courses’    // documentación
);

No hay lógica ahí, es cierto, pero a lo menos espero que les ayudarán. Me estoy comunicando con los desarrolladores de NuSOAP para averiguar el tema.

Categories: desarrollo, técnico Tags: , , , , ,

mbstring vs iconv benchmarking

October 5, 2008 6 comments

Following up on my previous post about the differences between the mbstring and iconv international characters libraries (which resulted in a tentative conclusion that nobody knew anything about those differences), and particularly the comments by Nicola, we have combined forces (mostly efforts from Nicola, actually) to provide you with a little benchmarking, if that can help you decide.

Nicola wrote the following script (which he gladly releases as public domain license) to test the efficiency of both the mbstring and iconv extensions for PHP5:

<?php

ini_set(‘iconv.internal_encoding’, ‘UTF-8′);
ini_set(‘mbstring.internal_encoding’, ‘UTF-8′);

function dummy_strlen($str)
{
}

function scan_file($file, $strlen)
{
fseek($file, 0);

$chars = 0;
$lines = 0;
$start_time = microtime(true);

while (!feof($file)) {
$chars += $strlen(fgets($file));
++$lines;
}

// Calculating elapsed time
$sec = microtime(true) – $start_time;
$usec = (int) ($sec * 1000000);

// Formatting
$strlen = str_pad($strlen, 20);
$usec = str_pad($usec, 10);

echo “$strlen$usec($lines lines and $chars chars)\n”;
}

// Text: 13083-utf8.txt
// From: http://www.gutenberg.org/files/13083/13083-utf8.txt

$file = fopen(’13083-utf8.txt’, ‘r’);

scan_file($file, ‘dummy_strlen’);
scan_file($file, ‘strlen’);
scan_file($file, ‘mb_strlen’);
scan_file($file, ‘iconv_strlen’);

fclose($file);

?>

Although we were expecting boring results, they are actually quite interesting. The following are results for the script above (always prefixed by the system details)

Linux amd64 2.6.26-ntd #1 PREEMPT Mon Jul 28 18:54:30 CEST 2008
x86_64 x86_64 x86_64 GNU/Linux

PHP 5.2.4 (cli)
iconv library version => 2.5
Multibyte regex (oniguruma) version => 4.4.4

dummy_strlen 5853 (4485 lines and 0 chars)
strlen 4853 (4485 lines and 150846 chars)
mb_strlen 8574 (4485 lines and 140932 chars)
iconv_strlen 38774 (4485 lines and 140932 chars)

————

PHP 5.2.4 (CLI version)
iconv 2.7 for glibc
mbstring regex oniguruma 4.4.4 (string engine libmbfl)
on an Apple Mac Book Pro (II), at 2.1GHz

dummy_strlen        15965     (4485 lines and 0 chars)
strlen              12470     (4485 lines and 150846 chars)
mb_strlen           34167     (4485 lines and 140932 chars)
iconv_strlen        48865     (4485 lines and 140932 chars)

Second execution (caching might help):
dummy_strlen        15692     (4485 lines and 0 chars)
strlen              12532     (4485 lines and 150846 chars)
mb_strlen           14727     (4485 lines and 140932 chars)
iconv_strlen        40086     (4485 lines and 140932 chars)

Tenth execution (stabilised):
dummy_strlen        15661     (4485 lines and 0 chars)
strlen              8369      (4485 lines and 150846 chars)
mb_strlen           6906      (4485 lines and 140932 chars)
iconv_strlen        34092     (4485 lines and 140932 chars)

—–

PHP 5.2.4 (Apache 2 version)
iconv 2.7 for glibc
mbstring regex oniguruma 4.4.4 (string engine libmbfl)
on an Apple Mac Book Pro (II), at 2.1GHz

dummy_strlen  38218 (4485 lines and 0 chars)
strlen        35356 (4485 lines and 150846 chars)
mb_strlen     35804 (4485 lines and 140932 chars)
iconv_strlen  66275 (4485 lines and 140932 chars)

And second execution:

dummy_strlen  52164 (4485 lines and 0 chars)
strlen        34219 (4485 lines and 150846 chars)
mb_strlen     35706 (4485 lines and 140932 chars)
iconv_strlen  65080 (4485 lines and 140932 chars)

Tenth execution:

dummy_strlen  59885 (4485 lines and 0 chars)
strlen        35341 (4485 lines and 150846 chars)
mb_strlen     36179 (4485 lines and 140932 chars)
iconv_strlen  66632 (4485 lines and 140932 chars)

The evident conclusion from this set of results is that iconv is quite slower than mbstring, although we do not have enough insight to tell if this is due to a compilation difference or anything like that.

The idea is that anyway, we have configurations identical to what most people will have, so it is very likely that the results will be the same in many cases, and as such iconv should be avoided for efficiency reasons, unless some of its very specific functions are required.

You can download the text file used in this example from here:http://mirror3.mirrors.tds.net/pub/gutenberg.org/1/3/0/8/13083/13083-utf8.txt

You will have to copy and paste the script above (there is no way to upload a simple text file here).

Categories: Development, Techie Tags: , , ,

Instalar Kcachegrind en Ubuntu 8.04

September 17, 2008 Leave a comment

Kcachegrind es una aplicación que nos muestra gráficamente el consumo de tiempo y memoria que un proceso php (función, comando) provoca a un servidor Apache. Aqui una manera facil de instalarlo:

En un terminal ejecutar:

sudo apt-get install kcachegrind
sudo apt-get install php5-xdebug

Configurar estos parametros en el php.ini o en la carpeta /etc/apache2/site-available/sitename

php_admin_value xdebug.profiler_enable 1
php_admin_value xdebug.profiler_output_dir /tmp/kcache

Donde /tmp/kcache es la carpeta donde se guardarán los archivos generados, para luego poder verlos con en Aplicaciones->Programación->Kcachegrind

es necesario que la carpeta /tmp/kcache tenga permisos de escritura

sudo chmod 777 -R /tmp/kcache

Estoy suponiendo que tenemos ya instalado el apache2 y php5 correctamente instalados.

Follow

Get every new post delivered to your Inbox.

Join 34 other followers

%d bloggers like this: