Du är en PHP-utvecklare. Jag förstår. Det är jag också. Min resa till PHP tog inte den normala vägen som de flesta PHP-utvecklare går i sin jakt på det perfekta programmeringsspråket. Jag började ursprungligen som Javautvecklare och tillbringade ungefär 10 år i det landet. Jag var en av de där inbitna Javautvecklarna som när PHP introducerades i en konversation började jag prata om saker som företag, skalbarhet och annat trams.
Jag började arbeta på ett open source-projekt som behövde en social webb front-end för ungefär 5 år sedan och teamet behövde välja ett programmeringsspråk för webbplatsen. Jag utforskade Java och de flesta andra språk men bestämde mig för PHP av flera skäl. Det var svårt att svälja min stolthet och börja koda i PHP, men det som hände under det projektet var inget annat än ett mirakel. Jag blev förälskad i språket och började använda det i så många projekt jag kunde hitta samtidigt som jag lämnade mina Java-rötter i damm. PHP har tjänat mig väl under de senaste fem åren, men jag letade fortfarande efter den heliga graalen av ett programmeringsspråk som är snabbt att utveckla i, som har stöd från företag, som är prestanda- och skalbart och som samtidigt har en stark utvecklargemenskap. Jag tror att Node.js uppfyller alla mina krav samtidigt som det är ett snabbt växande och utvecklande språk.
Det första du måste förstå är att Node.js inte bara är för hipsterutvecklare eller tidiga användare. Det används av några av de mest välbesökta webbplatserna på Internet i dag och fortsätter att vinna utvecklarnas hjärtan och sinnen. Det är verkligen vid en punkt där du kan lita på det även för de mest komplicerade systemen.
Node.js är JavaScript##
Om du tror att du måste lära dig ett helt nytt språk för att vara produktiv med Node.js har du förmodligen fel. De flesta utvecklare är redan bekanta med JavaScript och det är det språk och den semantik som du kommer att arbeta med när du kodar i Node.js. Faktum är att en artikel som nyligen publicerades av Red Monk som försöker förstå github-projekt för att fastställa de mest populära språken har JavaScript som kung. De tre främsta språken är följande:
- JavaScript
- Java
- PHP
Med tanke på JavaScript:s popularitet och dess utbredda användning i vår bransch, om du inte redan är bekant med det är det förmodligen dags att sätta dig ner och börja lära dig det.
Om Node.js bara använder JavaScript, vad exakt är det då?##
I ett nötskal är Node.js en plattform för aktiviteter på serversidan. Den använder programmeringsspråket Javascript och har en uppsjö av bibliotek som finns tillgängliga som npm-moduler. Du kan tänka på dessa npm-moduler som biblioteksberoenden som kan vara nöjda med Composer om du kommer från PHP-land. Faktum är att standardhanteringssystemet för beroenden för PHP (Composer) inspirerades av Node.js enligt den officiella webbplatsen. Chansen är stor att om du behöver lite funktionalitet och inte är sugen på att skriva all kod själv, finns det en npm-modul tillgänglig som redan tillhandahåller de funktioner du letar efter.
Node-applikationer implementeras normalt när du behöver maximera effektiviteten genom att använda icke-blockerande I/O och asynkrona händelser. Ett problem som PHP-utvecklare bör känna till är att Node.js-programmen körs i en enda tråd. Backend Node.js-kod använder dock flera trådar för operationer som nätverks- och filåtkomst. Med tanke på detta är Node perfekt för applikationer där man vill ha en upplevelse i nästan realtid.
Kom igång med ett exempelprojekt###
För återstoden av det här blogginlägget kommer jag att visa dig hur du kan komma igång med Node.js när du kommer från en PHP-bakgrund. Det exempelprogram som vi kommer att skriva är en enkel backend-tjänst som kommer att tillhandahålla platsen för varje Walmart-butik. Jag valde Walmart för det här exemplet eftersom det helt enkelt är den heliga graalen för alla varuhus. Om Walmart inte har det behöver du det inte.
I slutet av det här blogginlägget kommer du att se hur snabbt och enkelt det är att skapa ett REST-baserat API med hjälp av Node.js som drivs av den populära MongoDB-databasen. Jag valde detta REST-baserade exempel eftersom skapandet av ett backend API snabbt har blivit ett vanligt användningsområde i de flesta moderna applikationer.
Jag hade ursprungligen planerat att skapa samma applikation i både PHP och Node.js för att underlätta övergången för dig, men för att täcka alla de olika ramverken och sätten att skapa REST-baserade tjänster i PHP, skulle det motivera en hel bok och kan helt enkelt inte täckas i ett enda blogginlägg. Jag funderade då på att bara använda ramverket Laravel eftersom det fortsätter att växa i popularitet. Jag skulle dock fortfarande bara nå en fjärdedel av PHP-utvecklarna. Personligen är mitt favoritramverk CodeIgniter, men det förlorar snabbt mark och representerar nu bara mindre än 8 % av PHP-utvecklarna. Sitepoint publicerade nyligen en artikel som diskuterar just detta och ger följande diagram som visar vilka ramverk som är mest lovande för 2014.
Med tanke på de stora skillnaderna i hur man konfigurerar databasanslutningar och skapar REST-tjänster för varje ramverk, kommer jag att förutsätta att du vet hur du ska göra detta för ditt ramverk i PHP och kommer istället att fokusera bara på Node.js-kod.
Skapa vår Node.js-applikation##
För resten av det här inlägget kommer vi att skapa applikationen Walmart locator med hjälp av LoopBack API-ramverket från StrongLoop. Som en extra bonus kommer jag att gå igenom installationen av Node.js på OSX. Så ta din kopp kaffe, luta dig tillbaka, slappna av och låt oss börja jobba.
Steg 1: Installera Node.js##
Det enklaste sättet att installera Node.js är via ett av de tillgängliga binära paketen som finns tillgängliga för de flesta operativsystem. Rikta din webbläsare till följande URL och ladda ner rätt för ditt operativsystem:
http://nodejs.org/download/
När sidan laddas bör du se följande:
Om du använder Mac OSX klickar du på den universella .pkg-filen. Detta kommer att spara installationsprogrammet på din lokala dator. När filen har laddats ner startar du installationsprogrammet genom att dubbelklicka på den .pkg-fil som har laddats ner och du kommer att få se installationsdialogrutan:
Fullfölj installationsprocessen genom att använda alla standardinställningar och klicka slutligen på stängningsknappen för att avsluta programmet när installationen har lyckats. Ganska enkelt, eller hur?
Steg 2: Installera LoopBack med NPM
Nu när vi har Node.js installerat på vårt lokala system vill vi installera LoopBack-paketen som tillhandahålls av StrongLoop. LoopBack är ett API-ramverk med öppen källkod som tillhandahåller funktionalitet som kommer att göra ditt liv enklare när du börjar lära dig att skriva och distribuera programvara skriven i Node.js.
För att installera LoopBack kommer vi att använda kommandot npm som är en del av kärnan i Node.js-distributionen. NPM är den officiella pakethanteraren för att installera bibliotek eller moduler som dina applikationer är beroende av. Med tanke på att det här inlägget är skrivet för PHP-utvecklare är ett enkelt sätt att tänka på NPM-moduler att relatera det till Composer. Med hjälp av Composers beroendesystem kan utvecklare ange beroenden i sin composer.json-fil. När paketen har definierats i composer.json-filen behöver en PHP-utvecklare bara utfärda kommandot install som bör likna följande:
$ php composer.phar install
NPM-moduler fungerar på samma sätt och använder package.json-filen för att du ska kunna ange beroenden för ett visst program. Du kan också installera beroenden från kommandoraden för att göra dem tillgängliga på ditt lokala system. Oroa dig inte om du inte förstår detta ännu eftersom vi kommer att behandla package.json-filen mer ingående i ett senare steg.
För att installera LoopBack kan vi utfärda ett enda kommando som hämtar och installerar alla beroenden som vi behöver för paketet. Öppna ditt terminalfönster och ge följande kommando:
$ npm install -g strongloop
Notera: Du kan behöva använda sudo beroende på din installation
Vad hände precis? Vi berättade för npm att vi vill installera strongloop-paketet och samtidigt tillhandahålla alternativet -g
. Alternativet -g
gör paketet tillgängligt som ett globalt paket som alla på systemet kan använda och som är tillgängligt för alla program. När du kör ovanstående kommando kommer NPM att hämta paketet samt alla beroenden som krävs. Beroende på hastigheten på ditt system kan detta ta några minuter att genomföra.
Steg 3: Skapa vår applikation##
Skapa en applikation med hjälp av LoopBack API:et är mycket enkelt och okomplicerat. Öppna helt enkelt ditt terminalfönster och ge följande kommando för att skapa en ny applikation kallad locatewalmart
.
$ slc loopback _-----_ | | .--------------------------. |--(o)--| | Let's create a LoopBack | `---------´ | application! | ( _´U`_ ) '--------------------------' /___A___\ | ~ | __'.___.'__ ´ ` |° ´ Y ` Enter a directory name where to create the project: locatewalmart create locatewalmart/ info change the working directory to locatewalmart
Verktyget slc
kommer nu att skapa ett nytt LoopBack-baserat projekt kallat locatewalmart
och konfigurera projektet. När vi blir tillfrågade om programnamnet kan vi behålla standardvärdet.
What's the name of your application? locatewalmart
När du har kört kommandot ovan kommer en ny katalog för ditt projekt att skapas för ditt program. Byt till applikationskatalogen med kommandot cd:
$ cd locatewalmart
Nu när vi har skapat vår applikation vill vi lägga till stöd för MongoDB som datakälla för loopback.
Steg 4: Definiera vår datakälla###
För att kunna kommunicera med MongoDB måste vi lägga till en datakälla till vår applikation. Det gör vi genom att köra:
$ slc loopback:datasource mymongo Enter the data-source name: mymongo Select the connector for mymongo:PostgreSQL (supported by StrongLoop)Oracle (supported by StrongLoop)Microsoft SQL (supported by StrongLoop)❯ MongoDB (supported by StrongLoop)SOAP webservices (supported by StrongLoop)REST services (supported by StrongLoop)Neo4j (provided by community)(Move up and down to reveal more choices)
Steg 5: Peka på den riktiga datakällan##
För att kunna kommunicera med MongoDB måste vi peka datakällan på den faktiska MongoDB-instansen. LoopBack definierar all konfigurering av datakällan i filen datasource.json
som finns i katalogen root/server
för ditt program. Öppna den här filen och lägg till en datakälla för MongoDB enligt följande kod:
{ "db": { "name": "db", "connector": "memory" }, "mymongo": { "name": "mymongo", "connector": "mongodb" "url": "mongodb://localhost:27017/locatewalmart" }}
Notera: Var noga med att ange rätt anslutnings-URL för din MongoDB-databas. I det här exemplet har jag skapat en lokal databas som heter locatewalmart som jag vill använda som datakälla.
När vi nu har definierat vår databas finns det ett par extra saker som vi måste göra. Först och främst måste vi ange att våra program är beroende av paketet loopback-connector-mongodb
. För att ange ett beroende ändrar du filen package.json, vilket liknar redigering av filen composer.json
i PHP. Öppna filen package.json
som finns i din applikations rotkatalog och lägg till loopback-connector-mongodb
i avsnittet om beroende. Därefter kan du köra npm install.
Alternativt kan du bara köra:
$ npm install loopback-connector-mongodb --save
Detta kommer att automatiskt uppdatera package.json
. Avsnittet bör se ut på följande sätt:
"dependencies": { "compression": "^1.0.3", "errorhandler": "^1.1.1", "loopback": "^2.0.0", "loopback-boot": "^2.0.0", "loopback-connector-mongodb": "^1.4.1", "loopback-datasource-juggler": "^2.0.0", "serve-favicon": "^2.0.1" }
Steg 6: Importera data till MongoDB##
När vi nu har konfigurerat vår datakälla måste vi ladda datamängden till vår MongoDB-databas.
Det första vi vill göra är att hämta en JSON-fil som innehåller alla de data som vi vill returnera. Du kan hämta den på följande URL:
https://dl.dropboxusercontent.com/u/72466829/walmart.json
När du har laddat ner datamängden importerar du den helt enkelt till din databas med kommandot mongoimport som visas nedan:
$ mongoimport --jsonArray -d locatewalmart -c store --type json --file walmart.json -h yourMongoHost --port yourMongoPort -u yourMongoUsername -p yourMongoPassword
Du bör se följande resultat:
connected to: 127.0.0.12014-08-17T13:07:26.301-0400 check 9 31762014-08-17T13:07:26.305-0400 imported 3176 objects
Steg 7: Skapa vår butiksmodell##
En modell kan ses i samma termer som du tänker på modeller i PHP-land om du använder ett MVC-ramverk. Det är en representation av ett objekt som i det här fallet är en Walmart-butik. LoopBack erbjuder ett bekvämt sätt att skapa modellobjekt med hjälp av kommandoraden. Öppna ditt terminalfönster, gå till projektmappen och ge följande kommando:
$ slc loopback:model
Detta kommer att starta en interaktiv session där du kan definiera din modell. Det första du blir tillfrågad om är vilken datakälla du vill associera modellen med. Vi kommer att välja datakällan mymongo som vi just skapade tidigare. Därefter kommer den att fråga efter modellens pluralnamn. Vi använder standardvärdet (stores) och trycker på enter.
Enter the model name: store Select the data-source to attach store to:db (memory)❯ mymongo (mongodb) Expose store via the REST API? Yes Custom plural form (used to build REST URL):
När du trycker på enter-tangenten kommer du att uppmanas att ange egenskaperna för store-modellen. Du kan tänka på detta som var(s) som du definierar på en klass i PHP.
Enter an empty property name when done. Property name:
De egenskaper som vi vill lägga till är typ av butik, öppningsdatum, latitud och longitud.
Property name: opendate invoke loopback:property
När du trycker på enter kommer du att bli ombedd att ange datatyp för varje angiven egenskap. Det första objektet kommer att vara opendate och vi vill välja att den är av typen date. Välj datum och tryck på enter-tangenten.
Property type: string number boolean object array❯ date buffer geopoint (other)
Därefter kommer du att bli tillfrågad om du vill att den här egenskapen ska vara obligatorisk för schemavalidering. Vi anger ”ja”.
Required? (y/N) : y
Du kommer sedan att tillfrågas om datatypen för varje återstående egenskap. Ge följande svar:
Property name: type_store invoke loopback:property Property type: (Use arrow keys)❯ string number boolean object array date buffer geopoint (other) Required? (y/N) : yLet's add another store property.Enter an empty property name when done. Property name: latitude invoke loopback:property Property type: (Use arrow keys)❯ string number boolean object array date buffer geopoint (other) Required? (y/N) : yLet's add another store property.Enter an empty property name when done. Property name: longitude invoke loopback:property Property type: (Use arrow keys)❯ string number boolean object array date buffer geopoint (other) Required? (y/N) : y
Skriv in ”yes” och tryck på enter-tangenten.
Grattis! du har precis skapat ditt första modellobjekt med hjälp av LoopBack tillsammans med Node.js. För att se vad som faktiskt skapades under täckmantel öppnar du filen store.json
som finns i katalogen root/common/models
i din programkatalog. Hitta posten stores som kommer att se ut på följande sätt:
{ "name": "store", "base": "PersistedModel", "properties": { "opendate": { "type": "date", "required": true }, "type_store": { "type": "string", "required": true }, "latitude": { "type": "string", "required": true }, "longitude": { "type": "string", "required": true } }, "validations": , "relations": {}, "acls": , "methods": }
Som du kan se har vi skapat en modell och de egenskaper som vi definierade har tilldelats butiksmodellen. Fältet public anger att vi vill exponera den här modellen för världen via en REST-webbtjänst.
Mappningen av modellen till datakällan definieras i model-config.json
under mappen app root/server. Fältet datasource anger den datakälla som den här modellen kommer att använda för CRUD-operationer.
"store": { "dataSource": "mymongo", "public": true }
Steg 8: Testa det REST-baserade API:et##
Gissa vad? Du har precis skapat din första REST-baserade webbtjänst med hjälp av Node.js. Det var väl inte så farligt? Låt oss testa det genom att peka vår webbläsare till applikationen som vi just har skapat. Du kan göra detta genom att gå till följande URL:
http://0.0.0.0:3000/api/stores/
Du kommer att presenteras för en JSON-representation av alla Walmart-butiker som vi har importerat till databasen, vilket visas i följande bild:
Användning av StrongLoop Explorer###
Ja, det är ju bra. Vi har en REST-slutpunkt som returnerar alla Walmart-butiker i databasen, men det verkar fortfarande saknas en del eftersom vi inte har något förvaltningsgränssnitt för att arbeta med data eller för att kontrollera att alla CRUD-operationer fungerar. Lyckligtvis tillhandahåller StrongLoop en praktisk webbläsare som låter dig utforska alla slutpunkter som din applikation har. För att testa detta öppnar du din webbläsare och går till följande URL:
http://0.0.0.0:3000/explorer/
När Explorer-sidan har laddats expanderar du stores
API:et för att se alla tillgängliga operationer som är tillåtna på modellobjektet. Detta visas i följande bild:
Som exempel på vad du kan göra med Utforskaren expanderar du /stores/findOne
API och klickar på länken Try it out!
som kommer att fråga i databasen och returnera en post enligt följande bild:
Vidare genom att lägga till en kartrepresentation##
Visst, vi har skapat en REST-baserad slutpunkt som returnerar en lista över alla Walmart-butiker i vår databas. För att ytterligare illustrera hur snabbt man kan utveckla kompletta applikationer med StrongLoop, låt oss bygga en responsiv front end som innehåller en karta med pins för varje Walmart-butik.
Steg 1: Skapa den offentliga katalogen###
Som standard, enligt vad som anges i projektets app.js-fil, kommer alla filer i den offentliga katalogen som ligger i applikationens rotkatalog att serveras till den som begär dem. Den här katalogen kanske dock inte finns som standard, så vi måste skapa den. Öppna din terminal och byt till din applikations rotkatalog och ge följande kommando:
$ mkdir public
Steg 2: Skapa den responsiva kartan###
Nästa sak vi behöver göra är att skapa en snygg representation av data. Eftersom vi har latitud och longitud för varje butik skulle det vara bra att uttrycka detta innehåll med en karta som användaren kan dra runt, zooma in och ut ur osv. Den här uppgiften är faktiskt mycket enklare än du kanske tror om vi drar nytta av några befintliga bibliotek. I slutet av skapandet av den här responsiva vyn kommer resultatet att se ut på följande sätt:
För övrigt kommer användaren att kunna zooma in till en mycket detaljerad nivå på kartan för att visa den närmaste Walmart som visas i följande bild:
Koden för webbvyn i applikationen drar nytta av egenskaperna för longitud och latitud som vi definierade på vårt modellobjekt och importerade till databasen. Vi kommer också att använda det populära Leaflet-biblioteket för att skapa kartan och placera pins, eller markörer, på kartan.
För att skapa kartan skapar du en ny fil i den offentliga katalogen med namnet locatewalmart.html
och lägger till följande JavaScript-kod:
<!doctype html><html lang="en"><head> <title>Walmart Stores</title> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.css" /><!--> <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.ie.css" /><!--><script src="https://code.jquery.com/jquery-2.0.0.min.js"></script><link href='http://fonts.googleapis.com/css?family=oswald' rel='stylesheet' type='text/css'><meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /><style type="text/css">body { padding: 0; margin: 0;}html, body, #map { height: 100%; font-family: 'oswald';}.leaflet-container .leaflet-control-zoom { margin-left: 13px; margin-top: 70px;}#map { z-index: 1;}#title { z-index: 2; position: absolute; left: 10px; }</style></head><body><h1>Walmart Stores</h1><div></div><script src="http://cdn.leafletjs.com/leaflet-0.5.1/leaflet.js"></script><script>center = new L.LatLng(39.83, -98.58);zoom = 5;var map = L.map('map').setView(center, zoom);var markerLayerGroup = L.layerGroup().addTo(map);L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {maxZoom: 18,attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>'}).addTo(map);function getPins(e){url = "http://0.0.0.0:3000/api/stores";$.get(url, pinTheMap, "json")}function pinTheMap(data){//clear the current pinsmap.removeLayer(markerLayerGroup);//add the new pinsvar markerArray = ;var lastNumber = 0;for (var i = 0; i < data.length; i++){store = data;if(store.latitude.length > 0 && store.longitude.length>0) {markerArray.push(L.marker());}}markerLayerGroup = L.layerGroup(markerArray).addTo(map);}map.whenReady(getPins)</script></body></html>
Som du kan se är koden bara vanlig HTML och JavaScript. Den intressanta delen är funktionen getPins(e) där vi gör ett REST-samtal till API:et som vi skapade tidigare i det här blogginlägget. Vi itererar sedan över varje butik och skapar en pin med hjälp av latitud och longitud för varje butik. Ganska smart, eller hur?
Slutsats##
I det här blogginlägget visade jag hur man skapar en REST-baserad webbtjänst som returnerar en lista över Walmart-butiker i USA. Efter att vi skapat webbtjänsten med hjälp av Loopback lade vi till en front end-representation av data. Med mycket lite arbete kunde vi utveckla en fullt fungerande applikation mycket snabbare än vad man skulle kunna göra med sitt nuvarande språkval. Vi diskuterade också några av likheterna mellan Node.js och PHP. Även om jag fortfarande anser att PHP är ett utmärkt språk har jag personligen funnit att Node.js är ett utmärkt nästa språk att lära sig med tanke på det rika ekosystemet av bibliotek och den hastighet med vilken jag kan skapa tillämpningar.
Jag har inkluderat en snabbtabell som du kan referera till när du jämför Node.js med PHP.
Funktion |
PHP |
Node.js |
Bra IDE |
Ja, flera valmöjligheter med IntelliJ, Zend Studio, Netbeans etc. |
Ja, flera valmöjligheter med Eclipse, Visual Studio, Codenvy, etc |
Beroendehantering |
Composer, PEAR |
NPM |
Enterprise Ready |
Ja |
Ja |
Stort ekosystem av bibliotek |
Ja, men ibland svårt att hitta |
Ja |
Vanliga ramverk |
CodeIgniter, CakePHP, Laravel, etc |
Express, Meteor, etc |
Stöd för databaser |
Ja |
Ja |
Ickeblockerande IO |
Nej |
Ja |
Testning ramar |
Ja |
Ja |
Real-tidsapplikationer |
Ja, med ytterligare processer som Apache WebSocket osv. |
Ja |
Inbyggd webbserver |
Nej, de flesta använder den tillsammans med Apache |
Ja |
- Var redo att utveckla API:er i Node.js och få dem kopplade till dina data? Kolla in Node.js LoopBack-ramverket. Vi har gjort det enkelt att komma igång antingen lokalt eller i ditt favoritmoln, med en enkel npm-installation.