Diferència entre revisions de la pàgina «Serveis Web i Mashups a PHP»
(150 revisions intermèdies per 2 usuaris que no es mostren) | |||
Línia 1: | Línia 1: | ||
− | =Què són els Serveis Web?= | + | <!-- =Què són els Serveis Web?= |
Els '''serveis web són aplicacions client i servidor''' que es comuniquen sobre (WWW) Protocol de transferència d'hipertext de la World Wide Web (HTTP). Segons el descrit pel World Wide Web Consortium (W3C), serveis web '''proporcionen un mitjà estàndard d'interoperabilitat entre aplicacions de programari que s'executen en una varietat de plataformes i marcs'''. | Els '''serveis web són aplicacions client i servidor''' que es comuniquen sobre (WWW) Protocol de transferència d'hipertext de la World Wide Web (HTTP). Segons el descrit pel World Wide Web Consortium (W3C), serveis web '''proporcionen un mitjà estàndard d'interoperabilitat entre aplicacions de programari que s'executen en una varietat de plataformes i marcs'''. | ||
− | Els serveis web es caracteritzen per la seva gran interoperabilitat i extensibilitat, així com les seves descripcions processable per màquina, gràcies a la utilització de XML. Els serveis web es poden combinar d'una manera precisa per aconseguir operacions complexes. | + | Els serveis web es caracteritzen per la seva gran interoperabilitat i extensibilitat, així com les seves descripcions processable per màquina, gràcies a la utilització de XML. Els serveis web es poden combinar d'una manera precisa per aconseguir operacions complexes. |
=Tipus de Serveis Web= | =Tipus de Serveis Web= | ||
Línia 33: | Línia 33: | ||
Exemple: | Exemple: | ||
− | + | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
Existeixen dues maneres per accedir a un servei web: | Existeixen dues maneres per accedir a un servei web: | ||
*'''El proveïdor de serveis web coneix al client''':El proveïdor de serveis web proporcionarà el '''WSDL'' al client i el client podrà accedir als serveis web. | *'''El proveïdor de serveis web coneix al client''':El proveïdor de serveis web proporcionarà el '''WSDL'' al client i el client podrà accedir als serveis web. | ||
Línia 113: | Línia 55: | ||
</soap:Envelope> | </soap:Envelope> | ||
</source> | </source> | ||
− | Sembla només un altre arxiu XML però, el que fa que sigui un missatge SOAP és l'element ''root'' anomenat ''Envelope'' que té | + | Sembla només un altre arxiu XML però, el que fa que sigui un missatge SOAP és l'element ''root'' anomenat ''Envelope'' que té l'espai de noms soap a http://www.w3.org/2001/12/soap-envelope. L'atribut '''soap:encodingStyle''' determina el tipus de dades que s'utilitza en el fitxer per que SOAP no té una codificació per defecte. |
+ | |||
+ | L'element '''soap:Envelope''' és obligatori però l'elemenmt següent '''soap:Header''' és opcional i normalment conté informació rellevant a l'autenticació i la sessió. El protocol SOAP no ofereix autenticació però ofereix als desenvolupadors aquesta etiqueta per a incloure-ho. | ||
+ | |||
+ | El següent element es tracta de '''soap:Body''' que és obligatori. Conté el missatge RPC (Remote Procedure Call) on s'inclou els mètodes i si és un missatge de resposta, també el valor retornat pel mètode. L'etiqueta '''soap:Fault''' és opcional. Si està present al missatge conté els erros i el missatges dels errors. | ||
+ | |||
+ | Donem un cop d'ull a un missatge SOAP de petició: | ||
+ | <source lang="xml"> | ||
+ | <?xml version="1.0"?> | ||
+ | <soap:Envelope | ||
+ | xmlns:soap="http://www.w3.org/2001/12/soap-envelope" | ||
+ | soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> | ||
+ | <soap:Body xmlns:m="http://www.yourwebroot.com/stock"> | ||
+ | <m:GetStockPrice> | ||
+ | <m:StockName>IBM</m:StockName> | ||
+ | </m:GetStockPrice> | ||
+ | </soap:Body> | ||
+ | </soap:Envelope> | ||
+ | </source> | ||
+ | |||
+ | El missatge anterior és una petició per obtenir el preu d'estoc d'una empresa en concret. Dintre de l'etiqueta '''soap:Body''' veuràs l'element ''GetStockPrice'' que No correspon a SOAP, si no, que aquest element fa referència a un mètode particular de l'aplicació de servidor que es cridarà al rebre aquest missatge. L'element ''StockName'' també és específic de l'aplicació servidora i correspon a un paràmetre de la funció anterior. | ||
+ | |||
+ | El missatge de resposta és molt semblant: | ||
+ | <source lang="xml"> | ||
+ | <?xml version="1.0"?> | ||
+ | <soap:Envelope | ||
+ | xmlns:soap="http://www.w3.org/2001/12/soap-envelope" | ||
+ | soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> | ||
+ | <soap:Body xmlns:m="http://www.yourwebroot.com/stock"> | ||
+ | <m:GetStockPriceResponse> | ||
+ | <m:Price>183.08</m:Price> | ||
+ | </m:GetStockPriceResponse> | ||
+ | </soap:Body> | ||
+ | </soap:Envelope> | ||
+ | </source> | ||
+ | |||
+ | Dintre de l'element '''soap:Body''' veuràs l'element ''GetStockPriceRespomse'' que conté l'element ''Price'' amb la dada de resposta. Ambdós elements son específics de l'aplicació de servidor. | ||
+ | |||
+ | ==Client Java Swing d'un servei Web == | ||
+ | Es farà una implementació d'un servei web client utilitzant JAVA SWING. Segueix aquests passos: | ||
+ | *Crea un nou projecte de tipus Java Application. | ||
+ | |||
+ | [[Fitxer:wsclient-java1.png|500px]] | ||
+ | |||
+ | *Crea un formulari SWING per afegir els camps elements necessaris (buttons, labels, text fields, etc) | ||
+ | [[Fitxer:wsclient-java2.png|500px]] | ||
+ | |||
+ | [[Fitxer:wsclient-java3.png|500px]] | ||
+ | |||
+ | *Una vegada tinguis el formulari, afegeix la funcionalitat de web-service client | ||
+ | [[Fitxer:wsclient-java4.png|500px]] | ||
+ | |||
+ | *Omple el camp wsdl a l'hora de configurar el client. Deixa en blanc el camp package: | ||
+ | [[Fitxer:wsclient-java5.png|500px]] | ||
+ | |||
+ | *Una vegada generat, ja es pot utilitzar el client del WS des del formulari Swing. Per tal d'utilitzar-lo, genera el codi necessari insertant-lo des del netbeans: | ||
+ | [[Fitxer:wsclient-java6.png|500px]] | ||
+ | |||
+ | [[Fitxer:wsclient-java7.png|500px]] | ||
+ | |||
+ | [[Fitxer:wsclient-java8.png|300px]] | ||
+ | |||
+ | *Podem veure el codi generat. Él nom de la funció generada correspon al nom del servei web: | ||
+ | [[Fitxer:wsclient-java9.png|700px]] | ||
+ | |||
+ | *Ja podem utilitzar la crida al servei web associant-la al click d'un botó. El resultat de la execució del servei web es mostrarà en un Dialog. | ||
+ | [[Fitxer:wsclient-java10.png|700px]] | ||
+ | |||
+ | *Resultat de l'execució: | ||
+ | [[Fitxer:wsclient-java11.png|300px]] | ||
+ | |||
+ | [[Fitxer:wsclient-java12.png|300px]] | ||
+ | |||
+ | https://www.youtube.com/watch?v=BeY1bQzMeAk | ||
+ | |||
+ | ===Accedir a un servei Web des de un client php === | ||
+ | Per accedir a un servei web, és molt fàcil, només s'ha de donar el WSDL a la classe '''SoapClient''' de PHP. | ||
+ | L'objecte generat conté tots els serveis webs que estan implementat en el WSDL. | ||
+ | Per passar els paràmetres, es fa servir un Array associatiu on la clau és el nom del paràmetre configurat en el WS i el valor és el que es vol enviar al servei web. | ||
+ | Exemple: | ||
+ | <source lang="php"> | ||
+ | |||
+ | $client = new SoapClient("http://192.168.56.1:8084/webServiceProject/Hola?wsdl"); | ||
+ | |||
+ | $result = $client->hello(array("name"=>"alex")); | ||
+ | |||
+ | echo $result->return; | ||
+ | |||
+ | </source> | ||
+ | |||
+ | Per accedir al resultat del WebService, hem de veure en el WSDL el nom del camp corresponent al resultat del WS i així podrem accedir al valor. | ||
+ | |||
+ | Es pot crear un formulari amb php i en el controlador, fer la crida al servei Web corresponent. | ||
+ | |||
+ | Resultat execució codi anterior (Es recorda que es necessari una màquina virtual amb php + apache2): | ||
+ | |||
+ | [[Fitxer:wsclient-php1.png|500px]] | ||
+ | |||
+ | === NuSOAP server === | ||
+ | És molt senzill crear un servei web utilitzant la llibreria NuSOAP de PHP. Pots descarregar-la des d'aquest [https://github.com/pwnlabs/nusoap | enllaç]. Baixa't-ho i descomprimeix-lo en el directori principal de l'aplicació. Per utilitzar-ho només has d'incloure la llibreria '''nusoap.php''' en el codi de l'aplicació. | ||
+ | |||
+ | Veiem un exemple d'utilització de la llibreria '''nusoap''' per crear un servei web. | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | require_once "nusoap.php"; | ||
+ | |||
+ | function getProd($category) { | ||
+ | if ($category == "books") { | ||
+ | return join(",", array( | ||
+ | "The WordPress Anthology", | ||
+ | "PHP Master: Write Cutting Edge Code", | ||
+ | "Build Your Own Website the Right Way")); | ||
+ | } | ||
+ | else { | ||
+ | return "No products listed under that category"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $server = new soap_server(); | ||
+ | $server->register("getProd"); | ||
+ | $server->service($HTTP_RAW_POST_DATA); | ||
+ | </source> | ||
+ | |||
+ | Primer s'inclou el fitxer '''nusoap.php'' per poder accedir a la llibreria NuSOAP. Després es defineix la funció '''getProd()''' i s'instancia un objecte de la classe ''soap_server''. Immediatament després s'utilitza el mètode '''register'' per afegir la funció ''getProd'' al servidor sopa i poder accedir a ella des de un client. És a dir, convertim la funció ''getProd'' en un servei web. | ||
+ | |||
+ | Segurament, en un escenari real, la funció ''getProd'' hauria de cercar en una Base de Dades la informació que s'ha d'enviar a l'usuari. Ara mateix, no volem complicar el codi en coses externes a SOAP. | ||
+ | |||
+ | Es poden registrar funcions addicionals en el servidor per per donar més funcionalitats a l'aplicació. El procés seria idèntic del descrit anteriorment. | ||
+ | |||
+ | === NuSOAP Client === | ||
+ | |||
+ | Crearem una pàgina php que utilitzarà el servei web anterior: | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | require_once "nusoap.php"; | ||
+ | $client = new nusoap_client("http://localhost/nusoap/productlist.php"); | ||
+ | |||
+ | $error = $client->getError(); | ||
+ | if ($error) { | ||
+ | echo "<h2>Constructor error</h2><pre>" . $error . "</pre>"; | ||
+ | } | ||
+ | |||
+ | $result = $client->call("getProd", array("category" => "books")); | ||
+ | |||
+ | if ($client->fault) { | ||
+ | echo "<h2>Fault</h2><pre>"; | ||
+ | print_r($result); | ||
+ | echo "</pre>"; | ||
+ | } | ||
+ | else { | ||
+ | $error = $client->getError(); | ||
+ | if ($error) { | ||
+ | echo "<h2>Error</h2><pre>" . $error . "</pre>"; | ||
+ | } | ||
+ | else { | ||
+ | echo "<h2>Books</h2><pre>"; | ||
+ | echo $result; | ||
+ | echo "</pre>"; | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Com va passar en el servidor, primer s'ha d'incloure la llibreria ''nusoap.php'' amb la directiva ''required_once''. Seguidament, es crea un nova instància d'un client soap amb la classe: '''nusoap_client'''. El constructor necessita la localització del servidor soap al que s'ha de connectar. És a dir, del fitxer on es troba la creació del soap_server amb les funcions registrades. | ||
+ | |||
+ | La funció '''getError''' comprova si el client SOAP s'ha creat correctament i si no ha estat així, mostra un missatge d'error. | ||
+ | |||
+ | El mètode '''call()''' genera i envia un missatge SOAP de tipus petició (Request) a la funció o el mètode definit com a primer paràmetre. El segon paràmetre de la funció ''call()'' és un array associatiu del paràmetres que necessita el mètode servidor. | ||
+ | |||
+ | La propietat '''fault''' i el mètode '''getError()''' son utilitzat per comprovar i mostrar cualsevol error produït en la comunicació. | ||
+ | |||
+ | === Creació d'un arxiu WSDL === | ||
+ | |||
+ | Escriure un fitxer WSDL a mà pot ser de bojos. Una utilitat molt interessant de '''nusoap''' és que pot crear un fitxer WSDL automàticament. Veurem un exemple modificant una mica l'exemple anterior: | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | require_once "nusoap.php"; | ||
+ | |||
+ | function getProd($category) { | ||
+ | if ($category == "books") { | ||
+ | return join(",", array( | ||
+ | "The WordPress Anthology", | ||
+ | "PHP Master: Write Cutting Edge Code", | ||
+ | "Build Your Own Website the Right Way")); | ||
+ | } | ||
+ | else { | ||
+ | return "No products listed under that category"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $server = new soap_server(); | ||
+ | $server->configureWSDL("productlist", "urn:productlist"); | ||
+ | |||
+ | $server->register("getProd", | ||
+ | array("category" => "xsd:string"), | ||
+ | array("return" => "xsd:string"), | ||
+ | "urn:productlist", | ||
+ | "urn:productlist#getProd", | ||
+ | "rpc", | ||
+ | "encoded", | ||
+ | "Get a listing of products by category"); | ||
+ | |||
+ | $server->service($HTTP_RAW_POST_DATA); | ||
+ | |||
+ | /*if ( !isset( $HTTP_RAW_POST_DATA ) ) | ||
+ | $HTTP_RAW_POST_DATA =file_get_contents( 'php://input' ); | ||
+ | $server->service($HTTP_RAW_POST_DATA);*/ | ||
+ | </source> | ||
+ | Bàsicament és el mateix codi amb quatre canvis. El primer canvi que s'ha afegit és la crida a la funció '''configureWSDL()'''. Aquest mètode prepara al servidor per a que pugui generar un fitxer WSDL dels nostres serveis registrats. El primer paràmetre d'aquesta funció, és el nom del servei i el segon correspon a l'espai de noms del servei. | ||
+ | |||
+ | El segon canvi afegeix informació addicional al mètode '''register'''. Veiem-ho: | ||
+ | * '''getProd:''' correspon al nom de la funció | ||
+ | * '''array("category"=>"xsd:string")''' correspon a la descripció dels paràmetres que necessita la funció '''getProd''', veieu que cada paràmetre té associat un tipus de dades. | ||
+ | * '''array("return"=>"xsd:string")''' correspon al valor de retorn de la funció ''getProd''. S'ha d'especificar el tipus de dades a retornar. | ||
+ | * '''urn:productlist''' defineix l'espai de noms | ||
+ | * '''urn:productlist#getProd''' defineix l'acció SOAP | ||
+ | * '''rpc''' defineix el tipus de crida. Aquesta pot ser ''rpc'' o ''document'' | ||
+ | * '''encoded''' definexi el valor de l'atribut ''use''. Pot ser ''encoded'' o ''literal'' | ||
+ | * L'últim paràmetre és un string de documentació que descriu el mètode ''getProd''. | ||
+ | |||
+ | Per veure el fitxer wsdl només hem d'afegir a la url '''?wsdl''' al final. Exemple: http://yourwebroot/productlist.php?wsdl | ||
+ | Una vegada vegis el WSDL ja es pots copiar en un fitxer i depositar-lo en el directori web. | ||
+ | |||
+ | Al tenir el WSDL generat en un fitxer en el servidor web podem aprofitar-lo per crear un client soap que el llegeixi. Per fer-ho només s'ha de canviar aquesta línia del client soap: | ||
+ | <source lang="php"> | ||
+ | $client = new nusoap_client("http://localhost/nusoap/productlist.php"); | ||
+ | </source> | ||
+ | per aquesta altre: | ||
+ | <source lang="php"> | ||
+ | $client = new nusoap_client("products.wsdl", true); | ||
+ | </source> | ||
+ | Veieu que ara es crea el client SOAP utilitzant el fitxer '''products.wsdl''' que es troba en el mateix directory del servidor que l'aplicació client. El següent paràmetre és un booleà que indica que accepti aquest fitxer WSDL. | ||
+ | |||
+ | |||
+ | --> | ||
+ | =Pràctica Web Services = | ||
+ | |||
+ | *'''VideoTutorial SOAP:''' https://youtu.be/LIbP_pbwGZo | ||
+ | |||
+ | '''API:''' (siglas de ‘Application Programming Interface’) es un conjunto de reglas (código) y | ||
+ | especificaciones que las aplicaciones pueden seguir para comunicarse entre ellas. | ||
+ | |||
+ | '''¿Qué es SOAP?''' | ||
+ | |||
+ | *Los servicios SOAP o mejor conocimos simplemente como ''Web Services''. | ||
+ | |||
+ | *Son servicios que basan su comunicación bajo el protocolo ''SOAP'' (Simple Object Access Protocol) | ||
+ | según la Wiki "protocolo estándar que define cómo dos objetos en diferentes procesos pueden comunicarse por medio de intercambio de datos XML" | ||
+ | |||
+ | *Los servicios SOAP funcionan por lo general por el ''protocolo HTTP'', aunque también FTP, POP3, TCP... | ||
+ | |||
+ | '''WSDL''' (Web Services Description Language) es un protocolo basado en XML que describe los accesos al Web Service. Podríamos decir que es el manual de operación del mismo. | ||
+ | |||
+ | '''VENTAJAS:''' | ||
+ | |||
+ | *Protocolo mucho más robusto, tiene un tipiado mucho más fuerte (XSD,DTD) | ||
+ | |||
+ | *Permite agregar ''metadatos'' mediante los atributos (cosa que ''JSON no tien''e). | ||
+ | |||
+ | *Permite definir ''espacios de nombre'', evitando la ambigüedad. | ||
+ | |||
+ | '''INCONVENIENTES:''' | ||
+ | |||
+ | *SOAP es un formato ''más pesado'', tanto en tamaño como en procesamiento, pues los XML tiene que ser parseado a un árbol DOM resolver espacios de nombre (namespaces) antes de poder empezar a procesar el documento. | ||
+ | |||
+ | *Los XML además tienen métodos de ''validación muy potentes'' y ampliamente utilizados, a diferencia de JSON. | ||
+ | |||
+ | '''¿Qué es REST?''' | ||
+ | |||
+ | Hay que diferenciar dos conceptos: | ||
+ | |||
+ | '''REST''' (Representational State Transfer) es una arquitectura que se ejecuta sobre HTTP. | ||
+ | |||
+ | '''RESTful''' hace referencia a un servicio web que implementa la arquitectura REST. | ||
+ | |||
+ | REST es una tecnología ''mucho más flexible'' que transporta datos por medio del ''protocolo HTTP''. | ||
+ | |||
+ | Este permite utilizar los diversos métodos que proporciona HTTP para comunicarse, como lo son GET, POST, PUT, DELETE, PATCH y a la vez, utiliza los códigos de respuesta nativos de HTTP (404,200,204,409). | ||
+ | |||
+ | '''VENTAJAS:''' | ||
+ | |||
+ | *REST es tan flexible que permite transmitir prácticamente cualquier tipo de datos: ''JSON principalmente'', XML, Binarios (imágenes, documentos), Text, etc. | ||
+ | |||
+ | *JSON es ''interpretado de forma natural por JavaScript'', lo que ha hecho que frameworks como Angular, React y VUE se aprovechen al máximo, | ||
+ | pues pueden enviar peticiones directas al servidor por medio de AJAX y obtener los datos de una forma nativa. | ||
+ | |||
+ | *JSON son considerablemente ''más livianos en peso'' y mucho más rápido en su procesamiento | ||
+ | |||
+ | '''Diferencias entre SOAP y API''' | ||
+ | |||
+ | https://www.oscarblancarteblog.com/2017/03/06/soap-vs-rest-2/ | ||
+ | |||
+ | ------------------------ | ||
+ | |||
+ | ------------------------ | ||
+ | |||
+ | '''Descargar NUSOAP''' | ||
+ | |||
+ | https://github.com/pwnlabs/nusoap | ||
+ | |||
+ | |||
+ | ------------------------ | ||
+ | |||
+ | '''FICHERO SERVER.PHP''' | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | require_once "./nusoap/lib/nusoap.php"; | ||
+ | |||
+ | |||
+ | function getInfo() { | ||
+ | |||
+ | return "Info de los libros"; | ||
+ | |||
+ | } | ||
+ | |||
+ | |||
+ | function getProd($categoria) { | ||
+ | if ($categoria == "libros") { | ||
+ | return join(",", array( | ||
+ | "El señor de los anillos", | ||
+ | "Los límites de la Fundación", | ||
+ | "The Rails Way")); | ||
+ | } | ||
+ | else { | ||
+ | return "No hay productos de esta categoria"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | $server = new soap_server(); | ||
+ | $server->configureWSDL("producto", "urn:producto"); | ||
+ | |||
+ | $server->register("getProd", //nombre función | ||
+ | array("categoria" => "xsd:string"), //parametro de entrada | ||
+ | array("return" => "xsd:string"), //parametro de salida | ||
+ | "urn:producto", //namespace | ||
+ | "urn:producto#getProd", //accion SOAP | ||
+ | "rpc", //estilo | ||
+ | "encoded", | ||
+ | "Nos da una lista de productos de cada categoría"); | ||
+ | |||
+ | |||
+ | |||
+ | $server->register("getInfo", | ||
+ | array(""), | ||
+ | array("return" => "xsd:string"), | ||
+ | "urn:producto", | ||
+ | "urn:producto#getInfo", | ||
+ | "rpc", | ||
+ | "encoded", | ||
+ | "Nos da Info "); | ||
+ | |||
+ | if(!isset($HTTP_RAW_POST_DATA)){ ///Datos POST sin tratar , En general, se debería utilizar php://input en lugar de $HTTP_RAW_POST_DATA. | ||
+ | |||
+ | $HTTP_RAW_POST_DATA = file_get_contents("php://input"); | ||
+ | } | ||
+ | |||
+ | $server->service($HTTP_RAW_POST_DATA); | ||
+ | |||
+ | ?> | ||
+ | </source> | ||
+ | |||
+ | Primer s'inclou el fitxer '''nusoap.php'' per poder accedir a la llibreria NuSOAP. | ||
+ | |||
+ | Després es defineix la funció '''getProd()''' i s'instancia un objecte de la classe ''soap_server''. | ||
+ | |||
+ | Immediatament després s'utilitza el mètode '''register'' per afegir la funció ''getProd'' al servidor sopa i poder accedir a ella des de un client. És a dir, convertim la funció ''getProd'' en un servei web. | ||
+ | |||
+ | Segurament, en un escenari real, la funció ''getProd'' hauria de cercar en una Base de Dades la informació que s'ha d'enviar a l'usuari. Ara mateix, no volem complicar el codi en coses externes a SOAP. | ||
+ | |||
+ | Es poden registrar funcions addicionals en el servidor per per donar més funcionalitats a l'aplicació. El procés seria idèntic del descrit anteriorment. | ||
+ | |||
+ | Bàsicament és el mateix codi amb quatre canvis. El primer canvi que s'ha afegit és la crida a la funció '''configureWSDL()'''. | ||
+ | |||
+ | Aquest mètode prepara al servidor per a que pugui generar un fitxer WSDL dels nostres serveis registrats. El primer paràmetre d'aquesta funció, és el nom del servei i el segon correspon a l'espai de noms del servei. | ||
+ | |||
+ | '''FICHERO CLIENTE.PHP''' | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | require_once "./nusoap/lib/nusoap.php"; | ||
+ | |||
+ | $cliente = new nusoap_client("http://localhost/nusoap/client.php"); | ||
+ | //$cliente = new nusoap_client("http://localhost/webservice/server.php?wsdl", 'wsdl'); | ||
+ | //$cliente = new nusoap_client("./server.php?wsdl", true); | ||
+ | |||
+ | //si ocurre algún error al consumir el Web Service | ||
+ | if ($cliente->fault) { | ||
+ | $error = $cliente->getError(); | ||
+ | if ($error) { // Hubo algun error | ||
+ | echo 'Error:' . $error; | ||
+ | //echo 'Error2:' . $error->faultactor; | ||
+ | //echo 'Error3:' . $error->faultdetail;faultstring | ||
+ | //echo 'Error: ' . $cliente->faultstring; | ||
+ | } | ||
+ | |||
+ | die(); | ||
+ | } | ||
+ | |||
+ | $getProd = $cliente->call("getProd", array("categoria" => "libros")); | ||
+ | |||
+ | $getInfo = $cliente->call("getInfo"); | ||
+ | |||
+ | |||
+ | echo "<h2>Libros</h2><pre>"; | ||
+ | echo $getProd; | ||
+ | echo $getInfo; | ||
+ | echo "</pre>"; | ||
+ | ?> | ||
+ | </source> | ||
+ | |||
+ | Com va passar en el servidor, primer s'ha d'incloure la llibreria ''nusoap.php'' amb la directiva ''required_once''. | ||
+ | |||
+ | Seguidament, es crea un nova instància d'un client soap amb la classe: '''nusoap_client'''. | ||
+ | |||
+ | El constructor necessita la localització del servidor soap al que s'ha de connectar. És a dir, del fitxer on es troba la creació del soap_server amb les funcions registrades. | ||
+ | |||
+ | La funció '''getError''' comprova si el client SOAP s'ha creat correctament i si no ha estat així, mostra un missatge d'error. | ||
+ | |||
+ | El mètode '''call()''' genera i envia un missatge SOAP de tipus petició (Request) a la funció o el mètode definit com a primer paràmetre. El segon paràmetre de la funció ''call()'' és un array associatiu del paràmetres que necessita el mètode servidor. | ||
+ | |||
+ | La propietat '''fault''' i el mètode '''getError()''' son utilitzat per comprovar i mostrar cualsevol error produït en la comunicació. | ||
+ | |||
+ | |||
+ | --------------------------- | ||
+ | --------------------------- | ||
+ | '''Ejemplo de consumir un Web Service SOAP desde servidor externo (Obtener Ip)''' | ||
+ | https://ws.cdyne.com/ip2geo/ip2geo.asmx | ||
+ | <source lang="php"> | ||
+ | |||
+ | require_once "./nusoap.php"; | ||
+ | $url = "http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl"; | ||
+ | try { | ||
+ | ''' $client = new SoapClient($url, 'wsdl' ); cambio la sentencia da error''' | ||
+ | $client=new nusoap_client($url,'wsdl'); | ||
+ | $param=array('ipAddress'=>"210.45.151.101", 'licenseKey' => "0"); | ||
+ | $result = $client->call('ResolveIP', $param); | ||
+ | print_r($result); | ||
+ | } catch ( SoapFault $e ) { | ||
+ | echo $e->getMessage(); | ||
+ | } | ||
+ | echo PHP_EOL; | ||
+ | </source> | ||
+ | |||
+ | --------------------------- | ||
+ | --------------------------- | ||
+ | '''Ejemplo de consumir un Web Service SOAP de la universidad de Alicante desde el cliente.''' | ||
+ | |||
+ | La dirección que expone este Web Services es la siguiente: https://cvnet.cpd.ua.es/servicioweb/publicos/pub_gestdocente.asmx?wsdl, como puedes ver al final muestra un archivo WSDL, que es donde expone las interfaces que van a ser consumidas. | ||
+ | |||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | header('Content-Type: text/html; charset=ISO-8859-1'); | ||
+ | require_once('lib/nusoap.php'); | ||
+ | //Parámetros | ||
+ | $slengua = "C"; | ||
+ | $scurso = "2011-12"; | ||
+ | $scoddep = "B142"; | ||
+ | $scodest = ""; | ||
+ | |||
+ | //url del webservice | ||
+ | $wsdl="https://cvnet.cpd.ua.es/servicioweb/publicos/pub_gestdocente.asmx?wsdl"; | ||
+ | |||
+ | //instanciando un nuevo objeto cliente para consumir el webservice | ||
+ | $client=new nusoap_client($wsdl,'wsdl'); | ||
+ | //pasando los parámetros a un array | ||
+ | $param=array('plengua'=>$slengua, 'pcurso' => $scurso, 'pcoddep' => $scoddep, 'pcodest' => $scodest); | ||
+ | //llamando al método y pasándole el array con los parámetros | ||
+ | $resultado = $client->call('wsasidepto', $param); | ||
+ | |||
+ | //si ocurre algún error al consumir el Web Service | ||
+ | if ($client->fault) { // si | ||
+ | $error = $client->getError(); | ||
+ | if ($error) { // Hubo algun error | ||
+ | //echo 'Error:' . $error; | ||
+ | //echo 'Error2:' . $error->faultactor; | ||
+ | //echo 'Error3:' . $error->faultdetail;faultstring | ||
+ | echo 'Error: ' . $client->faultstring; | ||
+ | } | ||
+ | |||
+ | die(); | ||
+ | } | ||
+ | |||
+ | echo "<pre>"; | ||
+ | //print_r($resultado); | ||
+ | $result=$resultado['wsasideptoResult']['ClaseAsiDepto']; | ||
+ | |||
+ | for($i=0;$i<=count($result);$i++){ | ||
+ | echo $result[$i]['codasi']."<br>"; | ||
+ | echo $result[$i]['nomasi']."<br>"; | ||
+ | echo $result[$i]['enlaceasi']."<br>"; | ||
+ | echo $result[$i]['codest']."<br>"; | ||
+ | echo $result[$i]['nomest']."<br>"; | ||
+ | echo "<br>"."<br>"; | ||
+ | } | ||
+ | echo "</pre>"; | ||
+ | |||
+ | |||
+ | ?> | ||
+ | </source> | ||
+ | |||
+ | --------------------------- | ||
+ | --------------------------- | ||
+ | |||
+ | '''FICHERO TXT EN EL SERVIDOR''' | ||
+ | <source lang="TXT"> | ||
+ | melon, | ||
+ | melocoton, | ||
+ | banana, | ||
+ | frambuesa | ||
+ | </source> | ||
+ | |||
+ | |||
+ | '''RECUPERA FICHERO MOSTRANDO DATOS''' | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | |||
+ | $curl = curl_init("http://localhost/frutas.txt"); //Inicia una nueva sesión cURL | ||
+ | |||
+ | curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //Define opciones para nuestra sesion cURL, si se quiere que el contenido que devuelve la página se almacene en una variable, se puede utilizar la opción CURLOPT_RETURNTRANSFER | ||
+ | |||
+ | $respuesta = curl_exec($curl); //Ejecuta la sesión cURL que se le pasa como parámetro. | ||
+ | |||
+ | $info = curl_getinfo($curl); //Obtiene información de la última transferencia | ||
+ | |||
+ | echo $respuesta; | ||
+ | echo $info; | ||
+ | |||
+ | if($info['http_code'] == 200){ | ||
+ | |||
+ | |||
+ | $datos = explode (",", $respuesta); | ||
+ | |||
+ | echo "<h1>Frutas en mi tienda</h1>"; | ||
+ | |||
+ | foreach ($datos as $key => $value) { | ||
+ | echo $key."->".$value . "<br>"; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | /* //ejemplo cargar una web en el php | ||
+ | $cliente = curl_init(); | ||
+ | curl_setopt($cliente, CURLOPT_URL, "https://www.google.com/search?q=lamerce"); | ||
+ | curl_exec($cliente); | ||
+ | curl_close($cliente); | ||
+ | */ | ||
+ | |||
+ | |||
+ | ?> | ||
+ | </source> | ||
+ | |||
+ | |||
+ | ==Exercici Web Service SOAP == | ||
+ | *Crea un servei web que permeti Sumar, Restar, Multiplicar i Dividir. | ||
+ | *Busca un servei web a internet que utilitzi SOAP. site: wsdl | ||
+ | *Crea un servei web que façi dos consultes a una base de dades que tingui informació. | ||
+ | *Crea una aplicació client en PHP que també utilitzi aquest servei amb wsdl. | ||
+ | |||
+ | --------------------------- | ||
+ | --------------------------- | ||
+ | |||
+ | = API RESTFUL PHP = | ||
+ | |||
+ | '''VIDEOTUTORIAL''' | ||
+ | |||
+ | https://youtu.be/aC0gCDylAxk | ||
+ | |||
+ | |||
+ | '''curl''' o '''file_gets_contents()''' | ||
+ | |||
+ | -Para recuperar datos de una API, pueden usarse dos formas con '''curl''' o '''file_gets_contents()''' | ||
+ | |||
+ | '''Tenemos dos opciones, ¿Cúal es mejor?''' | ||
+ | |||
+ | |||
+ | '''file_get_contents()''' | ||
+ | |||
+ | * Es un simple destornillador. Ideal para ''simples solicitudes GET'' donde el encabezado, método de solicitud HTTP, tiempo de espera, cookies, redirecciones y otras cosas más complejas no importan. | ||
+ | |||
+ | * También se pueden ''usar para peticiones POS''T, pero habría que crear un contexto para ello (Ver esta contribución en el Manual de PHP). | ||
+ | |||
+ | * Es ''menos seguro que cURL'' y por eso viene desactivado por defecto en muchos entornos PHP. | ||
+ | |||
+ | '''cURL''' | ||
+ | |||
+ | * Es mucho ''más potente'' y para usos más avanzados. | ||
+ | |||
+ | * cURL es probablemente ''la librería de HTTP'' más ampliamente utilizada en el mundo de la programación. Originalmente fue ''codificado utilizando lenguaje C'', y luego fue portado a muchos otros lenguajes. | ||
+ | |||
+ | * cURL puede manejar manipulaciones ''HTTP complicadas de manera elegante'', como solicitudes HTTP asíncronas, informes de progreso, etc. | ||
+ | |||
+ | * El único problema de cURL es que requiere algún tiempo, varias horas al menos, para familiarizarse con sus funciones y estilo de codificación. Al ser una librería tan usada, la ''documentación y ejemplos'' de código en la red son ''abundantes''. | ||
+ | |||
+ | |||
+ | '''¿Cuál es más rápido?''' | ||
+ | |||
+ | * Todas las pruebas que he leído hasta ahora indican que ''cURL es más rápido''. | ||
+ | |||
+ | * El siguiente gráfico es el producto de una prueba entre diferentes métodos, publicada por Philip Norton en Quickest Way To Download A Web Page With PHP | ||
+ | |||
+ | https://es.stackoverflow.com/questions/81565/diferencias-entre-file-get-contents-y-curl | ||
+ | |||
+ | Antes hay que asegurarse que '''curl está instalado en nuestro server apache.''' | ||
+ | |||
+ | <source lang="script"> | ||
+ | sudo apt-get install curl-php | ||
+ | |||
+ | sudo service apache2 restart | ||
+ | |||
+ | </source> | ||
+ | |||
+ | '''Instalar POSTMAN para hacer las pruebas''' | ||
+ | <source lang="script"> | ||
+ | |||
+ | wget https://dl.pstmn.io/download/latest/linux64 -O postman.tar.gz | ||
+ | sudo tar -xzf postman.tar.gz -C /opt | ||
+ | rm postman.tar.gz | ||
+ | sudo ln -s /opt/Postman/Postman /usr/bin/postman | ||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | '''SERVIDOR''' | ||
+ | <source lang="php"> | ||
+ | <?php | ||
+ | // La base de datos se llama blog, la tabla "posts" y sus atributos (title, status, content, user_id) | ||
+ | $connection=mysqli_connect('localhost','root','','blog1'); | ||
+ | |||
+ | $request_method=$_SERVER["REQUEST_METHOD"]; | ||
+ | switch($request_method) | ||
+ | { | ||
+ | case 'GET': | ||
+ | // Retrive Products | ||
+ | if(!empty($_GET["id"])) | ||
+ | { | ||
+ | $id=intval($_GET["id"]); //transforma en número entero | ||
+ | get_products($id); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | get_products(); | ||
+ | } | ||
+ | break; | ||
+ | |||
+ | case 'POST': | ||
+ | insert_product(); | ||
+ | break; | ||
+ | |||
+ | case 'PUT': | ||
+ | // Update Product | ||
+ | $id=intval($_GET["id"]); | ||
+ | update_product($id); | ||
+ | break; | ||
+ | |||
+ | case 'DELETE': | ||
+ | // Delete Product | ||
+ | $id=intval($_GET["id"]); | ||
+ | delete_product($id); | ||
+ | break; | ||
+ | |||
+ | default: | ||
+ | // Invalid Request Method | ||
+ | header("HTTP/1.0 405 Method Not Allowed"); | ||
+ | break; | ||
+ | } | ||
+ | |||
+ | function insert_product() | ||
+ | { | ||
+ | global $connection; | ||
+ | $title=$_REQUEST["title"]; | ||
+ | $status=$_REQUEST["status"]; | ||
+ | $content=$_REQUEST["content"]; | ||
+ | $user_id=$_REQUEST["user_id"]; | ||
+ | |||
+ | $query = "INSERT INTO posts (title, status, content, user_id) VALUES ('$title', '$status', '$content', '$user_id')"; | ||
+ | |||
+ | |||
+ | if(mysqli_query($connection, $query)) | ||
+ | { | ||
+ | $response=array( | ||
+ | 'status' => 1, | ||
+ | 'status_message' =>'Product Added Successfully.' | ||
+ | ); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | $response=array( | ||
+ | 'status' => 0, | ||
+ | 'status_message' =>'Product Addition Failed.' | ||
+ | ); | ||
+ | } | ||
+ | header('Content-Type: application/json'); | ||
+ | echo json_encode($response); | ||
+ | } | ||
+ | |||
+ | function get_products($id=0) | ||
+ | { | ||
+ | |||
+ | global $connection; | ||
+ | $query="SELECT * FROM posts"; | ||
+ | if($id!= 0) | ||
+ | { | ||
+ | $query.=" WHERE id=".$id." LIMIT 1"; | ||
+ | } | ||
+ | $response=array(); | ||
+ | $result=mysqli_query($connection, $query); | ||
+ | while($row=mysqli_fetch_array($result)) | ||
+ | { | ||
+ | $response[]=$row; | ||
+ | } | ||
+ | header('Content-Type: application/json'); | ||
+ | echo json_encode($response); | ||
+ | } | ||
+ | |||
+ | function delete_product($id) | ||
+ | { | ||
+ | global $connection; | ||
+ | |||
+ | $query="DELETE FROM posts WHERE id=".$id; | ||
+ | if(mysqli_query($connection, $query)) | ||
+ | { | ||
+ | $response=array( | ||
+ | 'status' => 1, | ||
+ | 'status_message' =>'Product Deleted Successfully.' | ||
+ | ); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | $response=array( | ||
+ | 'status' => 0, | ||
+ | 'status_message' =>'Product Deletion Failed.' | ||
+ | ); | ||
+ | } | ||
+ | header('Content-Type: application/json'); | ||
+ | echo json_encode($response); | ||
+ | } | ||
+ | |||
+ | function update_product($id) | ||
+ | { | ||
+ | |||
+ | //(title, status, content, user_id) | ||
+ | global $connection; | ||
+ | parse_str(file_get_contents("php://input"),$post_vars); //php://input es un flujo de sólo lectura que permite leer datos del cuerpo solicitado, por tanto $post_vars recibirá todos los datos(título, status,content,user_id). | ||
+ | |||
+ | $title=$post_vars["title"]; | ||
+ | $status=$post_vars["status"]; | ||
+ | $content=$post_vars["content"]; | ||
+ | $user_id=$post_vars["user_id"]; | ||
+ | $query="UPDATE posts SET title='{$title}', status='{$status}', content='{$content}', user_id='{$user_id}' WHERE id=".$id; | ||
+ | if(mysqli_query($connection, $query)) | ||
+ | { | ||
+ | $response=array( | ||
+ | 'status' => 1, | ||
+ | 'status_message' =>'Product Updated Successfully.' | ||
+ | ); | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | $response=array( | ||
+ | 'status' => 0, | ||
+ | 'status_message' =>'Product Updation Failed.' | ||
+ | ); | ||
+ | } | ||
+ | header('Content-Type: application/json'); | ||
+ | echo json_encode($response); | ||
+ | } | ||
+ | |||
+ | // Close database connection | ||
+ | mysqli_close($connection); | ||
+ | </source> | ||
+ | |||
+ | |||
+ | '''CLIENTE''' | ||
+ | <source lang="php"> | ||
+ | /*************GET*************/ | ||
+ | |||
+ | $url = 'http://localhost/api/server.php?id=1'; | ||
+ | $ch = curl_init($url); | ||
+ | curl_setopt($ch, CURLOPT_HTTPGET, true); | ||
+ | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||
+ | $respuesta = curl_exec($ch); | ||
+ | print_r($respuesta); //respuesta | ||
+ | curl_close($ch); | ||
+ | $response_json=json_decode($respuesta, true); | ||
+ | print_r($response_json); //respuesta en JSON | ||
+ | |||
+ | /*************DELETE*************/ | ||
+ | |||
+ | $url = 'http://localhost/api/server.php?id=2'; | ||
+ | $ch = curl_init($url); //// abrimos la sesión cURL | ||
+ | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); // definimos la URL a la que hacemos la petición | ||
+ | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // recibimos la respuesta y la guardamos en una variable | ||
+ | $response_json = curl_exec($ch); | ||
+ | curl_close($ch); // recibimos la respuesta y la guardamos en una variable | ||
+ | $response=json_decode($response_json, true); | ||
+ | print_r($response); | ||
+ | |||
+ | |||
+ | /*************PUT*************/ | ||
+ | $data=array( | ||
+ | 'title' =>'Nuevo', | ||
+ | 'status' => "enviado", | ||
+ | 'content' => "10", | ||
+ | 'user_id' =>'2' | ||
+ | ); | ||
+ | $url = 'http://localhost/api/server.php?id=3'; | ||
+ | $ch = curl_init($url); | ||
+ | curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); | ||
+ | curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); | ||
+ | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||
+ | $respuesta = curl_exec($ch); | ||
+ | curl_close($ch); | ||
+ | |||
+ | print_r($respuesta); //{"status":1,"status_message":"Product Updated Successfully."} | ||
+ | $response_json=json_decode($respuesta, true); | ||
+ | print_r($response_json); //Array ( [status] => 1 [status_message] => Product Updated Successfully. ) | ||
+ | |||
+ | /*************POST*************/ | ||
+ | $data=array( | ||
+ | 'title' =>'Television', | ||
+ | 'status' => "1000", | ||
+ | 'content' => "10", | ||
+ | 'user_id' =>'2' | ||
+ | ); | ||
+ | $url = 'http://localhost/api/server.php'; | ||
+ | |||
+ | $ch = curl_init($url); | ||
+ | curl_setopt($ch, CURLOPT_POST, true); // indicamos el tipo de petición: POST | ||
+ | // definimos cada uno de los parámetros | ||
+ | curl_setopt($ch, CURLOPT_POSTFIELDS, $data); //curl_setopt($ch, CURLOPT_POSTFIELDS, "title=value1&status=value2&content=value3&user_id=5"); | ||
+ | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // recibimos la respuesta y la guardamos en una variable $ch | ||
+ | |||
+ | $respuesta= curl_exec($ch); //ejecutamos la sesión cUrl | ||
+ | curl_close($ch); // cerramos la sesión cURL | ||
+ | print_r($response_json); //mostramos datos {"status":1,"status_message":"Product Added Successfully."} | ||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | También se pueden hacer llamadas al servidor mediante el terminal.. | ||
+ | <source lang="script"> | ||
+ | //POST | ||
+ | curl -d "title=value1&status=value2&content=value3&user_id=5" http://localhost/api1/server.php | ||
+ | |||
+ | curl --data "title=value1&status=value2&content=value3&user_id=value4" http://localhost/api1/server.php | ||
+ | |||
+ | //DELETE | ||
+ | curl -X "DELETE" http://localhost/api1/server.php?id=1 | ||
+ | |||
+ | //GET | ||
+ | curl --data "title=value1&si -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost/api1/server.php?id=1 | ||
+ | |||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | http://frikibloggeo.blogspot.com/2017/01/crear-un-web-service-api-rest-con-php-y.html | ||
+ | |||
+ | |||
+ | '''EXERCICIS''' | ||
+ | |||
+ | *Familiarizarse con cURL y crear una API con una base de datos y probar el funcionamiento de POSTMAN | ||
+ | *Encontrar como hacer un GET por consola del cURL, también probar cómo ejecutar en el terminal del servidor estos comandos. | ||
+ | |||
+ | https://www.apptha.com/blog/how-to-build-a-rest-api-using-php/ | ||
+ | |||
+ | https://www.tmb.cat/es/sobre-tmb/herramientas-para-desarrolladores/datos-tiempo-real | ||
+ | |||
+ | https://github.com/public-apis/public-apis/blob/master/README.md | ||
+ | |||
+ | = API RESTFUL LARAVEL = | ||
+ | |||
+ | '''VIDEOTUTORIAL''' | ||
+ | |||
+ | https://youtu.be/-qefsJtOrHo | ||
+ | |||
+ | '''Interfaz Rutas API''' | ||
+ | |||
+ | https://styde.net/como-documentar-una-api-en-laravel-usando-swagger/ | ||
+ | |||
+ | https://github.com/mpociot/documentarian | ||
+ | |||
+ | 1. Crearemos la migración '''tareas''', que se encuentra en ''database/migrations'' | ||
+ | |||
+ | '''php artisan make:migration create_tareas_table --create="tareas"''' | ||
+ | |||
+ | <source lang="php"> | ||
+ | public function up() | ||
+ | { | ||
+ | Schema::create('tareas', function (Blueprint $table) { | ||
+ | $table->increments('id'); | ||
+ | $table->string('name',20); | ||
+ | $table->string('description',50); | ||
+ | $table->string('content',100); | ||
+ | |||
+ | }); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | 2. Creamos el modelo | ||
+ | |||
+ | '''php artisan make:model Tarea''' | ||
+ | |||
+ | <source lang="php"> | ||
+ | class Tarea extends Model | ||
+ | { | ||
+ | protected $fillable = ['name', 'description', 'content']; | ||
+ | public $timestamps = false; //indicamos que no queremos usar update_at y create_at en la base de datos. | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | 3. Creamos el controlador TareasController | ||
+ | |||
+ | '''php artisan make:controller TareasController''' | ||
+ | |||
+ | <source lang="php"> | ||
+ | use App\Tarea; //añadimos el modelo | ||
+ | |||
+ | class TareasController extends Controller | ||
+ | { | ||
+ | public function index(Request $request) | ||
+ | { | ||
+ | $task = Tarea::all(); | ||
+ | return $task; | ||
+ | //Esta función nos devolvera todas las tareas que tenemos en nuestra BD | ||
+ | } | ||
+ | |||
+ | public function store(Request $request) | ||
+ | { | ||
+ | $task = new Tarea(); | ||
+ | $task->name = $request->name; | ||
+ | $task->description = $request->description; | ||
+ | $task->content = $request->content; | ||
+ | |||
+ | $task->save(); | ||
+ | //Esta función guardará las tareas que enviaremos | ||
+ | return response()->json([ | ||
+ | "message" => "Tarea almacenada con éxito" | ||
+ | ], 201); | ||
+ | } | ||
+ | public function show(Request $request) | ||
+ | { | ||
+ | $task = Tarea::findOrFail($request->id); | ||
+ | return $task; | ||
+ | //Esta función devolverá los datos de una tarea que hayamos seleccionado para cargar el formulario con sus datos | ||
+ | } | ||
+ | |||
+ | public function update(Request $request) | ||
+ | { | ||
+ | $task = Tarea::findOrFail($request->id); | ||
+ | |||
+ | $task->name = $request->name; | ||
+ | $task->description = $request->description; | ||
+ | $task->content = $request->content; | ||
+ | |||
+ | $task->save(); | ||
+ | |||
+ | return $task; | ||
+ | //Esta función actualizará la tarea que hayamos seleccionado | ||
+ | |||
+ | } | ||
+ | |||
+ | public function destroy(Request $request) | ||
+ | { | ||
+ | $task = Tarea::destroy($request->id); //task tienen el id que se ha borrado | ||
+ | |||
+ | return response()->json([ | ||
+ | "message" => "Tarea con id =" . $task . " ha sido borrado con éxito" | ||
+ | ], 201); | ||
+ | //Esta función obtendra el id de la tarea que hayamos seleccionado y la borrará de nuestra BD | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | 4.Para la creación de las rutas lo añadimos en ''routes->api'', en vez de routes->web | ||
+ | <source lang="php"> | ||
+ | Route::get('/tareas', 'TareasController@index'); | ||
+ | |||
+ | Route::put('/tareas/actualizar/{id}', 'TareasController@update'); | ||
+ | |||
+ | Route::post('/tareas/guardar', 'TareasController@store'); | ||
+ | |||
+ | Route::delete('/tareas/borrar/{id}', 'TareasController@destroy'); | ||
+ | |||
+ | Route::get('/tareas/buscar/{id}', 'TareasController@show'); | ||
+ | </source> | ||
+ | |||
+ | Para listar las rutas: | ||
+ | ''' | ||
+ | php artisan route:list -v''' | ||
+ | |||
+ | |||
+ | Ahora vamos hacer pruebas desde '''POSTMAN''' | ||
+ | |||
+ | '''IMPORTANTE:''' fijaos que la ruta es .../public/api/... | ||
+ | |||
+ | Para '''GET''' -> index | ||
+ | |||
+ | [[Fitxer:get.png |500px |center]] | ||
+ | |||
+ | Para '''POST''' -> create | ||
+ | |||
+ | Aspecto interesantes del post: | ||
+ | |||
+ | *'''x-www-form-urlencoded''' Si desea enviar texto simple / datos ASCII, este es el valor predeterminado. Esta codificación es la misma que la utilizada en los parámetros de URL. Solo necesita ingresar los pares clave/valor y Postman codificará las claves y los valores correctamente | ||
+ | |||
+ | *'''form-data:''' Pero si tiene que enviar texto no ASCII o datos binarios grandes, los datos del formulario son para eso. | ||
+ | |||
+ | *'''Raw''' si desea enviar texto sin formato o JSON o cualquier otro tipo de cadena. Como su nombre indica, Postman envía sus datos de cadena sin procesar tal como están sin modificaciones. El tipo de datos que está enviando se puede configurar utilizando el encabezado de tipo de contenido del menú desplegable. | ||
+ | |||
+ | *'''Binario''' se puede usar cuando desea adjuntar datos no textuales a la solicitud, por ejemplo: un archivo de video / audio, imágenes o cualquier otro archivo de datos binarios. | ||
+ | |||
+ | [[Fitxer:post.png |500px |center]] | ||
+ | |||
+ | Para '''GET''' para obtener con id específico -> show | ||
+ | |||
+ | [[Fitxer:show.png ||500px |center]] | ||
+ | |||
+ | Para '''PUT''' -> update | ||
+ | |||
+ | [[Fitxer:put.png |500px |center]] | ||
+ | |||
+ | |||
+ | Para '''DELETE''' -> delete | ||
+ | |||
+ | [[Fitxer:delete.png |500px |center]] | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | <source lang="php"> | ||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | <source lang="php"> | ||
+ | |||
+ | </source> | ||
+ | https://www.nigmacode.com/laravel/Crear-API-REST-con-Laravel | ||
+ | |||
+ | |||
+ | === DOCUMENTAR API SWAGGER === | ||
+ | |||
+ | Instalamos el paquete swagger | ||
+ | |||
+ | <source lang="script"> | ||
+ | composer require "darkaonline/l5-swagger:6.*" | ||
+ | </source> | ||
+ | |||
+ | Instalamos el paquete para las anotaciones que va relacionado | ||
+ | |||
+ | <source lang="script"> | ||
+ | composer require zircote/swagger-php | ||
+ | </source> | ||
+ | |||
+ | publicamos la vista y configuración del paquete | ||
+ | |||
+ | <source lang="script"> | ||
+ | php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider" | ||
+ | </source> | ||
+ | |||
+ | podemos comprobar cómo han quedado las rutas y vemos que ha añadido "api/documentation" | ||
+ | |||
+ | <source lang="script"> | ||
+ | php artisan route:list | ||
+ | </source> | ||
+ | |||
+ | luego añadimos las anotaciones antes de cada función | ||
+ | |||
+ | <source lang="script"> | ||
+ | @OA\Info | ||
+ | @OA\License | ||
+ | @OA\Tag | ||
+ | @OA\Server | ||
+ | @OA\SecurityScheme | ||
+ | @OA\RequestBody | ||
+ | @OA\Property | ||
+ | @OA\Get | ||
+ | @OA\Post | ||
+ | @OA\Put | ||
+ | </source> | ||
+ | https://zircote.github.io/swagger-php/Getting-started.html#write-annotations | ||
+ | |||
+ | y generamos | ||
+ | |||
+ | <source lang="script"> | ||
+ | php artisan l5-swagger:generate | ||
+ | </source> | ||
+ | |||
+ | https://styde.net/como-documentar-una-api-en-laravel-usando-swagger/ | ||
+ | |||
+ | =API RESTFUL LARAVEL - PASSPORT TOKEN= | ||
+ | |||
+ | '''VIDEOTUTORIAL:''' | ||
+ | |||
+ | https://youtu.be/IemVQrcFrB0 | ||
+ | |||
+ | https://youtu.be/9F85AGNmFZ0 | ||
+ | |||
+ | |||
+ | |||
+ | 1. Creamos proyecto | ||
+ | |||
+ | '''composer create-project --prefer-dist laravel/laravel blog''' | ||
+ | |||
+ | 2. Descargamos paquete Passport | ||
+ | |||
+ | '''composer require laravel/passport''' | ||
+ | |||
+ | 3. Luego en '''config/app.php''' añadimos el servido de Provider | ||
+ | |||
+ | <source lang="script"> | ||
+ | /*Añadimos providers*/ | ||
+ | |||
+ | 'providers' =>[ | ||
+ | |||
+ | Laravel\Passport\PassportServiceProvider::class, | ||
+ | |||
+ | ], | ||
+ | </source> | ||
+ | |||
+ | 4. Después de añadir el provider, generamos la migración '''php artisan migrate''' | ||
+ | |||
+ | 5. A continuación, tenemos que instalar "passport" en el proyecto y esto generará los Tokens | ||
+ | '''php artisan passport:install''' | ||
+ | |||
+ | 6. Añadimos HasApiTokens en ruta '''app/User.php''' | ||
+ | |||
+ | <source lang="script"> | ||
+ | |||
+ | <?php | ||
+ | |||
+ | namespace App; | ||
+ | use Laravel\Passport\HasApiTokens; /*añadimos Clase HasApiTokens*/ | ||
+ | |||
+ | use Illuminate\Notifications\Notifiable; | ||
+ | use Illuminate\Foundation\Auth\User as Authenticatable; | ||
+ | |||
+ | class User extends Authenticatable | ||
+ | { | ||
+ | use HasApiTokens, Notifiable; /*añadimos HasApiTokens*/ | ||
+ | |||
+ | /** | ||
+ | * The attributes that are mass assignable. | ||
+ | * | ||
+ | * @var array | ||
+ | */ | ||
+ | |||
+ | protected $fillable = [ | ||
+ | 'name', 'email', 'password', | ||
+ | ];/** | ||
+ | * The attributes that should be hidden for arrays. | ||
+ | * | ||
+ | * @var array | ||
+ | */ | ||
+ | |||
+ | protected $hidden = [ | ||
+ | 'password', 'remember_token', | ||
+ | ];} | ||
+ | |||
+ | </source> | ||
+ | |||
+ | |||
+ | 7. Añadimos linea '''Passport::routes();''' en ruta '''app/Providers/AuthServiceProvider.php''' | ||
+ | <source lang="script"> | ||
+ | |||
+ | <?php | ||
+ | namespace App\Providers; | ||
+ | |||
+ | use Laravel\Passport\Passport; /*Añadimos Clase Passport*/ | ||
+ | |||
+ | use Illuminate\Support\Facades\Gate; | ||
+ | use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; | ||
+ | |||
+ | class AuthServiceProvider extends ServiceProvider | ||
+ | { | ||
+ | /** | ||
+ | * The policy mappings for the application. | ||
+ | * | ||
+ | * @var array | ||
+ | */ | ||
+ | protected $policies = [ | ||
+ | 'App\Model' => 'App\Policies\ModelPolicy', | ||
+ | ]; | ||
+ | |||
+ | /** | ||
+ | * Register any authentication / authorization services. | ||
+ | * | ||
+ | * @return void | ||
+ | */ | ||
+ | public function boot() | ||
+ | { | ||
+ | $this->registerPolicies(); | ||
+ | Passport::routes(); /*añadimos esta linea*/ | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | |||
+ | 8. Añadimos que también nos vamos autentificar en la API en '''config/auth.php''' | ||
+ | <source lang="script"> | ||
+ | |||
+ | <?php | ||
+ | return ['guards' => [ | ||
+ | 'web' => [ | ||
+ | 'driver' => 'session', | ||
+ | 'provider' => 'users', | ||
+ | ], | ||
+ | 'api' => [ /*añadimos linea api*/ | ||
+ | 'driver' => 'passport', | ||
+ | 'provider' => 'users', | ||
+ | ], | ||
+ | ], | ||
+ | </source> | ||
+ | |||
+ | 9. Añadimos rutas en '''Routes->api.php''' | ||
+ | |||
+ | <source lang="script"> | ||
+ | Route::post('login', 'API\UserController@login'); | ||
+ | Route::post('register', 'API\UserController@register'); | ||
+ | Route::group(['middleware' => 'auth:api'], function () { | ||
+ | Route::get('details', 'API\UserController@details'); | ||
+ | Route::get('logout', 'API\UserController@logout'); | ||
+ | }); | ||
+ | </source> | ||
+ | |||
+ | 10. Añadimos nuestras funciones en el controlador dentro de la carpeta API | ||
+ | |||
+ | '''php artisan make:controller API\UserController''' | ||
+ | <source lang="script"> | ||
+ | <?php | ||
+ | |||
+ | namespace App\Http\Controllers\API; | ||
+ | |||
+ | use Illuminate\Http\Request; | ||
+ | use App\Http\Controllers\Controller; | ||
+ | use App\User; | ||
+ | use Illuminate\Support\Facades\Auth; | ||
+ | use Validator; | ||
+ | |||
+ | class UserController extends Controller | ||
+ | { | ||
+ | |||
+ | public $successStatus = 200; | ||
+ | /** | ||
+ | * login api | ||
+ | * | ||
+ | * @return \Illuminate\Http\Response | ||
+ | */ | ||
+ | public function login() | ||
+ | { | ||
+ | if (Auth::attempt(['email' => request('email'), 'password' => request('password')])) { | ||
+ | $user = Auth::user(); | ||
+ | $success['token'] = $user->createToken('MyApp')->accessToken; | ||
+ | return response()->json(['success' => $success], $this->successStatus); | ||
+ | } else { | ||
+ | return response()->json(['error' => 'Unauthorised'], 401); | ||
+ | } | ||
+ | } | ||
+ | /** | ||
+ | * Register api | ||
+ | * | ||
+ | * @return \Illuminate\Http\Response | ||
+ | */ | ||
+ | public function register(Request $request) | ||
+ | { | ||
+ | |||
+ | $validator = Validator::make($request->all(), [ | ||
+ | 'name' => 'required', | ||
+ | 'email' => 'required|email', | ||
+ | 'password' => 'required', | ||
+ | 'c_password' => 'required|same:password', | ||
+ | ]); | ||
+ | if ($validator->fails()) { | ||
+ | return response()->json(['error' => $validator->errors()], 401); | ||
+ | } | ||
+ | $input = $request->all(); | ||
+ | $input['password'] = bcrypt($input['password']); | ||
+ | $user = User::create($input); | ||
+ | $success['token'] = $user->createToken('MyApp')->accessToken; | ||
+ | $success['name'] = $user->name; | ||
+ | return response()->json(['success' => $success], $this->successStatus); | ||
+ | } | ||
+ | /** | ||
+ | * details api | ||
+ | * | ||
+ | * @return \Illuminate\Http\Response | ||
+ | */ | ||
+ | public function details() | ||
+ | { | ||
+ | $user = Auth::user(); | ||
+ | return response()->json(['success' => $user], $this->successStatus); | ||
+ | } | ||
+ | |||
+ | |||
+ | |||
+ | public function logout(Request $request) | ||
+ | { | ||
+ | |||
+ | $isUser = $request->user()->token()->revoke(); | ||
+ | if($isUser){ | ||
+ | $success['message'] = "Successfully logged out."; | ||
+ | return response()->json(['success' => $isUser], $this->successStatus); | ||
+ | } | ||
+ | else{ | ||
+ | return response()->json(['error' => 'Unauthorised'], 401); | ||
+ | } | ||
+ | |||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | |||
+ | 1. Pruebas Postman. | ||
+ | |||
+ | '''REGISTER''' | ||
+ | |||
+ | [[Fitxer:registrer.png | 850px | center]] | ||
+ | |||
+ | <source lang="script"> | ||
+ | localhost/api/public/api/register -> método POST | ||
+ | name | ||
+ | email | ||
+ | password | ||
+ | c_password | ||
+ | </source> | ||
+ | |||
+ | '''LOGIN''' | ||
+ | |||
+ | [[Fitxer:login.png | 850px | center]] | ||
+ | <source lang="script"> | ||
+ | localhost/api/public/api/login -> método POST | ||
+ | email | ||
+ | password | ||
+ | |||
+ | </source> | ||
+ | |||
+ | '''DETAILS''' | ||
+ | |||
+ | [[Fitxer:details.png | 850px | center]] | ||
+ | <source lang="script"> | ||
+ | localhost/api/public/api/details-> método GET | ||
+ | 'Authorization' => 'Bearer '.$NuestroToken, | ||
+ | </source> | ||
+ | |||
+ | '''LOGOUT''' | ||
+ | |||
+ | [[Fitxer:logout.png | 850px | center]] | ||
+ | |||
+ | <source lang="script"> | ||
+ | localhost/api/public/api/logout-> método GET | ||
+ | 'accept' => 'application/json', | ||
+ | 'Content-Type' => 'application/x-www-form-urlencoded' | ||
+ | 'Authorization' => 'Bearer '.$NuestroToken, | ||
+ | </source> | ||
+ | |||
+ | https://medium.com/techcompose/create-rest-api-in-laravel-with-authentication-using-passport-133a1678a876 | ||
+ | |||
+ | https://medium.com/@bapunawarsaddam/rest-api-with-laravel-5-8-using-laravel-passport-53b5953798bb | ||
+ | |||
+ | https://stackoverflow.com/questions/47745884/laravel-passport-vs-jwt-vs-oauth2-vs-auth0 | ||
+ | |||
+ | https://medium.com/@devfelipe.mansilla/usando-graphql-con-laravel-446f0de02424 | ||
+ | |||
+ | =Webgrafia= | ||
+ | *http://wiki.netbeans.org/IniciandoseRESTful | ||
+ | |||
+ | *NetBeans soap: https://netbeans.org/kb/docs/websvc/jax-ws.html | ||
+ | *JAX-WS http://docs.oracle.com/javaee/6/tutorial/doc/bnayl.html | ||
+ | *JAX-RS http://docs.oracle.com/javaee/6/tutorial/doc/giepu.html | ||
+ | *http://www.java2blog.com/2013/03/soap-web-service-tutorial.html | ||
+ | |||
+ | |||
+ | http://frikibloggeo.blogspot.com/2017/01/crear-un-web-service-api-rest-con-php-y.html | ||
+ | |||
+ | |||
+ | = XML = | ||
+ | En aquest apartat es veurà com utilitzar XML per guardar dades des de un servidor PHP. | ||
+ | Exemple de XML: | ||
+ | <source lang="xml"> | ||
+ | Fitxer aules.xml: | ||
+ | <aules> | ||
+ | <aula> | ||
+ | <nom>205</nom> | ||
+ | <subxarxa>172.16.205.0</subxarxa> | ||
+ | <mascara>24</mascara> | ||
+ | <estatinicial>denega</estatinicial> | ||
+ | <estatactual>filtra</estatactual> | ||
+ | </aula> | ||
+ | <aula> | ||
+ | <nom>206</nom> | ||
+ | <subxarxa>172.16.206.0</subxarxa> | ||
+ | <mascara>24</mascara> | ||
+ | <estatinicial>denega</estatinicial> | ||
+ | <estatactual>denega</estatactual> | ||
+ | </aula> | ||
+ | </aules> | ||
+ | </source> | ||
+ | Per representar aquest fitxer com a un arbre i poder-lo recòrrer s'utilitza la llibreria DOMDocument de PHP. | ||
+ | |||
+ | == Creació del Arbre XML == | ||
+ | Per crear una representació del fitxer anterior, primer s'ha de crear l'objecte DOMDocument i a continuació llegir el fitxer: | ||
+ | <source lang="php"> | ||
+ | $file = "files/aules.xml"; | ||
+ | $xmldom = new DOMDocument(); | ||
+ | $xmldom->load($file); | ||
+ | </source> | ||
+ | |||
+ | == Obtenir un element del arbre == | ||
+ | Es pot utilitzar la funció ''getElementsByTagName''. Exemple: | ||
+ | <source lang="php"> | ||
+ | $aules = $xmldom->getElementsByTagName("aula"); | ||
+ | </source> | ||
+ | |||
+ | == Recòrrer tots els elemens == | ||
+ | Podem recòrrer tots els element amb un foreach: | ||
+ | <source lang="php"> | ||
+ | $aules = $xmldom->getElementsByTagName("aula"); | ||
+ | foreach ($aules as $aula) { | ||
+ | $name = $aula->getElementsByTagName("nom")->item(0)->nodeValue; | ||
+ | $net = $aula->getElementsByTagName("subxarxa")->item(0)->nodeValue; | ||
+ | $mask = $aula->getElementsByTagName("mascara")->item(0)->nodeValue; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | == Afegir un nou element == | ||
+ | Per afegir un nou elment s'ha de crear un node nou i afegir tos els fills que es necessiti per crear el XML correcte. | ||
+ | Exemple: | ||
+ | <source lang="php"> | ||
+ | $auladom = $xmldom->createElement("aula"); | ||
+ | //creamos el nodo NOM con su valor $classroomname | ||
+ | $aulanomdom = $xmldom->createElement("nom"); | ||
+ | $domnode = $xmldom->createTextNode(strtolower($classroomName)); | ||
+ | $aulanomdom->appendChild($domnode); | ||
+ | $auladom->appendChild($aulanomdom); | ||
+ | |||
+ | //creamos el nodo NETWORK con su valor $network | ||
+ | $aulanetwork = $xmldom->createElement(XARXA_AULA_XML); | ||
+ | $domnode = $xmldom->createTextNode(strtolower($network)); | ||
+ | $aulanetwork->appendChild($domnode); | ||
+ | $auladom->appendChild($aulanetwork); | ||
+ | |||
+ | //creamos el nodo MASK con su valor $mask | ||
+ | $aulamask = $xmldom->createElement(MASK_AULA_XML); | ||
+ | $domnode = $xmldom->createTextNode(strtolower($mask)); | ||
+ | $aulamask->appendChild($domnode); | ||
+ | $auladom->appendChild($aulamask); | ||
+ | |||
+ | //creamos el nodo initial status con su valor $initialstatus | ||
+ | $aulastatus = $xmldom->createElement(INIT_AULA_XML); | ||
+ | $domnode = $xmldom->createTextNode(strtolower($initialstatus)); | ||
+ | $aulastatus->appendChild($domnode); | ||
+ | $auladom->appendChild($aulastatus); | ||
+ | |||
+ | //creamos el nodo current status con su valor $initialstatus | ||
+ | $aulacurrentstatus = $xmldom->createElement(CURRENT_AULA_XML); | ||
+ | $domnode = $xmldom->createTextNode(strtolower($initialstatus)); | ||
+ | $aulacurrentstatus->appendChild($domnode); | ||
+ | $auladom->appendChild($aulacurrentstatus); | ||
+ | |||
+ | //afegim el node aula a la llista de nodes | ||
+ | $root = $xmldom->documentElement; | ||
+ | $root->appendChild($auladom); | ||
+ | |||
+ | //guardem | ||
+ | $xmldom->save($filename); | ||
+ | </source> | ||
+ | Finalment, s'ha de guardar el dom resultant al fitxer per mantenir correctament els canvis. Es fa amb la funció ''save''. | ||
+ | |||
+ | == Esborrar un element == | ||
+ | Per esborrar un element, primer s'ha de cercar, després dir-li al pare que ens volem eliminar. Però també hem d'esborrar els fills!. | ||
+ | <source lang="php"> | ||
+ | //funció que esborra un node i els seus fills | ||
+ | function deleteNode($node) { | ||
+ | deleteChildren($node); | ||
+ | $parent = $node->parentNode; | ||
+ | $oldnode = $parent->removeChild($node); | ||
+ | } | ||
+ | |||
+ | //funció que esborra els fills d'un node | ||
+ | function deleteChildren($node) { | ||
+ | while (isset($node->firstChild)) { | ||
+ | deleteChildren($node->firstChild); | ||
+ | $node->removeChild($node->firstChild); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | //funció que cerca al XML un node amb el nom=$classroomname | ||
+ | function delete($classroomName){ | ||
+ | $aules = $xmldom->getElementsByTagName("aula"); | ||
+ | foreach ($aules as $aula) { | ||
+ | $name = $aula->getElementsByTagName("nom")->item(0)->nodeValue; | ||
+ | if (strcmp(strtolower($name), strtolower($classroomName)) == 0){ | ||
+ | deleteNode($aula); | ||
+ | $xmldom->save($this->filename); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | Finalment, s'ha de guardar el dom resultant al fitxer per mantenir correctament els canvis. Es fa amb la funció ''save''. | ||
+ | |||
+ | == Modificar un valor == | ||
+ | Per modificar un valor, primer es cerca i després es mira quin dels atributs es vol modificar: | ||
+ | <source lang="php"> | ||
+ | function setNewClassroomAttr($classroomName, $attr, $value) | ||
+ | { | ||
+ | $aules = $xmldom->getElementsByTagName("aula"); | ||
+ | foreach ($aules as $aula) { | ||
+ | $name = $aula->getElementsByTagName("nom")->item(0)->nodeValue; | ||
+ | if (strcmp(strtolower($name), strtolower($classroomName)) == 0){ | ||
+ | $aula->getElementsByTagName($attr)->item(0)->nodeValue = strtolower($value); | ||
+ | $this->xmldom->save($this->filename); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | Finalment, s'ha de guardar el dom resultant al fitxer per mantenir correctament els canvis. Es fa amb la funció ''save''. | ||
+ | |||
+ | Podeu trobar més informació a http://www.php.net/manual/en/class.domdocument.php | ||
+ | |||
+ | =Mashups= | ||
+ | |||
+ | Una remescla, també coneguda pel terme anglès '''mashup''', és una aplicació web híbrida que utilitza contingut d'altres aplicacions web per a crear un nou contingut complet, consumint serveis directament sempre a través del protocol http. | ||
+ | |||
+ | El contingut d'un mashup normalment prové de llocs web de tercers a través d'una interfície pública o utilitzant una API. Altres mètodes que constitueixen l'origen de les seves dades inclouen: sindicació web (RSS o Atom), screen scraping, etc. | ||
+ | |||
+ | Els mashup estan revolucionant el desenvolupament web de la mateixa manera que els weblogs han revolucionat la publicació en línia. Permeten que qualsevol combini, de forma innovadora, dades que existeixen en diferents pàgines web. Requereixen pocs coneixements tècnics, les API existents són senzilles i potents i els mashup són relativament fàcils de dissenyar. Els creadors de mashups són generalment gent innovadora que vol combinar de formes noves i creatives dades disponibles públicament. | ||
+ | |||
+ | ==API de Google Maps== | ||
+ | A continuació trobareu un llistat amb les funcions més interesant de la API de Googlem maps que podeu utilitzar per realitzar mashups. | ||
+ | |||
+ | Primer heu d'afegir la llibreria de google Maps: | ||
+ | <source lang="html"> | ||
+ | |||
+ | <script src="http://maps.googleapis.com/maps/api/js"></script> | ||
+ | |||
+ | </source> | ||
+ | |||
+ | Després heu de un contenidor per al mapa. | ||
+ | |||
+ | <source lang="html"> | ||
+ | <div id="googleMap" style="width:500px;height:380px;"></div> | ||
+ | </source> | ||
+ | |||
+ | |||
+ | Una vegada teniu el contenidor heu de crear el mapa. Per crea-lo necessiteu informar a l'API de google maps unes quantes propietats: | ||
+ | * '''center''': Indica on ha de centrar el mapa. S'ha de donar les coordenades de latitud i longitud. | ||
+ | * '''zoom''': Indica el nivel de ZOOM del mapa. Zomm = 0 mostra la terra sencera. | ||
+ | * '''mapTypeId''': Indica el tipus de Mapa a mostrar. Existeixen els següents tipus de mapa: ROADMAP, SATELLITE, HYBRID, TERRAIN. | ||
+ | |||
+ | Exemple de les propietats: | ||
+ | <source lang="php"> | ||
+ | var mapProp = { | ||
+ | center:new google.maps.LatLng(51.508742, -0.120850), | ||
+ | zoom: 7, | ||
+ | mapTypeId: google.maps.MapTypeId.ROADMAP | ||
+ | }; | ||
+ | </source> | ||
+ | |||
+ | Una vegada s'ha definit les propietats ja es pot crear el mapa i un listener: | ||
+ | <source lang="javascript"> | ||
+ | var map=new google.maps.Map(document.getElementById("googleMap"), mapProp); | ||
+ | google.maps.event.addDomListener(window, 'load', initialize); | ||
+ | </source> | ||
+ | |||
+ | Exemple de mapa centrat a londres: | ||
+ | <source lang="html"> | ||
+ | <!DOCTYPE html> | ||
+ | <html> | ||
+ | <head> | ||
+ | <script src="http://maps.googleapis.com/maps/api/js"></script> | ||
+ | <script> | ||
+ | function initialize() { | ||
+ | var mapProp = { | ||
+ | center:new google.maps.LatLng(51.508742,-0.120850), | ||
+ | zoom:5, | ||
+ | mapTypeId:google.maps.MapTypeId.ROADMAP | ||
+ | }; | ||
+ | var map=new google.maps.Map(document.getElementById("googleMap"),mapProp); | ||
+ | } | ||
+ | google.maps.event.addDomListener(window, 'load', initialize); | ||
+ | </script> | ||
+ | </head> | ||
+ | |||
+ | <body> | ||
+ | <div id="googleMap" style="width:500px;height:380px;"></div> | ||
+ | </body> | ||
+ | |||
+ | </html> | ||
+ | </source> | ||
+ | |||
+ | Bé, ja tenim creat el mapa. Potser ens interessa afegir alguna marca dintre del mapa. Aquestes marques s'anomenen '''overlays''' i poden ser de diferents tipus: | ||
+ | * '''Marker''' - Localitzacions úniques del mapa. Poden tenir icones personalitzats. | ||
+ | * '''Polyline''' - Series de línies rectes en el mapa | ||
+ | * '''Polygon''' - Series de línies rectes en el mapa pero la forma resultant ha d'estar tancada. | ||
+ | * '''Circle and Rectangle''' | ||
+ | * '''Info Windows''' - Mostra contingut dintre de popups. | ||
+ | * '''marques personalitzades''' | ||
+ | https://www.w3schools.com/graphics/google_maps_intro.asp | ||
+ | |||
+ | Exemples: | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | |||
+ | <div id="map" style="width:100%;height:500px"></div> | ||
+ | |||
+ | <script> | ||
+ | function myMap() { | ||
+ | var mapCanvas = document.getElementById("map"); | ||
+ | var myCenter = new google.maps.LatLng(51.508742,-0.120850); | ||
+ | var mapOptions = {center: myCenter, zoom: 5}; | ||
+ | var map = new google.maps.Map(mapCanvas,mapOptions); | ||
+ | var marker = new google.maps.Marker({ | ||
+ | position: myCenter, | ||
+ | animation: google.maps.Animation.BOUNCE | ||
+ | }); | ||
+ | marker.setMap(map); | ||
+ | } | ||
+ | </script> | ||
+ | |||
+ | <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBu-916DdpKAjTmJNIgngS6HL_kDIKU0aU&callback=myMap"></script> | ||
+ | </source> | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | <div id="map" style="width:100%;height:500px"></div> | ||
+ | |||
+ | <script> | ||
+ | function myMap() { | ||
+ | var mapCanvas = document.getElementById("map"); | ||
+ | var myCenter = new google.maps.LatLng(51.508742,-0.120850); | ||
+ | var mapOptions = {center: myCenter, zoom: 5}; | ||
+ | var map = new google.maps.Map(mapCanvas,mapOptions); | ||
+ | var marker = new google.maps.Marker({ | ||
+ | position: myCenter, | ||
+ | icon: "pinkball.png" | ||
+ | }); | ||
+ | marker.setMap(map); | ||
+ | } | ||
+ | </script> | ||
+ | <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBu-916DdpKAjTmJNIgngS6HL_kDIKU0aU&callback=myMap"></script> | ||
+ | </source> | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | </source> | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | </source> | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | </source> | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | </source> | ||
+ | |||
+ | <source lang="javascript"> | ||
+ | //basic: | ||
+ | var marker=new google.maps.Marker({ | ||
+ | position:myCenter, | ||
+ | }); | ||
+ | |||
+ | marker.setMap(map); | ||
+ | |||
+ | //Amb animació: | ||
+ | var marker=new google.maps.Marker({ | ||
+ | position:myCenter, | ||
+ | animation:google.maps.Animation.BOUNCE | ||
+ | }); | ||
+ | |||
+ | marker.setMap(map); | ||
+ | |||
+ | //amb una icona | ||
+ | var marker=new google.maps.Marker({ | ||
+ | position:myCenter, | ||
+ | icon:'pinkball.png' | ||
+ | }); | ||
+ | |||
+ | marker.setMap(map); | ||
+ | |||
+ | |||
+ | //amb un poligon | ||
+ | var myTrip = [stavanger,amsterdam,london,stavanger]; | ||
+ | var flightPath = new google.maps.Polygon({ | ||
+ | path:myTrip, | ||
+ | strokeColor:"#0000FF", | ||
+ | strokeOpacity:0.8, | ||
+ | strokeWeight:2, | ||
+ | fillColor:"#0000FF", | ||
+ | fillOpacity:0.4 | ||
+ | }); | ||
+ | |||
+ | //amb un cercle | ||
+ | var myCity = new google.maps.Circle({ | ||
+ | center:amsterdam, | ||
+ | radius:20000, | ||
+ | strokeColor:"#0000FF", | ||
+ | strokeOpacity:0.8, | ||
+ | strokeWeight:2, | ||
+ | fillColor:"#0000FF", | ||
+ | fillOpacity:0.4 | ||
+ | }); | ||
+ | |||
+ | //amb una finestra d'informacio | ||
+ | var infowindow = new google.maps.InfoWindow({ | ||
+ | content:"Hello World!" | ||
+ | }); | ||
+ | |||
+ | infowindow.open(map,marker); | ||
+ | </source> | ||
+ | |||
+ | També podem afegir un listener a un marker per, per exemple, obrir un infowindow quan es faci click en ell: | ||
+ | <source lnag="javascript"> | ||
+ | var infowindow = new google.maps.InfoWindow({ | ||
+ | content:"Hello World!" | ||
+ | }); | ||
+ | |||
+ | google.maps.event.addListener(marker, 'click', function() { | ||
+ | infowindow.open(map,marker); | ||
+ | }); | ||
+ | </source> | ||
+ | |||
+ | Exemple de posicionament d'un marker on l'usuari fa click i a més a més afegeix un infowindow: | ||
+ | <source lang="javascript"> | ||
+ | google.maps.event.addListener(map, 'click', function(event) { | ||
+ | placeMarker(event.latLng); | ||
+ | }); | ||
+ | |||
+ | function placeMarker(location) { | ||
+ | var marker = new google.maps.Marker({ | ||
+ | position: location, | ||
+ | map: map, | ||
+ | }); | ||
+ | var infowindow = new google.maps.InfoWindow({ | ||
+ | content: 'Latitude: ' + location.lat() + | ||
+ | '<br>Longitude: ' + location.lng() | ||
+ | }); | ||
+ | infowindow.open(map,marker); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Podeu trobar la referència complerta de la API de google maps [http://www.w3schools.com/googleapi/google_maps_ref.asp | aqui]. | ||
+ | |||
+ | APIS | ||
+ | https://github.com/toddmotto/public-apis/blob/master/README.md | ||
+ | |||
+ | == Com trobar les coordenades d'una ciutat == | ||
+ | Podeu utilitzar l'API de google per trobar les coordenades d'una ciutat. Pots fer-ho de dues maneres: | ||
+ | Exemple1: | ||
+ | <source lang="php"> | ||
+ | $address = 'india'; | ||
+ | $details_url = "http://maps.googleapis.com/maps/api/geocode/json?address=".$address."&sensor=falsecurl_init(); | ||
+ | curl_setopt($ch, CURLOPT_URL, $details_url); | ||
+ | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | ||
+ | $response = json_decode(curl_exec($ch), true); | ||
+ | |||
+ | // If Status Code is ZERO_RESULTS, OVER_QUERY_LIMIT, REQUEST_DENIED or INVALID_REQUEST | ||
+ | if ($response['status'] != 'OK') { | ||
+ | return null; | ||
+ | } | ||
+ | |||
+ | //print_r($response); | ||
+ | //print_r($response['results'][0]['geometry']['location']); | ||
+ | |||
+ | $latLng = $response['results'][0]['geometry']['location']; | ||
+ | |||
+ | $lat = $latLng['lat']; | ||
+ | $lng = $latLng['lng']; | ||
+ | </source> | ||
+ | |||
+ | Exemple2: | ||
+ | <source lang="php"> | ||
+ | $geocode_stats = file_get_contents("http://maps.googleapis.com/maps/api/geocode/json?address=india&sensor=false"); | ||
+ | |||
+ | $output_deals = json_decode($geocode_stats); | ||
+ | |||
+ | $latLng = $output_deals->results[0]->geometry->location; | ||
+ | |||
+ | $lat = $latLng->lat; | ||
+ | $lng = $latLng->lng; | ||
+ | </source> |
Revisió de 20:20, 14 març 2022
Contingut
Pràctica Web Services
- VideoTutorial SOAP: https://youtu.be/LIbP_pbwGZo
API: (siglas de ‘Application Programming Interface’) es un conjunto de reglas (código) y especificaciones que las aplicaciones pueden seguir para comunicarse entre ellas.
¿Qué es SOAP?
- Los servicios SOAP o mejor conocimos simplemente como Web Services.
- Son servicios que basan su comunicación bajo el protocolo SOAP (Simple Object Access Protocol)
según la Wiki "protocolo estándar que define cómo dos objetos en diferentes procesos pueden comunicarse por medio de intercambio de datos XML"
- Los servicios SOAP funcionan por lo general por el protocolo HTTP, aunque también FTP, POP3, TCP...
WSDL (Web Services Description Language) es un protocolo basado en XML que describe los accesos al Web Service. Podríamos decir que es el manual de operación del mismo.
VENTAJAS:
- Protocolo mucho más robusto, tiene un tipiado mucho más fuerte (XSD,DTD)
- Permite agregar metadatos mediante los atributos (cosa que JSON no tiene).
- Permite definir espacios de nombre, evitando la ambigüedad.
INCONVENIENTES:
- SOAP es un formato más pesado, tanto en tamaño como en procesamiento, pues los XML tiene que ser parseado a un árbol DOM resolver espacios de nombre (namespaces) antes de poder empezar a procesar el documento.
- Los XML además tienen métodos de validación muy potentes y ampliamente utilizados, a diferencia de JSON.
¿Qué es REST?
Hay que diferenciar dos conceptos:
REST (Representational State Transfer) es una arquitectura que se ejecuta sobre HTTP.
RESTful hace referencia a un servicio web que implementa la arquitectura REST.
REST es una tecnología mucho más flexible que transporta datos por medio del protocolo HTTP.
Este permite utilizar los diversos métodos que proporciona HTTP para comunicarse, como lo son GET, POST, PUT, DELETE, PATCH y a la vez, utiliza los códigos de respuesta nativos de HTTP (404,200,204,409).
VENTAJAS:
- REST es tan flexible que permite transmitir prácticamente cualquier tipo de datos: JSON principalmente, XML, Binarios (imágenes, documentos), Text, etc.
- JSON es interpretado de forma natural por JavaScript, lo que ha hecho que frameworks como Angular, React y VUE se aprovechen al máximo,
pues pueden enviar peticiones directas al servidor por medio de AJAX y obtener los datos de una forma nativa.
- JSON son considerablemente más livianos en peso y mucho más rápido en su procesamiento
Diferencias entre SOAP y API
https://www.oscarblancarteblog.com/2017/03/06/soap-vs-rest-2/
Descargar NUSOAP
https://github.com/pwnlabs/nusoap
FICHERO SERVER.PHP
<?php
require_once "./nusoap/lib/nusoap.php";
function getInfo() {
return "Info de los libros";
}
function getProd($categoria) {
if ($categoria == "libros") {
return join(",", array(
"El señor de los anillos",
"Los límites de la Fundación",
"The Rails Way"));
}
else {
return "No hay productos de esta categoria";
}
}
$server = new soap_server();
$server->configureWSDL("producto", "urn:producto");
$server->register("getProd", //nombre función
array("categoria" => "xsd:string"), //parametro de entrada
array("return" => "xsd:string"), //parametro de salida
"urn:producto", //namespace
"urn:producto#getProd", //accion SOAP
"rpc", //estilo
"encoded",
"Nos da una lista de productos de cada categoría");
$server->register("getInfo",
array(""),
array("return" => "xsd:string"),
"urn:producto",
"urn:producto#getInfo",
"rpc",
"encoded",
"Nos da Info ");
if(!isset($HTTP_RAW_POST_DATA)){ ///Datos POST sin tratar , En general, se debería utilizar php://input en lugar de $HTTP_RAW_POST_DATA.
$HTTP_RAW_POST_DATA = file_get_contents("php://input");
}
$server->service($HTTP_RAW_POST_DATA);
?>
Primer s'inclou el fitxer 'nusoap.php per poder accedir a la llibreria NuSOAP.
Després es defineix la funció getProd() i s'instancia un objecte de la classe soap_server.
Immediatament després s'utilitza el mètode 'register per afegir la funció getProd al servidor sopa i poder accedir a ella des de un client. És a dir, convertim la funció getProd en un servei web.
Segurament, en un escenari real, la funció getProd hauria de cercar en una Base de Dades la informació que s'ha d'enviar a l'usuari. Ara mateix, no volem complicar el codi en coses externes a SOAP.
Es poden registrar funcions addicionals en el servidor per per donar més funcionalitats a l'aplicació. El procés seria idèntic del descrit anteriorment.
Bàsicament és el mateix codi amb quatre canvis. El primer canvi que s'ha afegit és la crida a la funció configureWSDL().
Aquest mètode prepara al servidor per a que pugui generar un fitxer WSDL dels nostres serveis registrats. El primer paràmetre d'aquesta funció, és el nom del servei i el segon correspon a l'espai de noms del servei.
FICHERO CLIENTE.PHP
<?php
require_once "./nusoap/lib/nusoap.php";
$cliente = new nusoap_client("http://localhost/nusoap/client.php");
//$cliente = new nusoap_client("http://localhost/webservice/server.php?wsdl", 'wsdl');
//$cliente = new nusoap_client("./server.php?wsdl", true);
//si ocurre algún error al consumir el Web Service
if ($cliente->fault) {
$error = $cliente->getError();
if ($error) { // Hubo algun error
echo 'Error:' . $error;
//echo 'Error2:' . $error->faultactor;
//echo 'Error3:' . $error->faultdetail;faultstring
//echo 'Error: ' . $cliente->faultstring;
}
die();
}
$getProd = $cliente->call("getProd", array("categoria" => "libros"));
$getInfo = $cliente->call("getInfo");
echo "<h2>Libros</h2><pre>";
echo $getProd;
echo $getInfo;
echo "</pre>";
?>
Com va passar en el servidor, primer s'ha d'incloure la llibreria nusoap.php amb la directiva required_once.
Seguidament, es crea un nova instància d'un client soap amb la classe: nusoap_client.
El constructor necessita la localització del servidor soap al que s'ha de connectar. És a dir, del fitxer on es troba la creació del soap_server amb les funcions registrades.
La funció getError comprova si el client SOAP s'ha creat correctament i si no ha estat així, mostra un missatge d'error.
El mètode call() genera i envia un missatge SOAP de tipus petició (Request) a la funció o el mètode definit com a primer paràmetre. El segon paràmetre de la funció call() és un array associatiu del paràmetres que necessita el mètode servidor.
La propietat fault i el mètode getError() son utilitzat per comprovar i mostrar cualsevol error produït en la comunicació.
Ejemplo de consumir un Web Service SOAP desde servidor externo (Obtener Ip) https://ws.cdyne.com/ip2geo/ip2geo.asmx
require_once "./nusoap.php";
$url = "http://ws.cdyne.com/ip2geo/ip2geo.asmx?wsdl";
try {
''' $client = new SoapClient($url, 'wsdl' ); cambio la sentencia da error'''
$client=new nusoap_client($url,'wsdl');
$param=array('ipAddress'=>"210.45.151.101", 'licenseKey' => "0");
$result = $client->call('ResolveIP', $param);
print_r($result);
} catch ( SoapFault $e ) {
echo $e->getMessage();
}
echo PHP_EOL;
Ejemplo de consumir un Web Service SOAP de la universidad de Alicante desde el cliente.
La dirección que expone este Web Services es la siguiente: https://cvnet.cpd.ua.es/servicioweb/publicos/pub_gestdocente.asmx?wsdl, como puedes ver al final muestra un archivo WSDL, que es donde expone las interfaces que van a ser consumidas.
<?php
header('Content-Type: text/html; charset=ISO-8859-1');
require_once('lib/nusoap.php');
//Parámetros
$slengua = "C";
$scurso = "2011-12";
$scoddep = "B142";
$scodest = "";
//url del webservice
$wsdl="https://cvnet.cpd.ua.es/servicioweb/publicos/pub_gestdocente.asmx?wsdl";
//instanciando un nuevo objeto cliente para consumir el webservice
$client=new nusoap_client($wsdl,'wsdl');
//pasando los parámetros a un array
$param=array('plengua'=>$slengua, 'pcurso' => $scurso, 'pcoddep' => $scoddep, 'pcodest' => $scodest);
//llamando al método y pasándole el array con los parámetros
$resultado = $client->call('wsasidepto', $param);
//si ocurre algún error al consumir el Web Service
if ($client->fault) { // si
$error = $client->getError();
if ($error) { // Hubo algun error
//echo 'Error:' . $error;
//echo 'Error2:' . $error->faultactor;
//echo 'Error3:' . $error->faultdetail;faultstring
echo 'Error: ' . $client->faultstring;
}
die();
}
echo "<pre>";
//print_r($resultado);
$result=$resultado['wsasideptoResult']['ClaseAsiDepto'];
for($i=0;$i<=count($result);$i++){
echo $result[$i]['codasi']."<br>";
echo $result[$i]['nomasi']."<br>";
echo $result[$i]['enlaceasi']."<br>";
echo $result[$i]['codest']."<br>";
echo $result[$i]['nomest']."<br>";
echo "<br>"."<br>";
}
echo "</pre>";
?>
FICHERO TXT EN EL SERVIDOR
melon,
melocoton,
banana,
frambuesa
RECUPERA FICHERO MOSTRANDO DATOS
<?php
$curl = curl_init("http://localhost/frutas.txt"); //Inicia una nueva sesión cURL
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); //Define opciones para nuestra sesion cURL, si se quiere que el contenido que devuelve la página se almacene en una variable, se puede utilizar la opción CURLOPT_RETURNTRANSFER
$respuesta = curl_exec($curl); //Ejecuta la sesión cURL que se le pasa como parámetro.
$info = curl_getinfo($curl); //Obtiene información de la última transferencia
echo $respuesta;
echo $info;
if($info['http_code'] == 200){
$datos = explode (",", $respuesta);
echo "<h1>Frutas en mi tienda</h1>";
foreach ($datos as $key => $value) {
echo $key."->".$value . "<br>";
}
}
/* //ejemplo cargar una web en el php
$cliente = curl_init();
curl_setopt($cliente, CURLOPT_URL, "https://www.google.com/search?q=lamerce");
curl_exec($cliente);
curl_close($cliente);
*/
?>
Exercici Web Service SOAP
- Crea un servei web que permeti Sumar, Restar, Multiplicar i Dividir.
- Busca un servei web a internet que utilitzi SOAP. site: wsdl
- Crea un servei web que façi dos consultes a una base de dades que tingui informació.
- Crea una aplicació client en PHP que també utilitzi aquest servei amb wsdl.
API RESTFUL PHP
VIDEOTUTORIAL
curl o file_gets_contents()
-Para recuperar datos de una API, pueden usarse dos formas con curl o file_gets_contents()
Tenemos dos opciones, ¿Cúal es mejor?
file_get_contents()
- Es un simple destornillador. Ideal para simples solicitudes GET donde el encabezado, método de solicitud HTTP, tiempo de espera, cookies, redirecciones y otras cosas más complejas no importan.
- También se pueden usar para peticiones POST, pero habría que crear un contexto para ello (Ver esta contribución en el Manual de PHP).
- Es menos seguro que cURL y por eso viene desactivado por defecto en muchos entornos PHP.
cURL
- Es mucho más potente y para usos más avanzados.
- cURL es probablemente la librería de HTTP más ampliamente utilizada en el mundo de la programación. Originalmente fue codificado utilizando lenguaje C, y luego fue portado a muchos otros lenguajes.
- cURL puede manejar manipulaciones HTTP complicadas de manera elegante, como solicitudes HTTP asíncronas, informes de progreso, etc.
- El único problema de cURL es que requiere algún tiempo, varias horas al menos, para familiarizarse con sus funciones y estilo de codificación. Al ser una librería tan usada, la documentación y ejemplos de código en la red son abundantes.
¿Cuál es más rápido?
- Todas las pruebas que he leído hasta ahora indican que cURL es más rápido.
- El siguiente gráfico es el producto de una prueba entre diferentes métodos, publicada por Philip Norton en Quickest Way To Download A Web Page With PHP
https://es.stackoverflow.com/questions/81565/diferencias-entre-file-get-contents-y-curl
Antes hay que asegurarse que curl está instalado en nuestro server apache.
sudo apt-get install curl-php
sudo service apache2 restart
Instalar POSTMAN para hacer las pruebas
wget https://dl.pstmn.io/download/latest/linux64 -O postman.tar.gz
sudo tar -xzf postman.tar.gz -C /opt
rm postman.tar.gz
sudo ln -s /opt/Postman/Postman /usr/bin/postman
SERVIDOR
<?php
// La base de datos se llama blog, la tabla "posts" y sus atributos (title, status, content, user_id)
$connection=mysqli_connect('localhost','root','','blog1');
$request_method=$_SERVER["REQUEST_METHOD"];
switch($request_method)
{
case 'GET':
// Retrive Products
if(!empty($_GET["id"]))
{
$id=intval($_GET["id"]); //transforma en número entero
get_products($id);
}
else
{
get_products();
}
break;
case 'POST':
insert_product();
break;
case 'PUT':
// Update Product
$id=intval($_GET["id"]);
update_product($id);
break;
case 'DELETE':
// Delete Product
$id=intval($_GET["id"]);
delete_product($id);
break;
default:
// Invalid Request Method
header("HTTP/1.0 405 Method Not Allowed");
break;
}
function insert_product()
{
global $connection;
$title=$_REQUEST["title"];
$status=$_REQUEST["status"];
$content=$_REQUEST["content"];
$user_id=$_REQUEST["user_id"];
$query = "INSERT INTO posts (title, status, content, user_id) VALUES ('$title', '$status', '$content', '$user_id')";
if(mysqli_query($connection, $query))
{
$response=array(
'status' => 1,
'status_message' =>'Product Added Successfully.'
);
}
else
{
$response=array(
'status' => 0,
'status_message' =>'Product Addition Failed.'
);
}
header('Content-Type: application/json');
echo json_encode($response);
}
function get_products($id=0)
{
global $connection;
$query="SELECT * FROM posts";
if($id!= 0)
{
$query.=" WHERE id=".$id." LIMIT 1";
}
$response=array();
$result=mysqli_query($connection, $query);
while($row=mysqli_fetch_array($result))
{
$response[]=$row;
}
header('Content-Type: application/json');
echo json_encode($response);
}
function delete_product($id)
{
global $connection;
$query="DELETE FROM posts WHERE id=".$id;
if(mysqli_query($connection, $query))
{
$response=array(
'status' => 1,
'status_message' =>'Product Deleted Successfully.'
);
}
else
{
$response=array(
'status' => 0,
'status_message' =>'Product Deletion Failed.'
);
}
header('Content-Type: application/json');
echo json_encode($response);
}
function update_product($id)
{
//(title, status, content, user_id)
global $connection;
parse_str(file_get_contents("php://input"),$post_vars); //php://input es un flujo de sólo lectura que permite leer datos del cuerpo solicitado, por tanto $post_vars recibirá todos los datos(título, status,content,user_id).
$title=$post_vars["title"];
$status=$post_vars["status"];
$content=$post_vars["content"];
$user_id=$post_vars["user_id"];
$query="UPDATE posts SET title='{$title}', status='{$status}', content='{$content}', user_id='{$user_id}' WHERE id=".$id;
if(mysqli_query($connection, $query))
{
$response=array(
'status' => 1,
'status_message' =>'Product Updated Successfully.'
);
}
else
{
$response=array(
'status' => 0,
'status_message' =>'Product Updation Failed.'
);
}
header('Content-Type: application/json');
echo json_encode($response);
}
// Close database connection
mysqli_close($connection);
CLIENTE
/*************GET*************/
$url = 'http://localhost/api/server.php?id=1';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPGET, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$respuesta = curl_exec($ch);
print_r($respuesta); //respuesta
curl_close($ch);
$response_json=json_decode($respuesta, true);
print_r($response_json); //respuesta en JSON
/*************DELETE*************/
$url = 'http://localhost/api/server.php?id=2';
$ch = curl_init($url); //// abrimos la sesión cURL
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); // definimos la URL a la que hacemos la petición
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // recibimos la respuesta y la guardamos en una variable
$response_json = curl_exec($ch);
curl_close($ch); // recibimos la respuesta y la guardamos en una variable
$response=json_decode($response_json, true);
print_r($response);
/*************PUT*************/
$data=array(
'title' =>'Nuevo',
'status' => "enviado",
'content' => "10",
'user_id' =>'2'
);
$url = 'http://localhost/api/server.php?id=3';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$respuesta = curl_exec($ch);
curl_close($ch);
print_r($respuesta); //{"status":1,"status_message":"Product Updated Successfully."}
$response_json=json_decode($respuesta, true);
print_r($response_json); //Array ( [status] => 1 [status_message] => Product Updated Successfully. )
/*************POST*************/
$data=array(
'title' =>'Television',
'status' => "1000",
'content' => "10",
'user_id' =>'2'
);
$url = 'http://localhost/api/server.php';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true); // indicamos el tipo de petición: POST
// definimos cada uno de los parámetros
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); //curl_setopt($ch, CURLOPT_POSTFIELDS, "title=value1&status=value2&content=value3&user_id=5");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // recibimos la respuesta y la guardamos en una variable $ch
$respuesta= curl_exec($ch); //ejecutamos la sesión cUrl
curl_close($ch); // cerramos la sesión cURL
print_r($response_json); //mostramos datos {"status":1,"status_message":"Product Added Successfully."}
También se pueden hacer llamadas al servidor mediante el terminal..
//POST
curl -d "title=value1&status=value2&content=value3&user_id=5" http://localhost/api1/server.php
curl --data "title=value1&status=value2&content=value3&user_id=value4" http://localhost/api1/server.php
//DELETE
curl -X "DELETE" http://localhost/api1/server.php?id=1
//GET
curl --data "title=value1&si -H "Accept: application/json" -H "Content-Type: application/json" -X GET http://localhost/api1/server.php?id=1
http://frikibloggeo.blogspot.com/2017/01/crear-un-web-service-api-rest-con-php-y.html
EXERCICIS
- Familiarizarse con cURL y crear una API con una base de datos y probar el funcionamiento de POSTMAN
- Encontrar como hacer un GET por consola del cURL, también probar cómo ejecutar en el terminal del servidor estos comandos.
https://www.apptha.com/blog/how-to-build-a-rest-api-using-php/
https://www.tmb.cat/es/sobre-tmb/herramientas-para-desarrolladores/datos-tiempo-real
https://github.com/public-apis/public-apis/blob/master/README.md
API RESTFUL LARAVEL
VIDEOTUTORIAL
Interfaz Rutas API
https://styde.net/como-documentar-una-api-en-laravel-usando-swagger/
https://github.com/mpociot/documentarian
1. Crearemos la migración tareas, que se encuentra en database/migrations
php artisan make:migration create_tareas_table --create="tareas"
public function up()
{
Schema::create('tareas', function (Blueprint $table) {
$table->increments('id');
$table->string('name',20);
$table->string('description',50);
$table->string('content',100);
});
}
2. Creamos el modelo
php artisan make:model Tarea
class Tarea extends Model
{
protected $fillable = ['name', 'description', 'content'];
public $timestamps = false; //indicamos que no queremos usar update_at y create_at en la base de datos.
}
3. Creamos el controlador TareasController
php artisan make:controller TareasController
use App\Tarea; //añadimos el modelo
class TareasController extends Controller
{
public function index(Request $request)
{
$task = Tarea::all();
return $task;
//Esta función nos devolvera todas las tareas que tenemos en nuestra BD
}
public function store(Request $request)
{
$task = new Tarea();
$task->name = $request->name;
$task->description = $request->description;
$task->content = $request->content;
$task->save();
//Esta función guardará las tareas que enviaremos
return response()->json([
"message" => "Tarea almacenada con éxito"
], 201);
}
public function show(Request $request)
{
$task = Tarea::findOrFail($request->id);
return $task;
//Esta función devolverá los datos de una tarea que hayamos seleccionado para cargar el formulario con sus datos
}
public function update(Request $request)
{
$task = Tarea::findOrFail($request->id);
$task->name = $request->name;
$task->description = $request->description;
$task->content = $request->content;
$task->save();
return $task;
//Esta función actualizará la tarea que hayamos seleccionado
}
public function destroy(Request $request)
{
$task = Tarea::destroy($request->id); //task tienen el id que se ha borrado
return response()->json([
"message" => "Tarea con id =" . $task . " ha sido borrado con éxito"
], 201);
//Esta función obtendra el id de la tarea que hayamos seleccionado y la borrará de nuestra BD
}
4.Para la creación de las rutas lo añadimos en routes->api, en vez de routes->web
Route::get('/tareas', 'TareasController@index');
Route::put('/tareas/actualizar/{id}', 'TareasController@update');
Route::post('/tareas/guardar', 'TareasController@store');
Route::delete('/tareas/borrar/{id}', 'TareasController@destroy');
Route::get('/tareas/buscar/{id}', 'TareasController@show');
Para listar las rutas: php artisan route:list -v
Ahora vamos hacer pruebas desde POSTMAN
IMPORTANTE: fijaos que la ruta es .../public/api/...
Para GET -> index
Para POST -> create
Aspecto interesantes del post:
- x-www-form-urlencoded Si desea enviar texto simple / datos ASCII, este es el valor predeterminado. Esta codificación es la misma que la utilizada en los parámetros de URL. Solo necesita ingresar los pares clave/valor y Postman codificará las claves y los valores correctamente
- form-data: Pero si tiene que enviar texto no ASCII o datos binarios grandes, los datos del formulario son para eso.
- Raw si desea enviar texto sin formato o JSON o cualquier otro tipo de cadena. Como su nombre indica, Postman envía sus datos de cadena sin procesar tal como están sin modificaciones. El tipo de datos que está enviando se puede configurar utilizando el encabezado de tipo de contenido del menú desplegable.
- Binario se puede usar cuando desea adjuntar datos no textuales a la solicitud, por ejemplo: un archivo de video / audio, imágenes o cualquier otro archivo de datos binarios.
Para GET para obtener con id específico -> show
Para PUT -> update
Para DELETE -> delete
https://www.nigmacode.com/laravel/Crear-API-REST-con-Laravel
DOCUMENTAR API SWAGGER
Instalamos el paquete swagger
composer require "darkaonline/l5-swagger:6.*"
Instalamos el paquete para las anotaciones que va relacionado
composer require zircote/swagger-php
publicamos la vista y configuración del paquete
php artisan vendor:publish --provider "L5Swagger\L5SwaggerServiceProvider"
podemos comprobar cómo han quedado las rutas y vemos que ha añadido "api/documentation"
php artisan route:list
luego añadimos las anotaciones antes de cada función
@OA\Info
@OA\License
@OA\Tag
@OA\Server
@OA\SecurityScheme
@OA\RequestBody
@OA\Property
@OA\Get
@OA\Post
@OA\Put
https://zircote.github.io/swagger-php/Getting-started.html#write-annotations
y generamos
php artisan l5-swagger:generate
https://styde.net/como-documentar-una-api-en-laravel-usando-swagger/
API RESTFUL LARAVEL - PASSPORT TOKEN
VIDEOTUTORIAL:
1. Creamos proyecto
composer create-project --prefer-dist laravel/laravel blog
2. Descargamos paquete Passport
composer require laravel/passport
3. Luego en config/app.php añadimos el servido de Provider
/*Añadimos providers*/
'providers' =>[
Laravel\Passport\PassportServiceProvider::class,
],
4. Después de añadir el provider, generamos la migración php artisan migrate
5. A continuación, tenemos que instalar "passport" en el proyecto y esto generará los Tokens php artisan passport:install
6. Añadimos HasApiTokens en ruta app/User.php
<?php
namespace App;
use Laravel\Passport\HasApiTokens; /*añadimos Clase HasApiTokens*/
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use HasApiTokens, Notifiable; /*añadimos HasApiTokens*/
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];}
7. Añadimos linea Passport::routes(); en ruta app/Providers/AuthServiceProvider.php
<?php
namespace App\Providers;
use Laravel\Passport\Passport; /*Añadimos Clase Passport*/
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
Passport::routes(); /*añadimos esta linea*/
}
}
8. Añadimos que también nos vamos autentificar en la API en config/auth.php
<?php
return ['guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [ /*añadimos linea api*/
'driver' => 'passport',
'provider' => 'users',
],
],
9. Añadimos rutas en Routes->api.php
Route::post('login', 'API\UserController@login');
Route::post('register', 'API\UserController@register');
Route::group(['middleware' => 'auth:api'], function () {
Route::get('details', 'API\UserController@details');
Route::get('logout', 'API\UserController@logout');
});
10. Añadimos nuestras funciones en el controlador dentro de la carpeta API
php artisan make:controller API\UserController
<?php
namespace App\Http\Controllers\API;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\User;
use Illuminate\Support\Facades\Auth;
use Validator;
class UserController extends Controller
{
public $successStatus = 200;
/**
* login api
*
* @return \Illuminate\Http\Response
*/
public function login()
{
if (Auth::attempt(['email' => request('email'), 'password' => request('password')])) {
$user = Auth::user();
$success['token'] = $user->createToken('MyApp')->accessToken;
return response()->json(['success' => $success], $this->successStatus);
} else {
return response()->json(['error' => 'Unauthorised'], 401);
}
}
/**
* Register api
*
* @return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
'c_password' => 'required|same:password',
]);
if ($validator->fails()) {
return response()->json(['error' => $validator->errors()], 401);
}
$input = $request->all();
$input['password'] = bcrypt($input['password']);
$user = User::create($input);
$success['token'] = $user->createToken('MyApp')->accessToken;
$success['name'] = $user->name;
return response()->json(['success' => $success], $this->successStatus);
}
/**
* details api
*
* @return \Illuminate\Http\Response
*/
public function details()
{
$user = Auth::user();
return response()->json(['success' => $user], $this->successStatus);
}
public function logout(Request $request)
{
$isUser = $request->user()->token()->revoke();
if($isUser){
$success['message'] = "Successfully logged out.";
return response()->json(['success' => $isUser], $this->successStatus);
}
else{
return response()->json(['error' => 'Unauthorised'], 401);
}
}
}
1. Pruebas Postman.
REGISTER
localhost/api/public/api/register -> método POST
name
email
password
c_password
LOGIN
localhost/api/public/api/login -> método POST
email
password
DETAILS
localhost/api/public/api/details-> método GET
'Authorization' => 'Bearer '.$NuestroToken,
LOGOUT
localhost/api/public/api/logout-> método GET
'accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded'
'Authorization' => 'Bearer '.$NuestroToken,
https://medium.com/@bapunawarsaddam/rest-api-with-laravel-5-8-using-laravel-passport-53b5953798bb
https://stackoverflow.com/questions/47745884/laravel-passport-vs-jwt-vs-oauth2-vs-auth0
https://medium.com/@devfelipe.mansilla/usando-graphql-con-laravel-446f0de02424
Webgrafia
- NetBeans soap: https://netbeans.org/kb/docs/websvc/jax-ws.html
- JAX-WS http://docs.oracle.com/javaee/6/tutorial/doc/bnayl.html
- JAX-RS http://docs.oracle.com/javaee/6/tutorial/doc/giepu.html
- http://www.java2blog.com/2013/03/soap-web-service-tutorial.html
http://frikibloggeo.blogspot.com/2017/01/crear-un-web-service-api-rest-con-php-y.html
XML
En aquest apartat es veurà com utilitzar XML per guardar dades des de un servidor PHP. Exemple de XML:
Fitxer aules.xml:
<aules>
<aula>
<nom>205</nom>
<subxarxa>172.16.205.0</subxarxa>
<mascara>24</mascara>
<estatinicial>denega</estatinicial>
<estatactual>filtra</estatactual>
</aula>
<aula>
<nom>206</nom>
<subxarxa>172.16.206.0</subxarxa>
<mascara>24</mascara>
<estatinicial>denega</estatinicial>
<estatactual>denega</estatactual>
</aula>
</aules>
Per representar aquest fitxer com a un arbre i poder-lo recòrrer s'utilitza la llibreria DOMDocument de PHP.
Creació del Arbre XML
Per crear una representació del fitxer anterior, primer s'ha de crear l'objecte DOMDocument i a continuació llegir el fitxer:
$file = "files/aules.xml";
$xmldom = new DOMDocument();
$xmldom->load($file);
Obtenir un element del arbre
Es pot utilitzar la funció getElementsByTagName. Exemple:
$aules = $xmldom->getElementsByTagName("aula");
Recòrrer tots els elemens
Podem recòrrer tots els element amb un foreach:
$aules = $xmldom->getElementsByTagName("aula");
foreach ($aules as $aula) {
$name = $aula->getElementsByTagName("nom")->item(0)->nodeValue;
$net = $aula->getElementsByTagName("subxarxa")->item(0)->nodeValue;
$mask = $aula->getElementsByTagName("mascara")->item(0)->nodeValue;
}
Afegir un nou element
Per afegir un nou elment s'ha de crear un node nou i afegir tos els fills que es necessiti per crear el XML correcte. Exemple:
$auladom = $xmldom->createElement("aula");
//creamos el nodo NOM con su valor $classroomname
$aulanomdom = $xmldom->createElement("nom");
$domnode = $xmldom->createTextNode(strtolower($classroomName));
$aulanomdom->appendChild($domnode);
$auladom->appendChild($aulanomdom);
//creamos el nodo NETWORK con su valor $network
$aulanetwork = $xmldom->createElement(XARXA_AULA_XML);
$domnode = $xmldom->createTextNode(strtolower($network));
$aulanetwork->appendChild($domnode);
$auladom->appendChild($aulanetwork);
//creamos el nodo MASK con su valor $mask
$aulamask = $xmldom->createElement(MASK_AULA_XML);
$domnode = $xmldom->createTextNode(strtolower($mask));
$aulamask->appendChild($domnode);
$auladom->appendChild($aulamask);
//creamos el nodo initial status con su valor $initialstatus
$aulastatus = $xmldom->createElement(INIT_AULA_XML);
$domnode = $xmldom->createTextNode(strtolower($initialstatus));
$aulastatus->appendChild($domnode);
$auladom->appendChild($aulastatus);
//creamos el nodo current status con su valor $initialstatus
$aulacurrentstatus = $xmldom->createElement(CURRENT_AULA_XML);
$domnode = $xmldom->createTextNode(strtolower($initialstatus));
$aulacurrentstatus->appendChild($domnode);
$auladom->appendChild($aulacurrentstatus);
//afegim el node aula a la llista de nodes
$root = $xmldom->documentElement;
$root->appendChild($auladom);
//guardem
$xmldom->save($filename);
Finalment, s'ha de guardar el dom resultant al fitxer per mantenir correctament els canvis. Es fa amb la funció save.
Esborrar un element
Per esborrar un element, primer s'ha de cercar, després dir-li al pare que ens volem eliminar. Però també hem d'esborrar els fills!.
//funció que esborra un node i els seus fills
function deleteNode($node) {
deleteChildren($node);
$parent = $node->parentNode;
$oldnode = $parent->removeChild($node);
}
//funció que esborra els fills d'un node
function deleteChildren($node) {
while (isset($node->firstChild)) {
deleteChildren($node->firstChild);
$node->removeChild($node->firstChild);
}
}
//funció que cerca al XML un node amb el nom=$classroomname
function delete($classroomName){
$aules = $xmldom->getElementsByTagName("aula");
foreach ($aules as $aula) {
$name = $aula->getElementsByTagName("nom")->item(0)->nodeValue;
if (strcmp(strtolower($name), strtolower($classroomName)) == 0){
deleteNode($aula);
$xmldom->save($this->filename);
}
}
}
Finalment, s'ha de guardar el dom resultant al fitxer per mantenir correctament els canvis. Es fa amb la funció save.
Modificar un valor
Per modificar un valor, primer es cerca i després es mira quin dels atributs es vol modificar:
function setNewClassroomAttr($classroomName, $attr, $value)
{
$aules = $xmldom->getElementsByTagName("aula");
foreach ($aules as $aula) {
$name = $aula->getElementsByTagName("nom")->item(0)->nodeValue;
if (strcmp(strtolower($name), strtolower($classroomName)) == 0){
$aula->getElementsByTagName($attr)->item(0)->nodeValue = strtolower($value);
$this->xmldom->save($this->filename);
}
}
}
Finalment, s'ha de guardar el dom resultant al fitxer per mantenir correctament els canvis. Es fa amb la funció save.
Podeu trobar més informació a http://www.php.net/manual/en/class.domdocument.php
Mashups
Una remescla, també coneguda pel terme anglès mashup, és una aplicació web híbrida que utilitza contingut d'altres aplicacions web per a crear un nou contingut complet, consumint serveis directament sempre a través del protocol http.
El contingut d'un mashup normalment prové de llocs web de tercers a través d'una interfície pública o utilitzant una API. Altres mètodes que constitueixen l'origen de les seves dades inclouen: sindicació web (RSS o Atom), screen scraping, etc.
Els mashup estan revolucionant el desenvolupament web de la mateixa manera que els weblogs han revolucionat la publicació en línia. Permeten que qualsevol combini, de forma innovadora, dades que existeixen en diferents pàgines web. Requereixen pocs coneixements tècnics, les API existents són senzilles i potents i els mashup són relativament fàcils de dissenyar. Els creadors de mashups són generalment gent innovadora que vol combinar de formes noves i creatives dades disponibles públicament.
API de Google Maps
A continuació trobareu un llistat amb les funcions més interesant de la API de Googlem maps que podeu utilitzar per realitzar mashups.
Primer heu d'afegir la llibreria de google Maps:
<script src="http://maps.googleapis.com/maps/api/js"></script>
Després heu de un contenidor per al mapa.
<div id="googleMap" style="width:500px;height:380px;"></div>
Una vegada teniu el contenidor heu de crear el mapa. Per crea-lo necessiteu informar a l'API de google maps unes quantes propietats:
- center: Indica on ha de centrar el mapa. S'ha de donar les coordenades de latitud i longitud.
- zoom: Indica el nivel de ZOOM del mapa. Zomm = 0 mostra la terra sencera.
- mapTypeId: Indica el tipus de Mapa a mostrar. Existeixen els següents tipus de mapa: ROADMAP, SATELLITE, HYBRID, TERRAIN.
Exemple de les propietats:
var mapProp = {
center:new google.maps.LatLng(51.508742, -0.120850),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
Una vegada s'ha definit les propietats ja es pot crear el mapa i un listener:
var map=new google.maps.Map(document.getElementById("googleMap"), mapProp);
google.maps.event.addDomListener(window, 'load', initialize);
Exemple de mapa centrat a londres:
<!DOCTYPE html>
<html>
<head>
<script src="http://maps.googleapis.com/maps/api/js"></script>
<script>
function initialize() {
var mapProp = {
center:new google.maps.LatLng(51.508742,-0.120850),
zoom:5,
mapTypeId:google.maps.MapTypeId.ROADMAP
};
var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="googleMap" style="width:500px;height:380px;"></div>
</body>
</html>
Bé, ja tenim creat el mapa. Potser ens interessa afegir alguna marca dintre del mapa. Aquestes marques s'anomenen overlays i poden ser de diferents tipus:
- Marker - Localitzacions úniques del mapa. Poden tenir icones personalitzats.
- Polyline - Series de línies rectes en el mapa
- Polygon - Series de línies rectes en el mapa pero la forma resultant ha d'estar tancada.
- Circle and Rectangle
- Info Windows - Mostra contingut dintre de popups.
- marques personalitzades
https://www.w3schools.com/graphics/google_maps_intro.asp
Exemples:
<div id="map" style="width:100%;height:500px"></div>
<script>
function myMap() {
var mapCanvas = document.getElementById("map");
var myCenter = new google.maps.LatLng(51.508742,-0.120850);
var mapOptions = {center: myCenter, zoom: 5};
var map = new google.maps.Map(mapCanvas,mapOptions);
var marker = new google.maps.Marker({
position: myCenter,
animation: google.maps.Animation.BOUNCE
});
marker.setMap(map);
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBu-916DdpKAjTmJNIgngS6HL_kDIKU0aU&callback=myMap"></script>
<div id="map" style="width:100%;height:500px"></div>
<script>
function myMap() {
var mapCanvas = document.getElementById("map");
var myCenter = new google.maps.LatLng(51.508742,-0.120850);
var mapOptions = {center: myCenter, zoom: 5};
var map = new google.maps.Map(mapCanvas,mapOptions);
var marker = new google.maps.Marker({
position: myCenter,
icon: "pinkball.png"
});
marker.setMap(map);
}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBu-916DdpKAjTmJNIgngS6HL_kDIKU0aU&callback=myMap"></script>
//basic:
var marker=new google.maps.Marker({
position:myCenter,
});
marker.setMap(map);
//Amb animació:
var marker=new google.maps.Marker({
position:myCenter,
animation:google.maps.Animation.BOUNCE
});
marker.setMap(map);
//amb una icona
var marker=new google.maps.Marker({
position:myCenter,
icon:'pinkball.png'
});
marker.setMap(map);
//amb un poligon
var myTrip = [stavanger,amsterdam,london,stavanger];
var flightPath = new google.maps.Polygon({
path:myTrip,
strokeColor:"#0000FF",
strokeOpacity:0.8,
strokeWeight:2,
fillColor:"#0000FF",
fillOpacity:0.4
});
//amb un cercle
var myCity = new google.maps.Circle({
center:amsterdam,
radius:20000,
strokeColor:"#0000FF",
strokeOpacity:0.8,
strokeWeight:2,
fillColor:"#0000FF",
fillOpacity:0.4
});
//amb una finestra d'informacio
var infowindow = new google.maps.InfoWindow({
content:"Hello World!"
});
infowindow.open(map,marker);
També podem afegir un listener a un marker per, per exemple, obrir un infowindow quan es faci click en ell:
var infowindow = new google.maps.InfoWindow({
content:"Hello World!"
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.open(map,marker);
});
Exemple de posicionament d'un marker on l'usuari fa click i a més a més afegeix un infowindow:
google.maps.event.addListener(map, 'click', function(event) {
placeMarker(event.latLng);
});
function placeMarker(location) {
var marker = new google.maps.Marker({
position: location,
map: map,
});
var infowindow = new google.maps.InfoWindow({
content: 'Latitude: ' + location.lat() +
'<br>Longitude: ' + location.lng()
});
infowindow.open(map,marker);
}
Podeu trobar la referència complerta de la API de google maps | aqui.
APIS https://github.com/toddmotto/public-apis/blob/master/README.md
Com trobar les coordenades d'una ciutat
Podeu utilitzar l'API de google per trobar les coordenades d'una ciutat. Pots fer-ho de dues maneres: Exemple1:
$address = 'india';
$details_url = "http://maps.googleapis.com/maps/api/geocode/json?address=".$address."&sensor=falsecurl_init();
curl_setopt($ch, CURLOPT_URL, $details_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = json_decode(curl_exec($ch), true);
// If Status Code is ZERO_RESULTS, OVER_QUERY_LIMIT, REQUEST_DENIED or INVALID_REQUEST
if ($response['status'] != 'OK') {
return null;
}
//print_r($response);
//print_r($response['results'][0]['geometry']['location']);
$latLng = $response['results'][0]['geometry']['location'];
$lat = $latLng['lat'];
$lng = $latLng['lng'];
Exemple2:
$geocode_stats = file_get_contents("http://maps.googleapis.com/maps/api/geocode/json?address=india&sensor=false");
$output_deals = json_decode($geocode_stats);
$latLng = $output_deals->results[0]->geometry->location;
$lat = $latLng->lat;
$lng = $latLng->lng;