Construiți-vă pornirea cu PHP Geolocation și Google Places

Ce veți crea

Aceasta este partea a treia a Building Your Startup cu seria PHP pe Tuts +. În această serie, vă conduc prin lansarea unei lansări de la concept la realitate utilizând aplicația mea Planificator de întâlniri ca exemplu de viață reală. Fiecare pas de-a lungul drumului, vom lansa codul Planificatorului de întâlniri ca exemple de sursă deschisă pe care le puteți învăța.

În această parte, vom construi o parte din infrastructura de bază pentru conceptul de Locuri unde oamenii pot programa întâlniri. Vom acoperi principiile de lucru cu Locații, bazându-ne pe schema bazei de date, care integrează Geolocation HTML5 și API-uri pentru Google Maps și Google Places. Ideea este să utilizați aceste funcții pentru a face rapid și ușor alegerea locației pentru întâlnirile dvs. Noi nu acoperim totul în formă și termina în acest episod - dar vom acoperi mai mult din asta într-un tutorial viitoare.

Tot codul pentru Planificatorul întâlnirilor este scris în cadrul Yii2 pentru PHP și utilizează Bootstrap și JavaScript. Dacă doriți să aflați mai multe despre Yii2, consultați seria noastră paralelă Programming With Yii2 de la Tuts+.

Doar un memento, eu particip la comentariile de mai jos. Sunt interesat în special dacă aveți abordări diferite sau idei suplimentare sau doriți să sugerați subiecte pentru tutoriale viitoare. De asemenea, sunt binevenite solicitările de cereri pentru Planificatorul de întâlniri.

Construirea funcțiilor de locații

Înainte ca utilizatorii să poată programa întâlniri, avem nevoie ca ei să poată găsi și sugera locurile preferate. Inițial, pentru simplificare, vom construi funcția Căutarea locației și crearea separată de funcția de programare.

Există trei modalități prin care utilizatorii pot adăuga locații:

  1. Folosind Geolocation HTML5, ei pot căuta locația curentă prin WiFi și pot adăuga acest loc ca loc.
  2. Utilizând API-ul Google Locații, aceștia pot căuta un loc în baza de date Locații utilizând autocompletarea. În cele din urmă, când cunoaștem locația lor actuală, putem restricționa rezultatele căutării în locații din apropiere.
  3. Intrare manuală. Utilizatorii pot introduce o adresă și o descriere pentru propriul lor loc, cum ar fi un birou sau o casă.

Extinde schema de locație

Iată schema pentru locațiile pe care le-am dezvoltat în partea a doua:

$ tableOptions = null; dacă ($ this-> db-> driverName === 'mysql') $ tableOptions = 'SETUL CHARACTERU utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> createTable ('% place', ['id' => Schema :: TYPE_PK, 'name' => Schema :: TYPE_STRING. TYPE_SMALLINT 'NOT NULL DEFAULT 0', 'status' => Schema :: TYPE_SMALLINT. 'NOT NULL DEFAULT 0', 'google_place_id' => Schema :: TYPE_STRING. => Schema :: TYPE_BIGINT.NOT NULL ',' created_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',' updated_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',], $ tableOptions); $ this-> addForeignKey ('fk_place_created_by', '% place', 'created_by', 'user%', 'id', 'CASCADE', 'CASCADE');

Rețineți că în acest tabel nu există nicio localizare asociată cu un loc. Acest lucru se datorează faptului că motorul MySQL InnoDB nu suportă indexuri spațiale. Așadar, am creat o tabelă secundară folosind tabelul MyISAM pentru coordonatele de localizare geografică a Locațiilor. Este vorba de Place_GPS masa:

clasa m141025_213611_create_place_gps_table extinde Migrarea public function up () $ tableOptions = null; dacă ($ this-> db-> driverName === 'mysql') $ tableOptions = 'SETUL CHARACTERU utf8 COLLATE utf8_unicode_ci ENGINE = MyISAM';  $ this-> createTable ('% place_gps', ['id' => Schema :: TYPE_PK, 'place_id' => Schema :: TYPE_INTEGER. NULL ',], $ tableOptions); $ this-> execute ('crează indexul spațial place_gps_gps pe'. '% place_gps (gps);'); $ this-> addForeignKey ('fk_place_gps', '% place_gps', 'place_id', '% place', 'id', 'CASCADE', 'CASCADE'); 

Pe măsură ce sunt în modul de prototipare rapidă, voi extinde schema folosind migrațiile Yii și, în cele din urmă, aș putea să fac și ajustări viitoare.

Pentru a extinde schema, vom crea o nouă migrare în Yii:

./ yii migrați / creați extens_place_table

Și furnizați următorul cod:

db-> driverName === 'mysql') $ tableOptions = 'SETAREA CHARACTERULUI utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB';  $ this-> addColumn ('% place', 'slug', 'șirul NOT NULL'); $ this-> addColumn ('% place', 'site-ul', 'string NULL'); $ this-> addColumn ('% place', 'full_address', 'șirul NOT NULL'); $ this-> addColumn ('% place', 'vecinătate', 'șir NOT NULL'); $ This-> addColumn ( '% loc' 'note', 'text');  funcția publică jos () $ this-> dropColumn ('% place', 'slug'); $ This-> dropColumn ( '% loc', 'site'); $ This-> dropColumn ( '% loc' 'full_address'); $ This-> dropColumn ( '% loc' 'apropierea'); $ This-> dropColumn ( 'locul%' 'note');  

Acest lucru va adăuga coloane pentru slug, site, adresă completă, vecinătate și note. Blocajul este o adresă prietenoasă adresei URL pentru afișarea paginii de vizualizare a locației pe care Yii o poate genera automat pentru noi. Celelalte câmpuri vor fi actualizate, uneori, de utilizatori și de alte ori populate din API-ul Google Locații.

Pentru a rula migrarea, introduceți următoarele:

./ yii migrați / în sus

Ar trebui să vedeți următoarele:

Instrumentul de migrare Yii (bazat pe Yii v2.0.0) Se va aplica o nouă migrare totală: m150114_202542_extend_place_table Aplicați migrarea de mai sus? (da: nu): da *** aplicând m150114_202542_extend_place_table> adăugați șirul coloanei de coloană NOT NULL la tabelul % place ... done (time: 0.011s) loc  loc ... făcut (timp: 0.010s)> adăuga coloană full_address string NU NULL la tabel % place ... done (time: 0.010s) (0,011s) *** adăugat coloana note text în tabel % place ... făcut (timpul: 0,011s) *** aplicat m150114_202542_extend_place_table (timpul: 0.055s) Migrate cu succes. 

Actualizarea codului CRUD

Dacă vizitați pagina Locații, de ex. http: // localhost: 8888 / mp / index.php / place / create, veți vedea formatul generat automat Yii2 automat cu toate câmpurile noastre de schemă:

Pentru acest tutorial, am reanalizat generatorul de cod Yii, Gii, folosind pașii de la Partea a doua pentru a construi codul pentru noua schemă de bază de date. Am instruit-o pe Gii să suprascrie codul CRUD de la început. 

Notă: poate fi mai ușor să înlocuiți sursa de mostre din partea a doua cu sursa de probă din această parte. Vedeți legătura Github cu partea dreaptă sus.

De asemenea, va trebui să actualizați bibliotecile furnizorilor împreună cu compozitorul pentru a integra suportul pentru bibliotecile 2amigOS Yii2 Google Maps și Places. Iată o parte din fișierul nostru composer.json:

 "minimum-stabilitate": "stabil", "solicita": "php": "> = 5.4.0" "yiisoft / yii2" yiisoft / yii2-swiftmailer ":" * "," 2 amigos/yii2-google-maps-library ":" * "," 2 amigos/yii2-google-places-library " 

Apoi, executați actualizarea compozitorului pentru a descărca fișierele:

sudo compozitor actualizare

Trei moduri diferite de a adăuga locații

De fapt, vom construi trei acțiuni și forme diferite de controler pentru fiecare dintre aceste tipuri de locuri. Amintiți-vă că trebuie să integrăm și modelul asociat, PlaceGPS, pentru a stoca coordonatele GPS pentru fiecare loc, indiferent de modul în care îl adaugă utilizatorul.

Adăugarea locațiilor în bara de navigare

Pentru a adăuga un link Locații în bara de navigare, editați /views/layouts/main.php. Acesta este aspectul implicit al paginii pe care Yii îl împachetează cu toate fișierele noastre de vizualizare. Acesta include antetul, bara de navigare Bootstrap și subsolul.

Mai jos $ menuItems, Adăug o intrare de matrice pentru meniul Loc:

 NavBar :: începe (['brandLabel' => 'MeetingPlanner.io', // 'brandUrl' => Yii :: $ app-> homeUrl, 'options' => fix-top ",],]); $ nameItems = [['label' => 'Home', 'url' => ['/ site / index']], ['label' => 'Locuri', 'url' => ['/ ], ['label' => 'Despre', 'url' => ['/ site / about']], ['label' => ' ],]; dacă Yii :: $ app-> user-> isGuest) $ menuItems [] = ['label' => 'Înscriere', 'url' => ['/ site / signup']]; $ menuItems [] = ['label' => 'Login', 'url' => ['/ site / login']];  altfel $ menuItems [] = ['label' => 'Logout' ('Yii :: $ app-> user-> identitate-> nume utilizator) ], 'linkOptions' => ['metode de date' => 'post']];  echo Nav :: widget (['options' => ['class' => 'navbar-nav navbar-right'], 'items' => $ menuItems,]); NavBar :: end (); ?> 

Vizualizarea indexului locului

Indexul locului de afișare va arăta astfel după ce adăugăm butoane pentru cele trei moduri de adăugare a locațiilor:

În /views/place/index.php, putem adăuga cele trei adăugați loc butoane:

 

"btn btn-succes"])>> "btn btn-succes"])>> "btn btn-succes"])>>

Și putem personaliza coloanele care apar în vizualizare, inclusiv construirea unei coloane personalizate într-o metodă de locație care afișează numele prietenos pentru tipul de locație:

 $ dataProvider, 'filterModel' => $ searchModel, 'coloane' => ['class' => 'yii \ grid \ SerialColumn'], 'name', ' > 'raw', 'value' => function ($ model) return '
'$ Model-> getPlaceType ($ Model-> place_type).'
„; ,], ['class' => 'yii \ grid \ ActionColumn'],]]]; ?>

Iată un subset al metodelor tipului de locație din /models/Place.php:

 const TYPE_OTHER = 0; const TYPE_RESTAURANT = 10; const TYPE_COFFEESHOP = 20; const TYPE_RESIDENCE = 30; const TYPE_OFFICE = 40; const TYPE_BAR = 50; ... funcția publică getPlaceType ($ date) $ options = $ this-> getPlaceTypeOptions (); returneaza optiunile $ [$ data];  funcția publică getPlaceTypeOptions () return array (self :: TYPE_RESTAURANT => 'Restaurant', self :: TYPE_COFFEESHOP => 'Coffeeshop', self :: TYPE_RESIDENCE => 'Residence', self :: TYPE_OFFICE = auto :: TYPE_BAR => 'Bar', auto :: TYPE_OTHER => 'Altele');  

Observați că nu am abordat încă statutul de conectare sau deținerea de către utilizatori a locațiilor. Vom revizui acest lucru în următorul tutorial. Din cauza complexității și a domeniului de aplicare al acestei etape, vom lăsa o mână de elemente de finisare pentru un tutorial mai târziu.

Adăugarea de locații cu localizare geografică HTML5

Un scenariu pentru adăugarea de locuri este să creați un loc pentru casa sau biroul dvs. Mai degrabă decât să cerem utilizatorilor să introducă aceste informații manual, putem genera adesea acest lucru cu ajutorul unei localizări HTML5.

Geometria HTML5 utilizează adresa dvs. WiFi pentru a determina punctele GPS pentru locația dvs. curentă. Nu funcționează cu conexiuni celulare / mobile și nu este rezistentă. 

Utilizatorul va trebui probabil să acorde permisiunea browserului pentru geolocație pentru ca această funcție să funcționeze. Căutați un pop-up sub bara de adrese, după cum se arată mai jos:

Folosesc scriptul geopozitiv de la estebanav pentru a suporta Geometria HTML5 cu cea mai mare asistență posibilă pentru browser.

Adăugarea acțiunii de controler de locație pentru localizarea geografică

În frontend / controlere / PlaceController.php, vom crea o nouă metodă pentru Create_geo acțiune:

 / ** * Creează un nou model de locație prin Geolocation * / public action actionCreate_geo () $ model = new Place (); dacă $ model-> încărcați (Yii :: $ app-> request-> post ())) ... va fi explicat mai jos ... else return $ this-> render ('create_geo', ' $ model,]); 

Deoarece formularul nu este încă depus, Yii va face create_geo pentru a afișa formularul.

În front-end / opinii / loc / create_geo.php, vom include _formGeolocate.php:

title = 'Creați loc după geolocație'; $ this-> params ['breadcrumbs'] [] = ['label' => 'Locuri', 'url' => ['index']]; $ this-> params ['breadcrumbs'] [] = $ acest-> titlu; ?> 

titlu)?>

render ('_ formGeolocate', ['model' => $ model,])?>

Să ne uităm la prima parte a lui _formGeolocate. Trebuie să includeți JavaScript pentru Geoposition.js, precum și propriul cod de geolocalizare personalizat, pentru a integra geofizia cu formularul nostru. Modul în care Yii face acest lucru este cu Asset Bundles. Definiți un pachet de active pentru pagini diferite, ceea ce vă permite să optimizați care JS și CSS sunt încărcate în diferite zone ale aplicației dvs. Vom crea LocateAsset primul:

?php folosiți yii \ helpers \ Html; utilizați yii \ helpers \ BaseHtml; utilizați yii \ widget-uri \ ActiveForm; utilizați frontend \ assets \ LocateAsset; LocateAsset :: registru ($ acest); 

În frontend / active / LocateAsset.php, vom defini JavaScript care trebuie să includem:

LocateAsset preîncărcă API-ul Hărți Google geoPosition biblioteca și codul nostru Locate.js personalizat, care este prezentat mai jos:

funcția beginSearch () $ ('# preSearch') ascunde (); $ ( '# SearchArea') removeClass ( 'ascunse').; // if (navigator.geolocation) // navigator. dacă (geoPosition.init ()) geoPosition.getCurrentPosition (succes, errorHandler, timeout: 5000);  else error ('Ne pare rău, nu putem utiliza geolocația browserului pentru a vă găsi.');  funcția succes (poziție) $ ('# actionBar') removeClass ('ascuns'); $ ( '# AutolocateAlert') addClass ( 'ascunse').; var s = document.querySelector ('# status'); // butoane var = document.querySelector ('# locate_actions'); dacă (s.className == "succes") // nu este sigur de ce lovim acest lucru de două ori în FF, cred că are de a face cu un rezultat memorat înapoi revenind;  s.innerHTML = "Sunteți aici:"; s.className = 'succes'; var mapcanvas = document.createElement ("div"); mapcanvas.id = 'mapcanvas'; mapcanvas.style.height = '300px'; mapcanvas.style.width = '300px'; mapcanvas.style.border = '1px solid negru'; document.querySelector ( 'articol') appendChild (mapcanvas).; var latlng = google.maps.LatLng nou (position.coords.latitude, position.coords.longitude); var myOptions = zoom: 16, centru: latlng, mapTypeControl: false, navigationControlOptions: stil: google.maps.NavigationControlStyle.SMALL, mapTypeId: google.maps.MapTypeId.ROADMAP; var hartă = nou google.maps.Map (document.getElementById ("mapcanvas"), myOptions); var marker = nou google.maps.Marker (poziție: latlng, map: map, title: "Sunteți aici!" (cel puțin într-o "+ position.coords.accuracy +" radius) "); $ ( '# Locate_actionbar') removeClass ( 'ascunse').; $ ( '# Locul-lat') val (position.coords.latitude).; . $ ( '# Locul-LNG') val (position.coords.longitude);  funcția errorHandler (err) var s = document.querySelector ('# status'); s.innerHTML = tipof msg == 'string'? msg: "nu a reușit"; s.className = 'eșec'; // if (err.code == 1)  // utilizatorul a spus nu! document.location.href = '/ loc / index errorLocate?';  

Practic, geolocalizarea este inițiată când utilizatorul declanșează beginSearch. Codul Geopozitiv apelează funcția de succes atunci când se întoarce cu locația utilizatorului. Personalizăm funcția de succes pentru a afișa o hartă la locația respectivă și pentru a popula câmpurile de formular ascunse cu latitudinea și longitudinea returnate. Când utilizatorul publică formularul, coordonatele locației vor fi disponibile pentru aplicația Web. 

Iată codul înăuntru Succes() care cuprinde câmpurile formularului cu coordonatele locației:

$ ( '# Locul-lat') val (position.coords.latitude).; . $ ( '# Locul-LNG') val (position.coords.longitude);

Restul _formGeolocate.php este împărțit în două jumătăți egale. În partea stângă, furnizăm câmpurile de formular pentru utilizatorul care intră cu datele de geolocație și câmpurile ascunse de care avem nevoie pentru a suporta JavaScript. În partea dreaptă, lăsăm spațiu pentru un buton pentru a declanșa Geolocația și pentru afișarea hărții. succes() funcția umple

eticheta cu harta.

câmp ($ model, 'nume') -> textInput (['maxlength' => 255])?> câmp ($ model, 'site') -> textInput (['maxlength' => 255])?> câmpul ($ model, 'place_type') -> dropDownList ($ model-> getPlaceTypeOptions (), ['prompt' => 'Ce tip de loc este acesta? câmp ($ model, "note") -> textArea ()?>
esteNewRecord? 'Creare': 'Actualizare', ['class' => $ model-> isNewRecord? 'btn btn-succes': 'btn btn-primary'])?>


'btn btn-succes', 'onclick' => "javascript: beginSearch (); return false";))>

Căutarea locației dvs. curente ...

Iată cum arată formularul inițial:

Faceți clic pe Locația căutării pentru a iniția localizarea geografică. Din nou, căutați o solicitare de permisiuni în bara de navigare a browserului.

După găsirea locației dvs., vă vom arăta locația pe o hartă:

Notă: Am setat întârzierea pentru Geolocație la cinci secunde, dar uneori va trebui să reîncărcați pagina pentru a obține răspunsul corect după ce ați acordat permisiunea. Anumite locații WiFi sunt mai puțin determinate decât altele.

Să aruncăm o privire la formularul de trimitere a formularului de control al conferinței:

 funcția publică funcțiaCreate_geo () $ model = new Place (); dacă ($ model-> încărcați (Yii :: $ app-> request-> post ())) if (Yii :: $ app-> user-> getIsGuest ()) $ model-> created_by = 1;  altceva $ model-> created_by = Yii :: $ app-> user-> getId ();  $ form = Yii :: $ app-> request-> post (); $ Model-> Salvare (); // adăugați intrarea GPS în modelul PlaceGeometry $ model-> addGeometryByPoint ($ model, $ form ['Place'] ['lat'], $ form ['Place'] ['lng']); returnați $ this-> redirect (['view', 'id' => $ model-> id]); 

Deocamdată, introducem doar un substituent pentru utilizatorul creat de utilizatori și lăsând o manevrare a erorilor mai târziu (asistăm puristii, care nu se află în prezent în acest tutorial).

Când se creează posturile de formular și un loc, vom lua punctul de geolocație din formular (acele câmpuri ascunse completate de scriptul Locate.js) și vom adăuga un rând în tabelul de locații asociat PlaceGPS

Așa cum am menționat în partea a doua, separăm datele de geolocație într-un tabel diferit, deoarece motorul InnoDB MySQL nu suportă indexuri spațiale. Acest lucru va îmbunătăți, de asemenea, performanța interogărilor pentru a găsi cele mai apropiate locuri de întâlnire între doi utilizatori. 

Iată-l addGeometryByPoint în modelul Place.php:

 funcția publică addGeometryByPoint ($ model, $ lat, $ lon) $ pg = new PlaceGPS; $ Pg-> place_id = $ Model-> id; $ pg-> gps = nou \ yii \ db \ Expresiune ("GeomFromText (" Punctul ("$ lat" "$ lon.") ') "); $ Pg-> Salvare (); 

Iată ce ar trebui să arate pagina indexului de loc după înregistrarea înregistrării:

Dacă doriți să vedeți o altă implementare a localizării HTML5 pentru Yii 1.x, consultați Cum se utilizează Hărți de Vecinătate Zillow și Geolocație HTML5.

Afișarea locațiilor pe Hărți Google

Dacă faceți clic pe pictograma de comandă de vizualizare asociată cu noul nostru loc în afișarea indexului de mai sus, veți vedea aceasta:

Am personalizat pagina de vizualizare generată de Gii și codul adăugat pentru a desena harta Google utilizând extensia Google Maps Yii2.

Iată-l Vedere acțiune în PlaceController.php:

 / ** * Afișează un singur model de locație. * @ param integer $ id * @return mixt * / public function actionView ($ id) $ model = $ this-> findModel ($ id); $ gps = $ model-> getLocation ($ id); returneaza $ this-> render ('view', ['model' => $ model, 'gps' => $ gps,]);  

Iată-l getLocation în modelul Place.php. Efectuează coordonatele locației de la PlaceGPS masa:

funcția publică getLocation ($ place_id) $ sql = 'Selectați AsText (gps) ca gps din % place_gps unde place_id ='. $ place_id; $ model = LocGPS :: findBySql ($ sql) -> unul (); $ gps = nou \ stdClass; dacă (is_null ($ model)) return false;  altceva list ($ gps-> lat, $ gps-> lng) = $ this-> string_to_lat_lon ($ model-> gps);  returnați $ gps; 

Iată o parte din fișierul de vizualizare care redă pagina. Partea stângă constă dintr-un standard Yii2 Vedere Detaliată widget pentru moment. Partea dreaptă generează codul care desenează harta:

$ model, 'atribute' => ['name', 'place_type', 'website', 'full_address',],])?
$ gps-> lat, 'lng' => $ gps-> lng]); $ map = Harta nouă (['center' => $ coord, 'zoom' => 14, 'lățime' => 300, 'înălțime' => 300,]); $ marker = marker nou (['position' => $ coord, 'title' => $ model-> nume,]); // Adaugă marker pe hartă $ map-> addOverlay ($ marker); echo $ map-> display (); else echo 'Nu pot fi găsite coordonate de locație pentru acest loc.'; ?>

Adăugarea din API-ul Google Locații

Funcția de completare automată Google Places este o modalitate incredibil de rapidă și simplă pentru ca utilizatorii să adauge locuri de întâlnire. Folosesc extensia Yii2 Google Places de 2amigOS.

În PlaceController.php, vom adăuga o acțiune pentru Create_place_google:

/ ** * Creează un nou model de locație din Google Place * Dacă creația are succes, browserul va fi redirecționat către pagina "vizualizare". * @return mixed * / public function actionCreate_place_google () $ model = new Place (); dacă $ model-> încărcați (Yii :: $ app-> request-> post ())) ... va fi explicat mai jos ... else return $ this-> render ('create_place_google', [ > $ model,]);  

/frontend/views/place/create_place_google.php fișierul va afișa formularul și va inițializa JavaScript necesar pentru a susține autocompletarea:

titlu)?>

render ('_ formPlaceGoogle', ['model' => $ model,])?>
'locuri', 'senzor' => 'false',)); echo $ this-> registerJsFile ($ gpJsLink); $ options = '"types": ["establishment"], "componentRestrictions": "country": "us"'; echo $ this-> registerJs ("(functie () var input = document.getElementById ('loc-searchbox'); var opțiuni = $ opțiuni; căutarebox = noi google.maps.places.Autocomplete (input, options); ();) (); ", \ yii \ web \ Vizualizare :: POS_END); // 'configurabounds ('. $ bound_bl. ','. $ bound_tr. '); ?>

Programatorul Petra Barus a oferit o extensie Google Places pentru Yii1.x. Pentru acest tutorial, am codat manual suportul de bază pentru Yii2. Cu toate acestea, Barus a fost suficient de bun pentru a elibera o extensie Yii2 la doar câteva zile după aceea. Încă nu am integrat codul lui. Iată cea mai recentă extensie Yii2 Autocompletare Google Locații.

Iată-l MapAsset pachet pe care îl creez pentru JavaScript asociat care va fi necesar:

Iată-l _formPlaceGoogle.php cod formular:

 

Introduceți un loc sau o companie cunoscută în Google Locații:

câmp ($ model, 'searchbox') -> textInput (['maxlength' => 255]) -> etichetă (' câmpul ($ model, 'place_type') -> dropDownList ($ model-> getPlaceTypeOptions (), ['prompt' => 'Ce tip de loc este acesta?
esteNewRecord? 'Creare': 'Actualizare', ['class' => $ model-> isNewRecord? 'btn btn-succes': 'btn btn-primary'])?>

Este un SearchBox câmp care va accepta intrarea de completare automată a utilizatorului. Există, de asemenea, o varietate de câmpuri ascunse pe care JavaScript-ul nostru le va încărca cu rezultatele serviciului Google Locații.

Aici este create_place.js care realizează toate "magia":

funcția setupListeners () // google.maps.event.addDomListener (fereastră, "încărcare", inițializare); // căsuța de căutare este var pentru obiectul locații google creat pe pagina google.maps.event.addListener (caseta de căutare, 'place_changed', function () var place = searchbox.getPlace (); if (! place.geometry) // Informați utilizatorul că un loc nu a fost găsit și returnat. Retur; altfel // migrează datele JSON de pe Google în câmpurile de formă ascunse populateResult (loc););  functie populateResult (loc) // muta JSON recuperarea datelor de la Google la campuri de formular ascunse // asa ca Yii2 poate posta datele $ ('# place-location') val (JSON.stringify (place ['geometry' 'Locație'])); $ ( '# Locul-google_place_id') val (loc [ 'place_id'].); $ ( '# Locul-full_address') val (loc [ 'formatted_address'].); . $ ( '# Locul-site-ul') val (locul [ 'site']); $ ( '# Locul-vecinătate') val (locul [ 'apropierea']).; $ ( '# Locul-name') val (locul [ 'name'].); loadMap (locul [ 'geometrie'] [ 'locația'], locul [ 'name']);  funcția loadMap (gps, nume) var mapcanvas = document.createElement ('div'); mapcanvas.id = 'mapcanvas'; mapcanvas.style.height = '300px'; mapcanvas.style.width = '300px'; mapcanvas.style.border = '1px solid negru'; document.querySelector ( 'articol') appendChild (mapcanvas).; var latlng = nou google.maps.LatLng (gps ['k'], gps ['D']); var myOptions = zoom: 16, centru: latlng, mapTypeControl: false, navigationControlOptions: stil: google.maps.NavigationControlStyle.SMALL, mapTypeId: google.maps.MapTypeId.ROADMAP; var hartă = nou google.maps.Map (document.getElementById ("mapcanvas"), myOptions); var marker = nou google.maps.Marker (position: latlng, map: map, title: name); 

setupListeners () metoda link-uri noastre SearchBox câmp la serviciul de completare automată Google Locații. Când un place_changed evenimentul apare, populateResult () este chemat să completeze câmpurile ascunse din formular cu datele de la Google și să încarce harta afișată în jumătatea dreaptă a formularului.

Puteți utiliza programul de depanare a browserului pentru a inspecta câmpurile ascunse după ce acestea au fost completate cu datele formularului prin JavaScript. Aceste date vor fi postate împreună cu formularul la trimitere, astfel încât să le putem adăuga în baza de date Loc.

Iată elementul rămas al PlaceController Create_place_google salvați acțiunea:

 funcția publică funcțiaCreate_place_google () $ model = new Place (); dacă ($ model-> încărcați (Yii :: $ app-> request-> post ())) if (Yii :: $ app-> user-> getIsGuest ()) $ model-> created_by = 1;  altceva $ model-> created_by = Yii :: $ app-> user-> getId ();  $ form = Yii :: $ app-> request-> post (); $ Model-> Salvare (); // adăugați intrarea GPS în modelul PlaceGeometry $ model-> addGeometry ($ model, $ form ['Place'] ['locație']); returnați $ this-> redirect (['view', 'id' => $ model-> id]); 

Este destul de similar cu Create_geo acțiune. Avem o metodă separată Place.php pentru a simplifica colectarea datelor despre locație. Iată addGeometry ():

funcția publică addGeometry ($ model, $ location) $ x = json_decode ($ location, true); reset ($ x); $ lat = curent ($ x); $ lon = următoarea ($ x); $ pg = Locație nouă; $ Pg-> place_id = $ Model-> id; $ pg-> gps = nou \ yii \ db \ Expresiune ("GeomFromText (" Punctul ("$ lat" "$ lon.") ') "); $ Pg-> Salvare (); 

Setarea filtrelor frontale geografice pentru căutare automată completă

Serviciul de completare automată a locațiilor vă permite de asemenea să configurați un dreptunghi delimitare geografică pentru a vă filtra în interiorul căutării. Când utilizatorul începe să scrie, autocompletul va folosi numai locurile în termen de zece kilometri de ele. Deoarece nu am configurat locația curentă a utilizatorului ca variabilă de sesiune, nu pun în aplicare dreptunghiul de delimitare în acest moment. Dar putem face asta mai târziu. Iată un exemplu de setupBounds ():

funcția setupBounds (pt1, pt2, pt3, pt4) defaultBounds = noi google.maps.LatLngBounds (nou google.maps.LatLng (pt1, pt2), nou google.maps.LatLng (pt3, pt4)); searchbox.setBounds (defaultBounds);  

Adăugarea manuală a locațiilor

Al treilea mod în care utilizatorii pot adăuga locuri este prin furnizarea manuală a detaliilor și a adreselor. Când trimit formularul, vom încerca să căutăm adresa și să obținem datele geolocation, dar e în regulă dacă nu găsim acest lucru. Abordarea manuală va permite utilizatorilor să adauge locuri cum ar fi casele lor sau un birou pe care nu le doresc să le asocieze cu datele de cartografiere Google.

Iată cum arată formularul:

Iată ce arată codul de acțiune pentru depunerea PlaceController.php. Folosim clientul Geocoding Maps 2Amigos pentru a cău

Cod