jueves, 8 de junio de 2017

Node.js 8 ya está aquí y esto es lo que trae

"Grandes mejoras para la depuración, y para el ecosistema de módulos nativos". Esta fue la descripción dada por parte del equipo desarrollador de Node.js para esta nueva versión que ha salido hace apenas un par de días. Las actualizaciones y características destacadas incluyen de la adición de la API Node.js para los desarrolladores de módulos nativos, async_hooks, enlaces JS para el inspector, Buffers de cero llenado, util.promisify y más.

Aunque la versión 8 reemplazará inmediatamente a la versión 7 como la actual versión, no obtendrá su estado como la versión de soporte a largo plazo (LTS) hasta finales de este año, por lo tanto, la fundación Node.js sugiere a las empresas esperen hasta entonces para poder actualizarse:
"Aquellos que necesitan estabilidad y tienen grandes ambientes de producción complejos (es decir, medianas y grandes empresas) deben esperar hasta que Node.js 8 entre en LTS antes de actualizarlo para su producción"

Node.js 8 se aprovechará de V8 5.8, el motor de JavaScript de google que se usa en Chrome. Este es un paso importante por que se estima una actualización a V8 5.9 más adelante. Esta será la primera versión con el interprete de ignición activado de forma predeterminada.

Este lanzamiento también trae consigo una actualización a npm a su versión 5.0. El rendimiento obtenido con esta actualización solo debería hacer que el desarrollo con node sea menos doloroso.

La nueva función util.promsify() permite a los desarrolladores convertir cualquier función escrita con "tradicional" Node.js callback en una Promesa. Esto, a su vez, permite el uso de async/await. Una vez más, por que 8.x tendrá una versión LTS más tarde, marcará la primera versión LTS que admite async/await. Se habilitó por primera vez por defecto en la versión 7.6, aunque muchas empresas optan por no ejecutar esta versión. Esta noticia ha hecho que algunos desarrolladores estén muy contentos:
"Este es un gran lanzamiento. Async/await en un núcleo estable es algo que he estado esperando (literalmente) durante 6 años. Async/await es un salto gigantesco para hacer Node utilizable tanto para principiantes como expertos. Este lanzamiento es una gran celebración" -Palabras por parte de HackerNews

sábado, 10 de diciembre de 2016

Instalando NGINX con Google Page Speed en Ubuntu

¿Que es NGINX?


nginxNginx es un servidor web de alto rendimiento, libre, multiplataforma y de código abierto, que cuenta también con un proxy para protocolos de correo electrónico (IMAP/POP3).

La herramienta se distribuye bajo la Licencia BSD simplificada y cuenta con una versión comercial. Es una de las más utilizada para el Alojamiento web, destacando entre sus usuarios a WordPress, Netflix, Hulu, GitHub, Ohloh, SourceForge, TorrentReactor, hostinger entre otros.

Según datos oficiales: “NGINX es el segundo servidor web más usado en dominios activos (14,35%) superando a Microsoft Information Server. Además, pasó la marca de ser usado en más de 100 millones de sitios”.

¿Que es Google Page Speed?


google-pagespeedGoogle Page Speed es un modulo de NGINX creado por Google el cual permite ayuda a acelerar la carga de los sitios web sin necesidad de hacer mucho trabajo.

El módulo recibe el nombre de ngx_pagespeed, y tiene la función de reescribir las páginas web para hacerlas más rápidas comprimiendo imágenes, minimizando el CSS y JavaScript, extendiendo la vida del Caché entre otras prácticas que son recomendadas en la optimización de un sitio web.

 

¿Como instalar NGINX con el módulo de Google Page Speed?


Para hacer esto existen dos maneras, la "facil" que consiste en un script que ejecuta la instalación de todas las dependencias necesarias y la "dificil" que sería la manera manual de hacerlo.

[divider]INSTALADOR AUTOMÁTICO[/divider]

Para instalar las dependencias automáticamente con la última versión de NGINX y Google Page Speed solo basta con correr el siguiente comando en consola:
bash <(curl -f -L -sS https://ngxpagespeed.com/install

Para ver las otras opciones de instalación, incluyendo opciones para elegir la versión de nginx o ngx_pagespeed, o incluso instalar ngx_pagespeed como un módulo dinámico basta con correr el siguiente comando:
bash <(curl -f -L -sS https://ngxpagespeed.com/install) --help

 

[divider]INSTALANDO MANUALMENTE[/divider]

Para hacerlo de la manera manual, es necesario instalar primero las dependencias necesarias:
sudo apt-get install build-essential zlib1g-dev libpcre3 libpcre3-dev unzip

Luego de eso configuramos las siguientes variables:
PS_NGX_EXTRA_FLAGS="--with-cc=/usr/lib/gcc-mozilla/bin/gcc  --with-ld-opt=-static-libstdc++"
NPS_VERSION=[Puedes ver la última versión de Page Speed aquí : https://goo.gl/N2AYzr]
NGINX_VERSION=[Puedes ver la última versión de NGINX aquí: https://goo.gl/ukV8d3]
psol_url=https://dl.google.com/dl/page-speed/psol/${NPS_VERSION}.tar.gz

Ahora procedemos a descargar ngx_pagespeed:
cd
wget https://github.com/pagespeed/ngx_pagespeed/archive/v${NPS_VERSION}-beta.zip
unzip v${NPS_VERSION}-beta.zip
cd ngx_pagespeed-${NPS_VERSION}-beta/
[ -e scripts/format_binary_url.sh ] && psol_url=$(scripts/format_binary_url.sh PSOL_BINARY_URL)
wget ${psol_url}
tar -xzvf $(basename ${psol_url})

Ahora descargamos e instalar NGINX con soporte para Google Page Speed:
cd
wget http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz
tar -xvzf nginx-${NGINX_VERSION}.tar.gz
cd nginx-${NGINX_VERSION}/
./configure --add-module=$HOME/ngx_pagespeed-${NPS_VERSION}-beta ${PS_NGX_EXTRA_FLAGS}
make
sudo make install

Ya con eso está todo listo y funcionando. En la documentación oficial de NGINX pueden encontrar todo lo relacionado a este software opensource, desde la guía para principiantes hasta otros módulos que pueden ser de utilidad para tu servidor web

miércoles, 30 de noviembre de 2016

Por qué las unidades de almacenamiento no vienen completas?

De antaño muchos han pensado que las unidades de almacenamiento de cualquier indole (discos duros, memorias usb, cd's, etc...) nunca vienen completas, lo cual es un error bastante común entre usuarios poco curiosos. La verdad es que esta confusión nace debido a los 2 sistemas de medidas de almacenamiento de información existentes: Las unidades de información binarias kibibyte, mebibyte, gibibyte etc. Y las unidades del sistema internacional de medidas: kilobyte, megabyte, gigabyte etc. Pero que diferencia existe realmente entre estos dos? y a que viene que nuestras unidades nunca tengan el tamaño que dicen tener? Vamos al grano:


Un kilobyte (representado como kB) son 1000 bytes (puesto que el prefijo griego 'kilo' significa mil), mientras que el kibibyte (o también kilo-binary byte, el cual representado como KiB) contiene 1024 bytes de información. Si probablemente tu también pensaste que 1kB eran 1024 bytes, pues no.


Resolviendo el enigma de nuestra unidad de almacenamiento:


Suponiendo que tenemos un Disco duro que dice tener 1000GB o lo que es lo mismo 1TB de almacenamiento, lo convertiremos a bytes para comprobar que estamos en lo cierto


1.000 gigabytes (GB) = 1.000.000 de megabytes (MB) =  1.000.000.000 de kilobytes (kB) = 1.000.000.000.000 de bytes.


Haciendo el proceso inverso:


1.000.000.000.000 bytes/1024 =  976.562.500 kibibytes(KiB) / 1024 = 953.674,316406 mebibytes (MiB) / 1024 = 931,32 gibibytes (GiB)


Es por eso esto, que al conectar nuestro nuevo disco duro de 1TB (1000GB) a nuestro ordenador cuando vemos el espacio de almacenamiento disponible nos indica 931,32GiB.


Conociendo esto ya sabemos que no hemos sido estafados y que el disco en realidad posee el almacenamiento que dice tener, solo que nuestro ordenador lo lee de manera diferente,es decir, la manera binaria.

Conceptos básicos del Modelo Entidad-Relación

Antes de hablar de los Modelos de Entidad-Relación, cabe resaltar que la siguiente información fue tomada del libro de Fundamentos de Bases de Datos, de Abaham Silberschatz.



Sistema gestor de bases de datos (SGBD)


Consiste en una colección de datos interrelacionados y un conjunto de programas para acceder a dichos datos. La colección de datos, normalmente denominada base de datos, contiene información relevante para el sistema.



Problemas a solucionar mediante BD



  • Redundancia e inconsistencia de datos

  • Dificultad en el acceso a los datos

  • Aislamiento de datos

  • Problemas de integridad

  • Problemas de atomicidad

  • Anomalías en el acceso concurrente

  • Problemas de seguridad


Modelo Entidad-Relación


El modelo de datos Entidad-Relación está basado en una percepción del mundo real consistente en objetos básicos llamados entidades y de relaciones entre estos objetos. Se desarrolló para facilitar el diseño de bases de datos permitiendo la especificación de un esquema de la empresa que representa la estructura lógica completa de una base de datos.



Elementos básicos del Modelo Entidad-Relación


Los elementos que componen al Modelo de Entidad-Relación son los siguientes:




  • Entidades: Una entidad es una «cosa» u «objeto» en el mundo real que es distinguible de todos los demás objetos. Un conjunto de entidades es un conjunto de entidades del mismo tipo que comparten las mismas propiedades, o atributos.

  • Relaciones: Una relación es una asociación entre diferentes entidades. Un conjunto de relaciones es un conjunto de relaciones del mismo tipo.

  • Atributos: Los atributos describen propiedades que posee cada miembro de un conjunto de entidades. La designación de un atributo para un conjunto de entidades expresa que  la base de datos almacena información similar concerniente a cada entidad del conjunto de entidades; sin embargo, cada entidad puede tener su propio valor para cada atributo.


Clasificaciones de Atributos


Los atributos se clasifican por:




  • Atributos simples y compuestos. Un atributo simple es aquel que no esta dividido en subpartes. En cambio los atributos compuestos pueden dividirse en subpartes, por ejemplo, si tenemos una entidad llamada usuario y un atributo sea nombre, este podria estar estructurado en un atributo compuesto de la siguiente forma en nombre, primer-apellido, segundo apellido.

  • Atributos monovalorados y multivalorados. Se llaman monovalorados a los atributos que tienen todos un valor sólo para una entidad concreta. Por ejemplo, el atributo número para una entidad préstamo específico, referencia a un único número de préstamo. Y los multivalorados,  se presenta en ocaciones, en las que un atributo tiene un conjunto de valores para una entidad específica. Por ejemplo, considérese un conjunto de entidades empleado con el atributo número-teléfono. Cualquier empleado particular puede tener cero, uno o más números de teléfono.

  • Atributos derivados. El valor para este tipo de atributo se puede derivar de los valores de otros atributos o entidades relacionados. Por ejemplo, sea el conjunto de entidades cliente que tiene un atributo préstamos que representa cuántos préstamos tiene un cliente en el banco. Ese atributo se puede derivar contando el número de entidades préstamo asociadas con ese cliente.


Ejemplo de conjunto de entidades


Se observara dos tablas llamadas Cliente y Préstamo, en este caso esas serian nuestras entidades, por como ya se explico una entidad es un objeto con características o atributos propias de ella. Como en este caso podemos ver que la tabla cliente tiene como atributos nombres, cédula.




[caption id="attachment_464" align="alignnone" width="430"]Ejemplo Modelo Entidad-Relación Ejemplo de conjunto de entidades[/caption]

Ejemplos de Atributos compuestos


En la siguiente imagen se muestran varios ejemplos de atributos compuestos.




[caption id="attachment_465" align="alignnone" width="457"]Ejemplo Modelo Entidad-Relación Ejemplo de atributos compuestos[/caption]

Ejemplo de Conjunto de Relaciones


Considérense las dos entidades cliente y préstamo del primer ejemplo. Se define el conjunto de relaciones prestatario para denotar la asociación entre clientes y préstamos bancarios que los clientes tengan. Esta asociación se describe en la siguiente imagen.




[caption id="attachment_466" align="alignnone" width="451"]Ejemplo Modelo Entidad-Relación Ejemplo de conjunto de relaciones[/caption]

Correspondencia de cardinalidades


Expresa el número de entidades a las que otra entidad puede estar asociada vía un conjunto de relaciones.




  • Uno a uno

  • Uno a varios

  • Varios a uno

  • Varios a varios


Correspondencia uno a uno


Una entidad en A se asocia solo con una entidad de B, y una entidad en B se asocia solo con una entidad en A.




[caption id="attachment_467" align="alignnone" width="358"]Cardinalidad Cardinalidad Uno a Uno[/caption]

Correspondencia uno a varios


Una entidad en A se asocia con cualquier cantidad de entidades en B (ninguna o varias). Una entidad en B, sin embargo, se puede asociar solo con una entidad en A.




[caption id="attachment_468" align="alignnone" width="338"]Cardinalidad Cardinalidad Uno a Varios[/caption]

Correspondencia varios a uno


Esta es muy parecida a la correspondencia anterior si no que es al revés, es donde una entidad en A se asocia solo con una entidad en B. Una entidad en B, sin embargo, se puede asociar con cualquier cantidad de entidades (ninguna o varias) en A.




[caption id="attachment_469" align="alignnone" width="380"]Cardinalidad Cardinalidad Varios a Uno[/caption]

Correspondencia varios a varios


Una entidad en A se asocia con cualquier cantidad de entidades (ninguna o varias) en B, y una entidad en B se asocia con cualquier cantidad de entidades (ninguna o varias) en A.




[caption id="attachment_470" align="alignnone" width="396"]Cardinalidad Cardinalidad Varios a Varios[/caption]

Participación total


La participación de un conjunto de entidades E en un conjunto de relaciones R se dice que es total si cada entidad en E participa al menos en una relación en R.



Participación parcial


Si sólo algunas entidades en participan en relaciones en R, la participación del conjunto de entidades E en la relación R se llama parcial.



Diagramas Entidad-Relación


Relación uno a varios


En la siguiente imagen se observar una relación de uno a varios debido a que un cliente puede tener ningún o muchos préstamos, pero un préstamos solo puede tener un cliente.




[caption id="attachment_472" align="alignnone" width="408"]Relación Relación Uno a Varios[/caption]

[stextbox id="info" bgcolor="eeeeee" cbgcolor="eeeeee" bgcolorto="eeeeee" cbgcolorto="eeeeee"]Nota: Una línea dirigida desde el conjunto de relaciones prestatario al conjunto de entidades préstamo especifica que prestatario es un conjunto de relaciones uno a uno, o bien varios a uno, desde cliente a préstamo; prestatario no puede ser un conjunto de relaciones varios a varios ni uno a varios, desde cliente a préstamo.[/stextbox]



Relación varios a uno


Se observar una relación de varios a uno debido a que un préstamo puede tener ningún o muchos clientes, pero un cliente solo puede tener un préstamo.




[caption id="attachment_473" align="alignnone" width="401"]Relación Relación Varios a Uno[/caption]

Relación uno a uno


Se observar una relación de uno a uno debido a que un cliente solo puede tener un préstamos, y un préstamos solo puede tener un cliente.




[caption id="attachment_474" align="alignnone" width="446"]Relación Relación Uno a Uno[/caption]

Relación varios a varios


Se observar una relación de varios a varios debido a que un cliente puede tener ningún o muchos préstamos, y un préstamos puede tener ningún o muchos clientes.




[caption id="attachment_475" align="alignnone" width="432"]Relación Relación Varios a Varios[/caption]

[stextbox id="info" bgcolor="eeeeee" cbgcolor="eeeeee" bgcolorto="eeeeee" cbgcolorto="eeeeee"]Nota: Una línea no dirigida desde el conjunto de relaciones prestatario al conjunto de relaciones préstamo especifica que prestatario es o bien un conjunto de relaciones varios a varios, o bien uno a varios, desde cliente a préstamo.[/stextbox]

sábado, 19 de noviembre de 2016

Introduccion a Android y el IDE Android Studio

Google acapara cada vez más y pasos agigantados el mercado de la tecnología controlando de este modo el manejo de la información, tanto, que ya hace muchos años dejó de ser un simple buscador, ofreciéndonos una cantidad de herramientas que nos permiten hacer el trabajo, la vida y hasta el ocio más agradables. una de sus grandes adquisiciones fue el SO android que hoy podemos ver en la mayoría de los dispositivos móviles  debido a la gran aceptación que tuvo. Pero, con la creación de un nuevo SO siempre viene de la mano un problema para los desarrolladores ¿donde creó aplicaciones para este? ¿qué herramientas y beneficios me ofrece?.


Originalmente se solventó la necesidad de un entorno de desarrollo para la creación de aplicaciones android con las herramientas que nos ofrecía eclipse, por medio de un plugin de código libre que podemos integrar a este (y digo podemos porque todavía se puede) algo en lo que no nos centraremos en este post, pero se debe anotar que este id fue un precursor que impulsó a muchos desarrolladores a involucrarse en este mundo de las aplicaciones móviles.


En 2013 google da a conocer su propio IDE (Development Environment o Entorno de Desarrollo Integrado traducido al español) llamado Android Studio en la Google I/O, aunque la primera versión estable no salió hasta 2014. Este ha sido un IDE de muchos cambios y mejoras, con la inclusión de  cada vez más herramientas, una de las más importantes fue la creación del material design por google, está cambió el modo en que vemos los recursos y las interfaces dándonos una gran gama de diseño pero esto es material de otro post , por ahora empezaremos explicando la estructura  de Android Studio para que nos sirven cada uno de sus recursos o  carpetas que este nos ofrece para programar de una manera más organizada.


Sabemos que la programación en Android consta de dos Lenguajes esenciales xml y java. Android Studio  divide el uso e integración de estos lenguajes en una serie de carpetas donde se realizará la programación de cada una de estas según se necesite. Estas carpetas aparecen en la parte izquierda de su entorno de desarrollo  y se ven como se puede observar en la siguiente imagen.


post1_1


 AndroidManifest.


Todas las aplicaciones debe constar de un  AndroidManifest.xml  debido a que esta proporciona la   información necesaria al sistema android sobre tu aplicación, como permisos o servicios que necesita esta para su correcto funcionamiento. sus principales funciones son:




  • Nombra el paquete de Java para la aplicación. El nombre del paquete sirve como un identificador único para la aplicación.

  • Describe los componentes de la aplicación, como las actividades, los servicios, los receptores de mensajes y los proveedores de contenido que la integran. También nombra las clases que implementa cada uno de los componentes y publica sus capacidades, como los mensajes Intent con los que pueden funcionar. Estas declaraciones notifican al sistema Android los componentes y las condiciones para el lanzamiento.

  • Determina los procesos que alojan a los componentes de la aplicación.

  • Declara los permisos debe tener la aplicación para acceder a las partes protegidas de una API e interactuar con otras aplicaciones. También declara los permisos que otros deben tener para interactuar con los componentes de la aplicación.

  • Enumera las clases Instrumentation que proporcionan un perfil y otra información mientras la aplicación se ejecuta. Estas declaraciones están en el manifiesto solo mientras la aplicación se desarrolla y se quitan antes de la publicación de esta.

  • Declara el nivel mínimo de Android API que requiere la aplicación.

  • Enumera las bibliotecas con las que debe estar vinculada la aplicación.


A continuacion se mestra la estructura general del archivo AndroidManifest.xml No todas las etiquetas son necesarias, algunas se colocan en la forma en que se necesiten . las etiquetas completamente básicas son  <manifest> y <application> y estas se colocan cuando creas un proyecto en android studio.


           



?xml version="1.0" encoding="utf-8"?>

<manifest>

<uses-permission />
<permission />
<permission-tree />
<permission-group />
<instrumentation />
<uses-sdk />
<uses-configuration />
<uses-feature />
<supports-screens />
<compatible-screens />
<supports-gl-texture />

<application>

<activity>
<intent-filter>
<action />
<category />
<data />
</intent-filter>
<meta-data />
</activity>

<activity-alias>
<intent-filter> . . . </intent-filter>
<meta-data />
</activity-alias>

<service>
<intent-filter> . . . </intent-filter>
<meta-data/>
</service>

<receiver>
<intent-filter> . . . </intent-filter>
<meta-data />
</receiver>

<provider>
<grant-uri-permission />
<meta-data />
<path-permission />
</provider>

<uses-library />

</application>

</manifest>

 Java.


En esta carpeta encontraran o se colocara todo el codigo java de tu aplicación incluida la clase MainActivity.java  que en algunso casos seria la principal, el paquete en el que se incluyen com.exemplo.haskhell.ejemplo  puede ser diferente en todos  las aplicaciones, ya que este se puede modificar al crear el proyecto o dejarse por defecto el que te cree el entorno.Este paquete albergara todas las clases,interfaces etc.Que nos proporciona java.


las otros paquetes que aparecen son para realizar test a tu aplicación android pero eso es material para otro post.


Res.


Este gran paquete contiene todos los recursos que necesitará tu aplicacion android tanto a nivel de diseño de vistas como datos que necesitará para la ejecución




  • Drawable.
    En esta carpeta se guardan todos aquellos recursos, que sean imágenes o archivos xml que contengan cualquier recurso drawables



  • Layout.
    Un diseño define la estructura visual para una interfaz de usuario, como la IU para una actividad o widget de una app. Puedes declarar un diseño de dos maneras:



  1. Declarar elementos de la IU en XML. Android proporciona un vocabulario XML simple que coincide con las clases y subclases de vistas, como las que se usan para widgets y diseños.

  2. Crear una instancia de elementos del diseño en tiempo de ejecución. Tu aplicación puede crear objetos View y ViewGroup (y manipular sus propiedades) programáticamente.


El framework de Android te ofrece la flexibilidad de usar uno de estos métodos o ambos para declarar y administrar la IU de tu aplicación. Por ejemplo, podrías declarar los diseños predeterminados de la aplicación en XML, incluidos los elementos de pantalla que aparecerán en ellos y sus propiedades. Luego podrías agregar código en tu aplicación para modificar el estado de los objetos de la pantalla, incluidos los declarados en XML, en tiempo de ejecución.




  1. También puedes probar la herramienta Visor de jerarquía para depurar diseños; revela valores de propiedad del diseño, dibuja mallas (wireframes) con indicadores de márgenes/relleno y vistas completas mientras depuras en el emulador o dispositivo.

  2. La herramienta layoutopt te permite analizar rápidamente tus diseños y jerarquías para detectar ineficiencias y otros problemas.


La ventaja de declarar tu IU en XML es que te permite separar la vistas de tu aplicación del código que controla su comportamiento. Tus descripciones de la IU son externas al código de tu aplicación, lo que significa que puedes modificarlo o adaptarlo sin tener que modificar el código fuente y volver a compilar. Por ejemplo, puedes crear diseños XML para diferentes orientaciones de pantalla, diferentes tamaños de pantalla de dispositivos y diferentes idiomas. Además, declarar el diseño en XML facilita la visualización de la estructura de tu IU, de modo que sea más fácil depurar problemas. Este documento se centra en enseñarte cómo declarar tu diseño en XML. Si te interesa crear instancias de objetos View en tiempo de ejecución, consulta las referencias de las clases ViewGroup y View.


En general, el vocabulario XML para declarar elementos de la IU sigue de cerca la estructura y la denominación de las clases y los métodos, en los que los nombres de los elementos coinciden con los nombres de las clases y los nombres de los atributos coinciden con los métodos. De hecho, la correspondencia generalmente es tan directa que puedes deducir qué atributo XML corresponde a un método de clase, o deducir qué clase corresponde a un elemento XML determinado. No obstante, ten en cuenta que no todo el vocabulario es idéntico. En algunos casos, hay pequeñas diferencias de denominación. Por ejemplo, el elemento EditText tiene un atributo text que coincide con EditText.setText().



<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">

<TextView
android:id="@+id/text"
android:textSize="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="HOLA, I am a TextView"
android:textColor="@color/colorPrimaryDark" />

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:textSize="20dp"
android:text="HOLA, I am a Button" />
</LinearLayout>

vista-ejemplo




  • Mipmap.


Pues es esta es facil aqui se guardaran todos los iconos que necesita tu aplicación en cada una de las densidades,  de esta manera android elegirá la adecuada dependiendo del dispositivo en el que se ejecute.


mimap




  • Values.


Contiene todos los valores constantes de tu aplicación estilos,texto,tamaños,colores etc.Estas carpetas son:




  • Colors.


Deberá contener todos los colores que utilizaras en tu aplicación.



<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
</resources>


  • Dimens.


Deberá incluir todas las dimensiones que utilizara su aplicación.



<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>


  • Strings.


Se recomiendan contenga el texto que utiliza su aplicación, debido a que este le beneficia si desea hacer su aplicación multi idiomas, si ese es su deseo solo tendrá que traducir el contenido de String.xml y android automáticamente sabrá que string ejecutar dependiendo del idioma del dispositivo.



<resources>
<string name="app_name">Mi aplicacion</string>
<string name="Text">hola mundo</string>
</resources>


  • Styles.


Un recurso de estilo define el formato y busque una interfaz de usuario. Un estilo se puede aplicar a un individuo View (desde dentro de un archivo de diseño) o para toda una Activity aplicación o (desde dentro del archivo de manifiesto).



<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

</resources>

Build.Gradel(Module:app).


Aquí es donde se agregan las librerías en android de una manera fácil. También se especifican las condiciones de lanzamiento de su aplicación.


El sistema de construcción Android recopila recursos de aplicaciones y código fuente, y las empaqueta en los archivos APK que se puede probar, implementar, firmar y distribuir. Android Studio utiliza Gradle , un avanzado juego de herramientas de construcción, para automatizar y administrar el proceso de construcción, mientras que le permite definir configuraciones flexibles de generación personalizada. Cada configuración de generación puede definir su propio conjunto de código y recursos, mientras que la reutilización de las partes comunes a todas las versiones de su aplicación. El plugin de Android para Gradle funciona con el kit de herramientas de construcción para proporcionar procesos y parámetros configurables que son específicos de la construcción y prueba de aplicaciones de Android.



apply plugin: 'com.android.application'

android {
compileSdkVersion 24
buildToolsVersion "24.0.0"
defaultConfig {
applicationId "com.exemplo.haskhell.ejemplo"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
}

en la parte de dependencias es donde se agregarían todas las librerías, esta parte es al que se encarga de conectarse a Internet y descargar todos los archivos necesarios para el uso de esta librería  como la ejecución del programa, esta seria la estructura de como se compila en aplicación en  android studio.


post1_5

Conclusión

cosas como el diseño xml y el  brindar una estructura bien definida para el desarrollo son lo que hacen de este un entorno muy poderoso para el desarrollo de aplicaciones móviles, y a esto sumarle la gran documentación que nos brida google sobre toda esta temática, que os da herramientas a un simple click,y nos explica la manera correcta de usarlas.

Haciendo el juego del ahorcado en C++

El ahorcado, un juego en donde el participante o jugador cuenta con un límite de intentos para adivinar una palabra oculta letra por letra antes. Un juego sencillo el cual el hoy programaremos en lenguaje C++. En este caso, programaremos el juego tal de que cuente con varias categorías de palabras las cuales serán: Software, Hadware, OS (Operative Systems - Sistemas Operativos)

Para comenzar el programa, añadimos las librerías que usaremos, hacemos uso del "namespace std", declaramos las funciones que usaremos ( y que explicaré cada una mas adelante), declaramos un par de vectores globales en donde almacenaremos las palabras a usar y creamos el main:
#include <iostream>
#include <vector>
#include <ctime>
#include <windows.h>

string software[] = {"teamspeak","nikto","telegram","megasync","maltego","kate","armitage"};
string hardware[] = {"beeusb","yagui","jtagulator","mouse","usbkiller","harddrive","headset"};
string os[] = {"freebsd","linux","macos","winbugs","openbsd","unix","solaris"};

using namespace std;

int intro();
int juego(int opt);
string words(int opt);
void gotoxy(int x, int y);

int main(void){
 juego(intro());
 cout<<"\n\n\n\n\n";
}
En este main solamente implementamos la función juego(), a la cual se le pasa un parámetro que será definido por la función intro(). En el caso de la función intro() solamente implementaremos un menú en donde el jugador elegirá la categoría a jugar:
int intro(){
 char aux;
 int opt;

 do{
  system("cls");
  cout<<"\n\t******* Menu principal *******";
  cout<<"\n\t[1]   Software\n\t[2]   Hardware\n\t[3]   Sistemas Operativos\n\t[4]   Salir\n\t>>";
  cin>>aux;
 } while (aux < 49 || aux > 52);
 switch(aux){
  case 49: opt = 1; break;
  case 50: opt = 2; break;
  case 51: opt = 3; break;
  case 52: opt = 4; break;
 }
 cout<<opt;
 return opt;
}
El do - while() implementado no hace más que asegurarse de que la opción a elegida por el usuario no sea una distinta a las disponibles, y la variable opt lo que hace es retornar un valor entero teniendo en cuenta la opción elegida. [stextbox id="info" color="000000"]Nota: La variable aux evaluada es de tipo char, por lo cual hacemos uso del valor ASCII de los números al momento de la comprobación.[/stextbox] La función words() es la que se encargará de decidir cual palabra es la que usaremos para jugar, y contiene lo siguiente:
string words(int opt){
 int rword;
 srand(time(NULL));
 rword = 1+rand()%(8-1);
 switch (opt){
  case 1 : return software[rword-1];   
  case 2 : return hardware[rword-1];  
  case 3 : return os[rword-1];       
 }  
}
Crearemos una variable que almacenará un número aleatorio del 1 al 7 y luego teniendo en cuenta la opción elegida en la función intro(), usamos un switch-case para retornar una de las palabras almacenadas en los vectores de palabras que declaramos arriba. Ahora, la más grande y más importante: La función juego(). Esta función es la que se encargará de hacer todo el algoritmo requerido para que el juego sea funcional:
int juego(int opt){
  
  int turn = 6;//Cantidad de errores permitidos
  string used; //Almacena la palabra a usar
  char letra; //Aquí almacenamos la letra ingresada por el jugador
  string cat; //Almacenaremos el nombre de la categoría elegida
  int old=0; //Solo un pequeño auxiliar
  used = words(opt); //Rellenamos la variable con lo retornado por la función words()
  string count = ""; //Un auxiliar
  int total = used.size(); //Guardamos en esta variable el numero de caracteres que tiene la palabra a usar.
  int my_accurate = 0; //Es un auxiliar usado para llevar la cuenta de los aciertos hechos
  switch(opt){
   case 1: cat="Software";break; //En este switch lo que haremos será guardar el nombre de la
   case 2: cat="Hardware";break; //categoría elegida en la variable cat
   case 3: cat="   os   ";break;
  }
  //Se rellena el auxiliar count con espacios en blanco o "_ " teniendo en cuenta la cantidad de letras que hay
  for(int i=0; i != used.size(); i++){
   count+="_ ";
  }
  //Se hace un dibujito bonito (esto es sólo estética, no es necesario explicarlo)
  system("cls");
  cout<<"\n\n\t*******"<<cat<<"*******\n\tIntentos["<<turn<<"]";
  cout<<"\n\n\tPalabra: "<<count<<endl;
  gotoxy(11,5);cout<<"\n\n\t>> ";
  
  gotoxy(6,1);cout<<"**************************************************************";
  gotoxy(6,8);cout<<"**************************************************************";     
  for(int i=1;i<=8;i++){
   gotoxy(6,i);cout<<"*";
   gotoxy(39,i);cout<<"*";
   gotoxy(67,i);cout<<"*";
  }
  gotoxy(40,2);cout<<"           (__)  Have you";
  gotoxy(40,3);cout<<"           (OO)  ";
  gotoxy(40,4);cout<<"   /--------\\/    mooed";
  gotoxy(40,5);cout<<"  / |       ||   ";
  gotoxy(40,6);cout<<" * / \\------/\\    today?";
  gotoxy(40,7);cout<<"   ~~~      ~~~  ";
  
  do {
   //Aquí se comienza a jugar, se le pide al usuario ingresar una letra
   do{
    gotoxy(11,7);cout<<" ";
    gotoxy(11,7);cin>>letra;
    
   }while( letra<97 || letra>122); //Código ascii de las letras EN MINISCULAS desde la a hasta la z
   //Evalua si la letra usada hace parte de la palabra con que se está jugando, en caso de que si se aumenta el auxiliar my_accurate
   //dependiendo de la cantidad de coincidencias
   for(int i=0;i<used.size();i++){
    if(used[i]==letra){
     gotoxy(((i*2)+1)+16,5);cout<<letra;
     my_accurate++;
     used[i] = ' ';                
    }
   }
   //Aqui solamente se va tapando la vaquita simulando el "ahogado"
   if(old == my_accurate){//Si old es igual a my_accurate quiere decir que no hubieron coincidencias en la palabra, lo que significa una oportunidad menos
       gotoxy(40,turn+1);cout<<"\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126\126";      
    turn--;
    
   }
   old = my_accurate; //se actualiza old para saber cuantos intentos se llevan y poder saber si hubieron coincidencias nuevas
   gotoxy(17,3);cout<<turn;
   //Si la cantidad de aciertos es igual a la cantidad de letras que tiene, ganas.
   if(my_accurate == total){
      gotoxy(8,12);cout<<"Congrats! you win :)";
      break;
   }
   
  }while(turn>0);
  //Si es diferente, pierdes
  if (my_accurate != total){
   gotoxy(8,12);cout<<"You lose :(";
  }
  
 if(opt==4){
  return 0;
 }      
}
Por último creamos la función gotoxy(), esta es una función que se encarga de posicionar en cualquier lugar de la pantalla de ejecución un elemento teniendo en cuenta las cordenadas X y Y de la de donde se desea posicionar.
void gotoxy(int x, int y){
 HANDLE hcon;
 hcon = GetStdHandle(STD_OUTPUT_HANDLE);
 COORD dwPos;
 dwPos.X = x;
 dwPos.Y = y;
 SetConsoleCursorPosition(hcon,dwPos);
}
Y eso es todo, un juego del Ahorcado que cuenta con 3 categorías de juego diferente y haciendo uso de la función gotoxy() para darle un poco de animación. Código fuente: Descargar IDE usado: Dev C++

viernes, 11 de noviembre de 2016

Crear Web Service RESTFul con PHP [API] [Básico]

Un servicio web (en inglés, Web Service o Web services) es una tecnología que utiliza un conjunto de protocolos y estándares que sirven para intercambiar datos entre aplicaciones. Distintas aplicaciones de software desarrolladas en lenguajes de programación diferentes, y ejecutadas sobre cualquier plataforma, pueden utilizar los Web Services para intercambiar datos en redes de ordenadores como Internet. La interoperabilidad se consigue mediante la adopción de estándares abiertos.




[caption id="" align="aligncenter" width="424"]Web Service Funcionamiento básico de un Web Service[/caption]

Como se puede apreciar en la imagen, un Web Service está compuesto por dos partes:


Un servidor: En este está almacenada la información que va a ser consumida y toda la lógica del servicio.


Los clientes: Que son los encargados de consumir dicho servicio.


Básicamente el cliente envía una petición al servidor a través de la red y el servidor le envía el resultado, sencillo, ¿No?



Características de los Web Services


Algunas de las características de los Web Services son:




  • Pueden ser consumidas desde cualquier tipo de aplicación sin importar el lenguaje

  • Permiten el fácil acceso a su contenido y funcionamiento

  • Está orientado a la web

  • Basados en Mensajes

  • Puede ser localizado dinámicamente

  • Puede ser ensamblados o agregados dinámicamente

  • Accesible a través de internet

  • Basados en estándares de la industria

  • Fácil Integración

  • Escalabilidad

  • Permiten que servicios y software de diferentes compañías ubicadas en diferentes lugares geográficos puedan ser combinados fácilmente para proveer servicios integrados.


Inconvenientes de los Web Services



  • Para realizar transacciones no pueden compararse en su grado de desarrollo con los estándares abiertos de computación distribuida como CORBA (Common Object Request Broker Architecture).

  • Su rendimiento es bajo si se compara con otros modelos de computación distribuida, tales como RMI (Remote Method Invocation), CORBA o DCOM (Distributed Component Object Model). Es uno de los inconvenientes derivados de adoptar un formato basado en texto. Y es que entre los objetivos de XML no se encuentra la concisión ni la eficacia de procesamiento.

  • Al apoyarse en HTTP, pueden esquivar medidas de seguridad basadas en firewall cuyas reglas tratan de bloquear o auditar la comunicación entre programas a ambos lados de la barrera.


Estándares empleados (Tipos de Web Services)


Existen varios tipos de Web Services, varios de ellos son:




  • WSDL (Web Services Description Language)

  • UDDI (Universal Description, Discovery and Integration)

  • SOAP (Simple Object Access Protocol) o XML-RPC (XML Remote Procedure Call)

  • REST (Representational State Transfer)


Es importante resaltar que los dos últimos son los que están “en apogeo” debido a que han venido evolucionando a través del tiempo adaptándose a las demandas actuales.



[stextbox id="info" bgcolor="eeeeee" cbgcolor="eeeeee" bgcolorto="eeeeee" cbgcolorto="eeeeee"]Para saber más a cerca de estos dos últimos tipos de Web Service los invito a leer su Bench en el siguiente enlace: SOAP vs REST/RESTful[/stextbox]


 Crear Web Service


Para seguir este tutorial es muy recomendable tener conocimientos básicos en PHP y la estructura de JSON porque la finalidad de esta guía no es enseñar PHP sino aprender a crear un Web Service con PHP, aunque, si conoce otro lenguaje de programación es muy fácil intuir el funcionamiento del código.

En este tutorial aprenderemos a crear un Web Service RESTful sencillo, para la creación de nuestro Web Service requerimos usar diversas tecnologías, las que usaremos en este tutorial serán las siguientes:




  • PHP (Versión 7.0.8)

  • MySQL (Versión 5.7.16)

  • PHP ActiveRecord (Versión 1.xx)


El componente PHP ActiveRecord, es una "ORM library" de código abierto basado en el patrón ActiveRecord el cual facilitará la conexión entre PHP y nuestro motor de base de datos, esta librería es muy potente y no sólo se puede integrar con MySQL, sino que también se puede usar con otros motores de base de datos como PostgreSQL, SQLite y OCI (Oracle Call Interface).


Para descargarlo pueden hacerlo desde su página oficial, pero, la versión posteada ahí está desatendida, por lo cual es recomendable que se descargue la versión que se tiene en GitHub.


Esta librería es muy fácil de utilizar, es recomendable leer toda la información que está alojada en la Wiki oficial, es muy poca pero muy precisa y clara.


Para este ejemplo crearemos un sistema de deberes, que consiste básicamente en guardar Usuarios y a estos usuarios gestionarle Deberes.


Para organizarnos mejor haremos nuestra Check List:




  1. Crear nuestra base de datos y montarla

  2. Instalar PHP AR

  3. Configurar y probar PHP AR

  4. Crear los modelos o entidades de nuestra base de datos en PHP y probarlos

  5. Crear los controladores de cada modelo

  6. Probar cada modelo


1- Crear nuestra base de datos y montarla


La base de datos que usare será la siguiente:

[caption id="" align="alignnone" width="419"]Diagrama Diagrama de la base de datos[/caption]

La relación indica que, un usuario puede tener muchos deberes y (EN ESTE CASO) un deber sólo lo puede tenerlo un usuario, como vemos no verificamos que ningún campo sea único y bien se podría hacer normalización pero para no complicar el ejemplo mejor no se aplica tanto protocolo porque debemos recordar que es un ejemplo básico.


Ya teniendo nuestro diagrama creado, el SQL queda de la siguiente manera:

[spoiler title='SQL del ejemplo' style='default' collapse_link='true']
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

CREATE SCHEMA IF NOT EXISTS `programeet_ejemplo_web_service` DEFAULT CHARACTER SET utf8 ;
USE `programeet_ejemplo_web_service` ;

CREATE TABLE IF NOT EXISTS `programeet_ejemplo_web_service`.`Usuarios` (
`id` INT NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(45) NOT NULL,
`telefono` VARCHAR(45) NOT NULL,
`email` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id`))
ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `programeet_ejemplo_web_service`.`Deberes` (
`id` INT NOT NULL AUTO_INCREMENT,
`deber` VARCHAR(45) NOT NULL,
`Usuarios_id` INT NOT NULL,
PRIMARY KEY (`id`),
INDEX `fk_Deberes_Usuarios_idx` (`Usuarios_id` ASC),
CONSTRAINT `fk_Deberes_Usuarios`
FOREIGN KEY (`Usuarios_id`)
REFERENCES `programeet_ejemplo_web_service`.`Usuarios` (`id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

[/spoiler]

Para montar la base de datos usaré MySQL Workbench siguiendo la siguiente ruta:

[caption id="" align="alignnone" width="903"]Mount DB Montar base de datos desde MySQL Workbench[/caption]

Luego de montar la base de datos nos quedará de la siguiente manera:

[caption id="" align="alignnone" width="333"]Mounted DB Base de datos montada con las dos tablas[/caption]

[stextbox id="info" bgcolor="eeeeee" cbgcolor="eeeeee" bgcolorto="eeeeee" cbgcolorto="eeeeee"]NOTA: De aquí en adelante esta nota es válida, en caso de usar Ubuntu Server es recomendable darle permisos a los archivos para que puedan ejecutar sin problemas, en mi caso como es para pruebas y lo tengo local, le asigné 777 a todos para evitar cualquier inconveniente.[/stextbox]

2 -Instalar PHP AR


Al descargarnos la librería de GitHub, la extraemos y copiamos los archivos relevantes a la librería que son:




  • ActiveRecord.php

  • lib [carpeta]


Nos vamos a nuestro servidor web (puede ser con Appserv, Xampp, Wamp o cualquier otro, que en mi caso uso Ubuntu Server)  y creamos una carpeta con el nombre que queramos, yo le pondré "php-activerecord" y agregaré la librería, la ruta de la librería es la siguiente:




[caption id="" align="alignnone" width="196"]Lib path Ruta de la librería[/caption]

3- Configurar y probar PHP AR


Para la configuración de PHP AR haremos un script que va a servir para iniciar la librería en todos nuestros controladores y lo pondremos en la ruta padre de nuestra librería aunque puede ponerse en cualquier otro lado:

[caption id="" align="alignnone" width="161"]autoload path Ruta de autoload.php[/caption]

El contenido del script es el siguiente:

[spoiler title='Contenido de autoload.php' style='default' collapse_link='true']
<?php
// Importamos nuestra librería poniendo la ruta del ActiveRecord.php
require_once 'php-activerecord/ActiveRecord.php';

ActiveRecord\Config::initialize(function($cfg){
$cfg->set_model_directory('model');
$cfg->set_connections(array(
'development' =>
'mysql://root:programeet@localhost/programeet_ejemplo_web_service'));
});
// Configuramos la ruta de la carpeta donde pondremos nuestros modelos
// en este caso la carpeta se llama 'model' y está en el mismo directorio que este script.
// Configuramos nuestra conexión a la base de datos:
// Usuario = root
// Password = programeet
// Servidor = localhost
// Nombre de la base de datos = programeet_ejemplo_web_service

[/spoiler]

Nuestro Web Service ahora tendrá la siguiente estructura:

[caption id="" align="alignnone" width="169"]path service Directorio del Web Service[/caption]

Una vez configurada nuestra librería procedemos a probarla:

[caption id="" align="alignnone" width="386"]testing lib Probando la librería[/caption]

Como pudimos notar no hubo ningún error, lo que quiere decir que nos conectamos correctamente a la base de datos.



4-Crear los modelos o entidades de nuestra base de datos en PHP y probarlos


Dentro de la carpeta "model" crearemos un script por cada tabla en la base de datos y tendrá la siguiente estructura:
<?php
class NOMBRE_DE_LA_CLASE extends ActiveRecord\Model
{
public static $table_name = 'NOMBRE_DE_LA_TABLA';
public static $primary_key = 'LLAVE_PRIMARIA';
}

Notese que la clase debe heredar de "ActiveRecord\Model", conociendo la estructura de todos los modelos así quedaron los del ejemplo:



// Deber.php
<?php
class Deber extends ActiveRecord\Model
{
public static $table_name = 'Deberes';
public static $primary_key = 'id';
}

// Usuario.php
<?php
class Usuario extends ActiveRecord\Model
{
public static $table_name = 'Usuarios';
public static $primary_key = 'id';
}

Una vez creados los modelos procedemos a probarlos, dentro del script "autoload.php" haremos las pruebas, no es necesario que sea ese, puede ser en otro pero se debe importar éste para iniciar la librería y poder usarla, haremos un crud sencillo por cada modelo para probar que funciona todo correctamente.


 [stextbox id="warning"]NOTA: Para poder hacer las pruebas deben tener TODOS los modelos creados.[/stextbox]

Procedemos a probar la entidad Usuario:

[spoiler title='Código de prueba para la entidad Usuario' style='default' collapse_link='true']
<?php
require_once 'php-activerecord/ActiveRecord.php';

ActiveRecord\Config::initialize(function($cfg){
$cfg->set_model_directory('model');
$cfg->set_connections(array(
'development' =>
'mysql://root:programeet@localhost/programeet_ejemplo_web_service'));
});

echo '<pre>';
//Create
Usuario::create(array(
'nombre' => 'Dro',
'telefono' => '5555',
'email' => 'programeet@web_service.ejemplo'
));
//Read
$u = Usuario::find_by_email('programeet@web_service.ejemplo');
print_r($u);
echo '<br>';

//Update
$u->telefono = "666";
$u->save();

$u2 = Usuario::find_by_telefono('666');
print_r($u2);
echo '<br>';

//Delete
$u2->delete();

[/spoiler]

Al ejecutar el script los print_r($u) y print_r($u2) nos arroja lo siguiente:

[spoiler title='Resultado' style='default' collapse_link='true']
Usuario Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[id] => 1
[nombre] => Dro
[telefono] => 5555
[email] => programeet@web_service.ejemplo
)

[__dirty:ActiveRecord\Model:private] => Array
(
)

[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)

[__new_record:ActiveRecord\Model:private] =>
)

Usuario Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[id] => 1
[nombre] => Dro
[telefono] => 666
[email] => programeet@web_service.ejemplo
)

[__dirty:ActiveRecord\Model:private] => Array
(
)

[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)

[__new_record:ActiveRecord\Model:private] =>
)


[/spoiler]

Con esto confirmamos que la identidad o modelo "Usuario" funciona perfectamente, procedemos a probar la entidad Deber:

Pero para poder probar la entidad Deber, debe existir por lo menos un usuario para que se cumpla la relación y el script queda de la siguiente manera:

[spoiler title='Código de prueba para la entidad Deber' style='default' collapse_link='true']
<?php
require_once 'php-activerecord/ActiveRecord.php';

ActiveRecord\Config::initialize(function($cfg){
$cfg->set_model_directory('model');
$cfg->set_connections(array(
'development' =>
'mysql://root:programeet@localhost/programeet_ejemplo_web_service'));
});

echo '<pre>';

// Creamos un usuario
$u = Usuario::create(array(
'nombre' => 'Dro',
'telefono' => '5555',
'email' => 'programeet@web_service.ejemplo'
));

//Create
Deber::create(array(
'deber' => 'Terminar la guia',
'Usuarios_id' => $u->id
));
//Read
$d = Deber::find_by_deber('Terminar la guia');
print_r($d);
echo '<br>';

//Update
$d->deber = "Crear guia intermedia";
$d->save();

$d2 = Deber::find_by_deber('Crear guia intermedia');
print_r($d2);
echo '<br>';

//Delete
$d2->delete();

[/spoiler]

Al ejecutar el script los print_r($d) y print_r($d2) nos arroja lo siguiente:

[spoiler title='Resultado' style='default' collapse_link='true']
Deber Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[id] => 1
[deber] => Terminar la guia
[usuarios_id] => 2
)

[__dirty:ActiveRecord\Model:private] => Array
(
)

[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)

[__new_record:ActiveRecord\Model:private] =>
)

Deber Object
(
[errors] =>
[attributes:ActiveRecord\Model:private] => Array
(
[id] => 1
[deber] => Crear guia intermedia
[usuarios_id] => 2
)

[__dirty:ActiveRecord\Model:private] => Array
(
)

[__readonly:ActiveRecord\Model:private] =>
[__relationships:ActiveRecord\Model:private] => Array
(
)

[__new_record:ActiveRecord\Model:private] =>
)


[/spoiler]

Y en la tabla usuario tenemos:

[caption id="" align="alignnone" width="887"]users list Tabla Usuarios luego de probar la entidad Deber[/caption]

Con esto comprobamos que las dos entidades funcionan perfectamente.

5-Crear los controladores de cada modelo


Ahora creamos una carpeta llamada "controladores" o el nombre que quieran, pero es mejor llamar las carpetas y ficheros por lo que son, el directorio del servicio nos quedará de la siguiente manera:




[caption id="" align="alignnone" width="186"]service path Directorio del Web Service[/caption]

Dentro de esa carpeta vamos a crear dos script por cada entidad:

  1. ControllerEntidad.php: En este script va el crud de la identidad

  2. Entidad.php: Este script será el que reciba las peticiones HTTP y direccionarlas a cada método del controlador


[caption id="" align="alignnone" width="1098"]http description Peticiones HTTP y asociación con el CRUD de la entidad[/caption]

En este ejemplo sólo trabajaremos con la petición GET siendo este un tutorial de Web Service Básico.

[stextbox id="warning"]ADVERTENCIA: Con este ejemplo no se puede sacar un Web Service a producción porque no tiene medidas de seguridad y no aplica todas las peticiones HTTP[/stextbox]

Para el retorno de datos del Web Service vamos a usar el formato JSON y no XML.

[stextbox id="info" bgcolor="eeeeee" cbgcolor="eeeeee" bgcolorto="eeeeee" cbgcolorto="eeeeee"] NOTA: Para saber más sobre estos dos formatos de texto los invitamos a leer por qué elegimos JSON sobre XML en el Bench XML vs JSON[/stextbox]

Teniendo en cuenta esto creamos los respectivos controladores:

[spoiler title='Controlador Usuario' style='default' collapse_link='true']
<?php
require_once '../autoload.php';
include '../model/Usuario.php';

class ControllerUsuarios{

public function Create($name, $telefono, $email){
$u = Usuario::create(array(
'nombre' => "$name",
'telefono' => "$telefono",
'email' => "$email"
));
return null;
}

public function Read($name){
$u = Usuario::find_by_nombre($name);
return is_null($u) ? null : $u;
}

public function Update($name, $email){
$u = Usuario::find_by_nombre($name);
if(is_null($u)) return false;
$u->email = $email;
$u->save();
return true;
}

public function Delete($name){
$u = Usuario::find_by_nombre($name);
if(is_null($u)) return false;
$u->delete();
return true;
}
}

[/spoiler]

[spoiler title='Manejador de peticiones' style='default' collapse_link='true']
<?php
//print_r($_GET);
require 'ControllerUsuarios.php';
$crud = isset($_GET['action']) ? $_GET['action'] : 'empty';
switch ($crud) {
case 'create':
if (isset($_GET['name']) && isset($_GET['telefono']) && isset($_GET['email'])) {
$res = ControllerUsuarios::Create($_GET['name'],$_GET['telefono'],$_GET['email']);
echo json_encode(array(
'status' => '0',
'msg' => 'Usuario creado satisfactoriamente.'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
case 'read':
if (isset($_GET['name'])) {
$res = ControllerUsuarios::Read($_GET['name']);
//print_r($res);
if($res) echo json_encode(array(
'status' => '0',
'msg' => $res->to_json()
));
else echo json_encode(array(
'status' => '1',
'msg' => 'No se encuentra el usuario con ese nombre.'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
case 'update':
if (isset($_GET['name']) && isset($_GET['email'])) {
$res = ControllerUsuarios::Update($_GET['name'],$_GET['email']);
//print_r($res);
if($res) echo json_encode(array(
'status' => '0',
'msg' => 'Usuario actualizado correctamente.'
));
else echo json_encode(array(
'status' => '1',
'msg' => 'No se encuentra el usuario a modificar.'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
case 'delete':
if (isset($_GET['name'])) {
$res = ControllerUsuarios::Delete($_GET['name']);
//print_r($res);
if($res) echo json_encode(array(
'status' => '0',
'msg' => 'Usuario eliminado satisfactoriamente'
));
else echo json_encode(array(
'status' => '1',
'msg' => 'No se encuentra el usuario con ese nombre.'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
default:
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar una opcion valida.'
));
break;
}
?>

[/spoiler]

[spoiler title='Controlador Deberes' style='default' collapse_link='true']
<?php
require_once '../autoload.php';
include '../model/Deber.php';

class ControllerDeberes{

public function Create($deber, $usuarios_id){
$u = Deber::create(array(
'deber' => "$deber",
'Usuarios_id' => "$usuarios_id"
));
return null;
}

public function Read($usuarios_id){
$u = Deber::find_all_by_Usuarios_id($usuarios_id);
$res = array();
foreach ($u as $d) $res[] = $d->to_json();
return is_null($u) ? null : $res;
}

public function Update($deber, $deber_new, $usuarios_id){
$check = Deber::find_by_deber_and_Usuarios_id("$deber", $usuarios_id);
if(is_null($check)) return false;
$check->deber = $deber_new;
$check->save();
return true;
}

public function Delete($deber, $usuarios_id){
$u = Deber::find_by_deber_and_Usuarios_id($deber, $usuarios_id);
if(is_null($u)) return false;
$u->delete();
return true;
}
}

[/spoiler]

[spoiler title='Manejador de peticiones' style='default' collapse_link='true']
<?php
//print_r($_GET);
require 'ControllerDeberes.php';
$crud = isset($_GET['action']) ? $_GET['action'] : 'empty';
switch ($crud) {
case 'create':
if (isset($_GET['deber']) && isset($_GET['usuarios_id'])) {
$res = ControllerDeberes::Create($_GET['deber'], $_GET['usuarios_id']);
echo json_encode(array(
'status' => '0',
'msg' => 'Deber agregado satisfactoriamente'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
case 'read':
if (isset($_GET['usuarios_id'])) {
$res = ControllerDeberes::Read($_GET['usuarios_id']);
//print_r($res);
if($res) echo json_encode(array(
'status' => '0',
'msg' => $res
));
else echo json_encode(array(
'status' => '1',
'msg' => 'No se encuentran los deberes de ese usuario.'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
case 'update':
if (isset($_GET['deber']) && isset($_GET['deber_new']) && isset($_GET['usuarios_id'])) {
$res = ControllerDeberes::Update($_GET['deber'],$_GET['deber_new'],$_GET['usuarios_id']);
//print_r($res);
if($res) echo json_encode(array(
'status' => '0',
'msg' => 'Deber actualizada correctamente.'
));
else echo json_encode(array(
'status' => '1',
'msg' => 'No se encuentra el deber a modificar.'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
case 'delete':
if (isset($_GET['deber']) && isset($_GET['usuarios_id'])) {
$res = ControllerDeberes::Delete($_GET['deber'], $_GET['usuarios_id']);
if($res) echo json_encode(array(
'status' => '0',
'msg' => 'Deber eliminado satisfactoriamente'
));
else echo json_encode(array(
'status' => '1',
'msg' => 'No se encuentra el deber.'
));
}else{
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar todos los parámetros.'
));
}
break;
default:
echo json_encode(array(
'status' => '1',
'msg' => 'Debe especificar una opcion valida.'
));
break;
}
?>

[/spoiler]

Como pudimos notar en el script ControllerEntidad.php son importados dos scripts, que son el autoload y el modelo de cada entidad, esto quiere decir que para poder hacer uso de la librería de PHP AR hay que ejecutar siempre el autoload y los modelos usados dentro del controlador, y como era de esperarse en el manejador se incluye el controlador para poder llamar sus métodos.

6-Probar cada modelo


Al final nuestro Web Service deberá tener la siguiente estructura:

[caption id="" align="alignnone" width="472"]service path Web Service terminado[/caption]

Ahora probemos todas las funciones de nuestro Web Service:

Usuarios


[spoiler title='Pruebas' style='default' collapse_link='true']

  • CREATE:


[ip_servidor]/controladores/Usuarios.php?action=create&name=Programeet&telefono=555&email=programeet@web_service.ejemplo


  • RESULT:


{"status":"0","msg":"Usuario creado satisfactoriamente."}


  • READ:


[ip_serv]/controladores/Usuarios.php?action=read&name=Programeet


  • RESULT:


{"status":"0","msg":"{\"id\":4,\"nombre\":\"Programeet\",\"telefono\":\"555\",\"email\":\"programeet@web_service.ejemplo\"}"}


  • UPDATE:


[ip_serv]/controladores/Usuarios.php?action=update&name=Programeet&email=dro_programeet@web_service.ejemplo


  • RESULT:


{"status":"0","msg":"Usuario actualizado correctamente."}


  • DELETE:


[ip_serv]/controladores/Usuarios.php?action=delete&name=Programeet


  • RESULT:


{"status":"0","msg":"Usuario eliminado satisfactoriamente"}

[/spoiler]

Deberes


[spoiler title='Pruebas' style='default' collapse_link='true']

Para probar esta identidad creamos un nuevo usuario y tiene un id=5
[ip_servidor]/controladores/Usuarios.php?action=create&name=Programeet&telefono=555&email=programeet@web_service.ejemplo


  • CREATE:


[ip_servidor]/controladores/Deberes.php?action=create&deber=Terminar%20la%20guia&usuarios_id=5


  • RESULT:


{"status":"0","msg":"Deber agregado satisfactoriamente"}


  • READ:


[ip_serv]/controladores/Deberes.php?action=read&deber=s&usuarios_id=5


  • RESULT:


{"status":"0","msg":["{\"id\":5,\"deber\":\"Terminar la guia\",\"usuarios_id\":5}"]}


  • UPDATE:


[ip_serv]/controladores/Deberes.php?action=update&deber=Terminar%20la%20guia&deber_new=Comer&usuarios_id=5


  • RESULT:


{"status":"0","msg":"Deber actualizada correctamente."}


  • DELETE:


[ip_serv]/controladores/Deberes.php?action=delete&deber=Comer&usuarios_id=5


  • RESULT:


{"status":"0","msg":"Deber eliminado satisfactoriamente"}

[/spoiler]

Esas pruebas son hechas en escenarios ideales en donde todos los parámetros enviados están bien, Probar que está bien validado depende de ustedes.

Bueno, eso fue todo por esta guía sencilla sobre cómo crear un Web Service básico conectado a cualquier motor de base de datos soportada por PHP AR.

Enlace de descarga del código fuente: MEGA

Herramientas utilizadas en el tutorial