Dit is deel drie van de Building Your Startup With PHP-serie op Tuts +. In deze serie begeleid ik je door een opstart van concept naar realiteit te starten met behulp van mijn Meeting Planner-app als een echt voorbeeld. Bij elke stap zullen we de Meeting Planner-code vrijgeven als open source-voorbeelden waar u van kunt leren.
In dit deel gaan we een deel van de onderliggende infrastructuur voor het concept Plaatsen bouwen waar mensen vergaderingen kunnen plannen. We bespreken de basisbeginselen van werken met Places, voortbouwend op ons databaseschema, integratie van HTML5 Geolocation en API's voor Google Maps en Google Places. Het idee is om deze functies te gebruiken om het snel en eenvoudig kiezen van de locatie voor uw vergaderingen. In deze aflevering dekken we de pasvorm en afwerking niet volledig, maar we zullen er meer over vertellen in een volgende tutorial.
Alle code voor Meeting Planner is geschreven in het Yii2 Framework voor PHP en maakt gebruik van Bootstrap en JavaScript. Als je meer wilt weten over Yii2, bekijk dan onze parallelle serie Programming With Yii2 at Tuts+.
Ter herinnering, ik neem wel deel aan de commentaarthreads hieronder. Ik ben vooral geïnteresseerd als je verschillende benaderingen of aanvullende ideeën hebt, of onderwerpen wilt voorstellen voor toekomstige zelfstudies. Functieverzoeken voor Meeting Planner zijn ook welkom.
Voordat gebruikers vergaderingen kunnen plannen, moeten ze hun favoriete plaatsen kunnen vinden en voorstellen. In eerste instantie bouwen we voor de eenvoud de functie voor zoeken en maken van plaatsen apart van de planningsfunctie.
Gebruikers kunnen op drie manieren plaatsen toevoegen:
Dit is het schema voor plaatsen dat we in deel twee hebben ontwikkeld:
$ tableOptions = null; if ($ this-> db-> driverName === 'mysql') $ tableOptions = 'KARAKTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'; $ this-> createTable ('% place', ['id' => Schema :: TYPE_PK, 'name' => Schema :: TYPE_STRING. 'NOT NULL', 'place_type' => Schema :: TYPE_SMALLINT. 'NOT NULL DEFAULT 0', 'status' => Schema :: TYPE_SMALLINT. 'NOT NULL DEFAULT 0', 'google_place_id' => Schema :: TYPE_STRING. 'NOT NULL', // eg google places id 'created_by' => 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');
Opmerking: er is geen geolocatie gekoppeld aan een plaats in deze tabel. Dat komt omdat de MySQL InnoDB-engine geen ruimtelijke indexen ondersteunt. Dus ik heb een secundaire tabel gemaakt met behulp van de geolocatie-coördinaten van de MyISAM-tabel voor plaatsen. Het is de Place_GPS
tafel:
class m141025_213611_create_place_gps_table breidt Migration uit public function up () $ tableOptions = null; if ($ this-> db-> driverName === 'mysql') $ tableOptions = 'KARAKTER SET utf8 COLLATE utf8_unicode_ci ENGINE = MyISAM'; $ this-> createTable ('% place_gps', ['id' => Schema :: TYPE_PK, 'place_id' => Schema :: TYPE_INTEGER. 'NOT NULL', 'gps' => 'POINT NOT NULL ',], $ tableOptions); $ this-> execute ('create spatial index place_gps_gps on'. '% place_gps (gps);'); $ this-> addForeignKey ('fk_place_gps', '% place_gps', place_id ',' % place ',' id ',' CASCADE ',' CASCADE ');
Omdat ik in rapid prototyping-modus ben, ga ik het schema uitbreiden met Yii's migraties en ik kan uiteindelijk ook toekomstige aanpassingen maken.
Om het schema uit te breiden, maken we een nieuwe migratie in Yii:
./ yii migreren / create extend_place_table
En geef de volgende code op:
db-> driverName === 'mysql') $ tableOptions = 'KARAKTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'; $ this-> addColumn ('% place', 'slug', 'string NOT NULL'); $ this-> addColumn ('% place', 'website', 'string NOT NULL'); $ this-> addColumn ('% place', 'full_address', 'string NOT NULL'); $ this-> addColumn ('% place', 'vicinity', 'string NOT NULL'); $ This-> addColumn ( '% plaats', 'merkt', 'tekst'); public function down () $ this-> dropColumn ('% place', 'slug'); $ This-> dropColumn ( '% plaats', 'website'); $ This-> dropColumn ( '% plaats', 'full_address'); $ This-> dropColumn ( '% plaats', 'omgeving'); $ This-> dropColumn ( '% plaats', 'merkt');
Hiermee worden kolommen toegevoegd voor slug, website, volledige_adres, omgeving en notities. De slug is een URL-vriendelijk adres voor het weergeven van de Place View-pagina die Yii automatisch voor ons kan genereren. De andere velden worden soms bijgewerkt door gebruikers en andere tijden die zijn gevuld met de Google Places API.
Om de migratie uit te voeren, voeren we het volgende in:
./ yii migreren / omhoog
Je zou het volgende moeten zien:
Yii Migration Tool (gebaseerd op Yii v2.0.0) Totaal 1 nieuwe migratie die moet worden toegepast: m150114_202542_extend_place_table Pas de bovenstaande migratie toe? (yes | no) [no]: yes *** apply m150114_202542_extend_place_table> voeg kolom slug string NOT NULL toe aan tabel % place ... done (time: 0.011s)> voeg kolom website string toe NOT NULL to table % plaats ... klaar (tijd: 0.010s)> kolom vol_address tekenreeks NIET NULL toevoegen aan tabel % place ... klaar (tijd: 0.010s)> voeg kolom nabijheid string NIET NULL toe aan tabel % place ... done (time: 0.011s)> kolomtekst toevoegen aan tabel % place ... done (tijd: 0.011s) *** toegepast m150114_202542_extend_place_table (tijd: 0.055s) Migratie succesvol uitgevoerd.
Als u de pagina Plaatsen bezoekt, bijvoorbeeld http: // localhost: 8888 / mp / index.php / place / create, je ziet de standaard Yii2 automatisch gegenereerde formulier met al onze schemavelden:
Voor deze zelfstudie heb ik Yii's codegenerator Gii opnieuw uitgevoerd met de stappen uit Deel twee om code te bouwen voor het nieuwe databaseschema. Ik gaf Gii opdracht de CRUD-code van eerder te overschrijven.
Opmerking: het is wellicht het gemakkelijkst om uw voorbeeldbron uit deel twee te vervangen door een voorbeeldbron uit dit deel. Zie de Github-link rechtsboven.
U moet ook onze leveranciersbibliotheken bijwerken met componist om ondersteuning voor de 2amigOS Yii2 Google Maps- en Places-bibliotheken te integreren. Hier is een deel van ons composer.json-bestand:
"minimum-stability": "stable", "require": "php": "> = 5.4.0", "yiisoft / yii2": "*", "yiisoft / yii2-bootstrap": "*", " yiisoft / yii2-swiftmailer ":" * "," 2 amigos/yii2-google-maps-library ":" * "," 2 amigos/yii2-google-places-library ":" * "
Voer vervolgens de update van de composer uit om de bestanden te downloaden:
sudo composer update
We gaan eigenlijk drie verschillende controlleracties en -formulieren maken voor elk van deze soorten plaatsen. Vergeet niet dat we ook het gerelateerde model moeten integreren, PlaceGPS
, om de GPS-coördinaten voor elke plaats op te slaan, ongeacht hoe de gebruiker deze toevoegt.
Om een Places-link aan de navigatiebalk toe te voegen, bewerk /views/layouts/main.php
. Dit is de standaard paginalay-out waarmee Yii al onze view-bestanden omslaat. Het bevat de header, Bootstrap-navigatiebalk en voettekst.
Hieronder in $ menuitems
, Ik voeg een array-vermelding toe voor het menu Plaatsen:
NavBar :: begin (['brandLabel' => 'MeetingPlanner.io', // 'brandUrl' => Yii :: $ app-> homeUrl, 'options' => ['class' => 'navbar-inverse navbar- vaste top ',],]); $ menuItems = [['label' => 'Home', 'url' => ['/ site / index']], ['label' => 'Plaatsen', 'url' => ['/ plaats'] ], ['label' => 'Over', 'url' => ['/ site / over']], ['label' => 'Contact', 'url' => ['/ site / contact'] ],]; if (Yii :: $ app-> user-> isGuest) $ menuItems [] = ['label' => 'Signup', 'url' => ['/ site / aanmelding']]; $ menuItems [] = ['label' => 'Inloggen', 'url' => ['/ site / login']]; else $ menuItems [] = ['label' => 'Uitloggen ('. Yii :: $ app-> gebruiker-> identiteit-> gebruikersnaam. ')', 'url' => ['/ site / logout' ], 'linkOptions' => ['data-methode' => 'post']]; echo Nav :: widget (['options' => ['class' => 'navbar-nav navbar-right'], 'items' => $ menuItems,]); NavBar :: uiteinde (); ?>
De Place Index-weergave ziet er als volgt uit nadat we knoppen hebben toegevoegd voor de drie manieren om Places toe te voegen:
In /views/place/index.php
, we kunnen de drie toevoegen plaats toevoegen
toetsen:
= Html::a('Add Place', ['create'], ['class' => 'btn btn-success'])?> = Html::a('Add Current Location', ['create_geo'], ['class' => 'btn btn-success'])?> = Html::a('Add a Google Place', ['create_place_google'], ['class' => 'btn btn-success'])?>
En we kunnen de kolommen aanpassen die in de weergave worden weergegeven, inclusief het bouwen van een aangepaste kolom naar een plaatsmethode die de beschrijvende naam voor plaatstype weergeeft:
= GridView::widget([ 'dataProvider' => $ dataProvider, 'filterModel' => $ searchModel, 'columns' => [['class' => 'yii \ grid \ SerialColumn'], 'name', ['attribute' => 'place_type', 'format' = > 'onbewerkt', 'waarde' => functie ($ model) terug ''$ Model-> getPlaceType ($ model-> place_type).''; ,], ['class' => 'yii \ grid \ ActionColumn'],],]); ?>
Hier is een subset van de Place Type-methoden in /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; ... openbare functie getPlaceType ($ data) $ options = $ this-> getPlaceTypeOptions (); return $ options [$ data]; openbare functie getPlaceTypeOptions () return array (self :: TYPE_RESTAURANT => 'Restaurant', self :: TYPE_COFFEESHOP => 'Coffeeshop', self :: TYPE_RESIDENCE => 'Woonplaats', zelf :: TYPE_OFFICE => 'Kantoor', self :: TYPE_BAR => 'Bar', self :: TYPE_OTHER => 'Anders');
Opmerking: we hebben de aanmeldingsstatus of gebruikerseigendom van plaatsen nog niet geadresseerd. We zullen dit in de volgende tutorial opnieuw bekijken. Vanwege de complexiteit en reikwijdte van deze fase laten we een handvol afwerkingsitems achter voor een later zelfstudie.
Eén scenario voor het toevoegen van plaatsen is om een plaats te maken voor uw huis of kantoor. In plaats van te vereisen dat gebruikers deze informatie met de hand typen, kunnen we dit vaak automatisch genereren met HTML5 Geolocation.
HTML5 Geolocation gebruikt uw WiFi-adres om GPS-punten voor uw huidige locatie te bepalen. Het werkt niet met mobiele / mobiele verbindingen en het is niet waterdicht.
De gebruiker moet waarschijnlijk toestemming geven aan zijn browser voor geolocatie om deze functie te laten werken. Zoek naar een pop-up onder de adresbalk zoals hieronder getoond:
Ik gebruik het geoposition-script van estebanav om HTML5 Geolocation te ondersteunen met de breedst mogelijke browserondersteuning.
In frontend / controllers / PlaceController.php
, we zullen een nieuwe methode voor de maken Create_geo
actie:
/ ** * Maakt een nieuw plaatsmodel via Geolocatie * / public function actionCreate_geo () $ model = nieuwe plaats (); if ($ model-> load (Yii :: $ app-> request-> post ())) ... hieronder uit te leggen ... else return $ this-> render ('create_geo', ['model' => $ model,]);
Omdat het formulier nog niet wordt ingediend, geeft Yii het formulier weer create_geo
weergave om het formulier weer te geven.
In frontend / views / plaats / create_geo.php
, we zullen opnemen _formGeolocate.php
:
title = 'Plaats op geolocatie'; $ this-> params ['breadcrumbs'] [] = ['label' => 'Plaatsen', 'url' => ['index']]; $ this-> params ['breadcrumbs'] [] = $ this-> title; ?>= Html::encode($this->titel)?>
= $this->render ('_ formGeolocate', ['model' => $ model,])?>
Laten we naar het eerste deel kijken _formGeolocate
. We moeten JavaScript voor Geoposition.js en onze aangepaste geolocatiecode opnemen om geoposition te integreren met ons formulier. De manier waarop Yii dit doet, is met Asset Bundles. U definieert een activabundel voor verschillende pagina's en hiermee kunt u optimaliseren welke JS en CSS wordt geladen in verschillende delen van uw toepassing. We zullen creëren LocateAsset
eerste:
?php gebruik yii \ helpers \ Html; gebruik yii \ helpers \ BaseHtml; gebruik yii \ widgets \ ActiveForm; gebruik frontend \ assets \ LocateAsset; LocateAsset :: register ($ this);
In frontend / assets / LocateAsset.php
, we zullen het JavaScript definiëren dat we moeten opnemen:
LocateAsset
preloads de Google Maps API, deGeopositie
bibliotheek en onze aangepaste Locate.js-code die hieronder wordt weergegeven:function startSearch () $ ('# preSearch'). hide (); $ ( '# SearchArea') removeClass ( 'verborgen').; // if (navigator.geolocation) // navigator. if (geoPosition.init ()) geoPosition.getCurrentPosition (success, errorHandler, timeout: 5000); else error ('Sorry, we kunnen de geolocatie van de browser niet gebruiken om u te vinden.'); functie success (positie) $ ('# actionBar'). removeClass ('hidden'); $ ( '# AutolocateAlert') addClass ( 'verborgen').; var s = document.querySelector ('# status'); // var buttons = document.querySelector ('# locate_actions'); if (s.className == 'success') // niet zeker waarom we dit in FF twee keer raken, ik denk dat het te maken heeft met een resultaat in de cache dat terugkomt; s.innerHTML = "U bent hier:"; s.className = 'succes'; var mapcanvas = document.createElement ('div'); mapcanvas.id = 'mapcanvas'; mapcanvas.style.height = '300px'; mapcanvas.style.width = '300px'; mapcanvas.style.border = '1px effen zwart'; document.querySelector ( 'artikel') appendChild (mapcanvas).; var latlng = new google.maps.LatLng (position.coords.latitude, position.coords.longitude); var myOptions = zoom: 16, center: latlng, mapTypeControl: false, navigationControlOptions: style: google.maps.NavigationControlStyle.SMALL, mapTypeId: google.maps.MapTypeId.ROADMAP; var map = new google.maps.Map (document.getElementById ("mapcanvas"), myOptions); var marker = new google.maps.Marker (position: latlng, map: map, title: "You are here! (tenminste binnen een" + position.coords.accuracy + "straal van de meter)"); $ ( '# Locate_actionbar') removeClass ( 'verborgen').; $ ( '# Place-lat') val (position.coords.latitude).; . $ ( '# Place-lng') val (position.coords.longitude); function errorHandler (err) var s = document.querySelector ('# status'); s.innerHTML = typeof msg == 'string'? msg: "mislukt"; s.className = 'mislukt'; // if (err.code == 1) // gebruiker zei nee! document.location.href = '/ plaats / index errorLocate?';In principe wordt geolocatie gestart wanneer de gebruiker triggert
beginSearch
. De Geoposition-code roept de succesfunctie aan wanneer deze terugkeert naar de locatie van de gebruiker. We passen de succesfunctie aan om een kaart op de locatie weer te geven en om onze verborgen formuliervelden te vullen met de geretourneerde breedtegraad en lengtegraad. Wanneer de gebruiker het formulier heeft geplaatst, zijn de locatiecoördinaten beschikbaar voor onze web-app.Hier is de code in
Succes()
die de formuliervelden aanvult met de locatiecoördinaten:$ ( '# Place-lat') val (position.coords.latitude).; . $ ( '# Place-lng') val (position.coords.longitude);De rest van
_formGeolocate.php
is gesplitst in twee gelijke helften. Aan de linkerkant bieden we de formuliervelden voor de gebruiker om in te voeren met de geolocatiegegevens en de verborgen velden die we nodig hebben om JavaScript te ondersteunen. Aan de rechterkant laten we ruimte voor een knop om Geolocation te activeren en voor het weergeven van de kaart. Desucces()
functie vult detag met de kaart.
= $form->field ($ model, 'name') -> textInput (['maxlength' => 255])?> = $form->field ($ model, 'website') -> textInput (['maxlength' => 255])?> = $form->field ($ model, 'place_type') -> dropDownList ($ model-> getPlaceTypeOptions (), ['prompt' => 'Welk type plaats is dit?']) -> label ('Type of Place')?> = $form->field ($ model, 'notes') -> textArea ()?> = BaseHtml::activeHiddenInput($model, 'lat'); ?> = BaseHtml::activeHiddenInput($model, 'lng'); ?>= Html::submitButton($model->isNewRecord? 'Maken': 'Update', ['class' => $ model-> isNewRecord? 'btn btn-success': 'btn btn-primary'])?>= Html::a('Lookup Location', ['lookup'], ['class' => 'btn btn-success', 'onclick' => "javascript: beginSearch (); return false;"])?>
Zoeken naar je huidige locatie ...
Dit is hoe het formulier er in eerste instantie uitziet:
Klik op de Opzoeklocatie knop om geolocatie te initiëren. Nogmaals, zoek naar een toestemmingsverzoek in de navigatiebalk van de browser.
Zodra uw locatie is gevonden, laten we uw locatie zien op een kaart:
Opmerking: ik heb de vertraging voor Geolocation ingesteld op vijf seconden, maar soms moet je de pagina opnieuw laden om de juiste reactie te krijgen nadat je toestemming hebt gegeven. Bepaalde wifi-locaties zijn minder bepalend dan andere.
Laten we de indelingscode van de vergaderingcontroller bekijken:
public function actionCreate_geo () $ model = nieuwe plaats (); if ($ model-> load (Yii :: $ app-> request-> post ())) if (Yii :: $ app-> user-> getIsGuest ()) $ model-> created_by = 1; else $ model-> created_by = Yii :: $ app-> user-> getId (); $ form = Yii :: $ app-> request-> post (); $ Model-> save (); // voeg GPS-invoer toe in PlaceGeometry $ model-> addGeometryByPoint ($ model, $ form ['Place'] ['lat'], $ form ['Place'] ['lng']); return $ this-> redirect (['view', 'id' => $ model-> id]);Voor nu plaatsen we gewoon een tijdelijke aanduiding voor de gebruiker created_by en laten we de foutafhandeling voor later achter (sorry puristen, dat is niet de focus van deze tutorial op dit moment).
Wanneer de formulierberichten en een plaats worden gemaakt, nemen we het geolocatiepunt van het formulier (die verborgen velden gevuld met het script Locate.js) en voegen we een rij toe aan de gerelateerde plaatsentabel.
PlaceGPS
.Zoals ik in deel twee heb genoemd, scheiden we de geolocatiegegevens in een andere tabel omdat de MySQL InnoDB-engine geen ruimtelijke indexen ondersteunt. Dit zal ook de prestaties van zoekopdrachten verbeteren om de dichtstbijzijnde ontmoetingsplaatsen tussen twee gebruikers te vinden.
Hier is de
addGeometryByPoint
methode in het Place.php-model:openbare functie addGeometryByPoint ($ model, $ lat, $ lon) $ pg = nieuwe PlaceGPS; $ PG-> place_id = $ model-> id; $ pg-> gps = new \ yii \ db \ Expression ("GeomFromText ('Point (". $ lat. "". $ lon. ")')"); $ PG-> save ();Dit is hoe de Place Index-pagina eruit moet zien nadat de record is opgeslagen:
Als u een andere implementatie van HTML5 Geolocation voor Yii 1.x wilt zien, ga dan naar Hoe u Zillow Neighborhood Maps en HTML5 Geolocation gebruikt.
Plaatsen weergeven op Google Maps
Als u op het opdrachtpictogram voor de weergave klikt dat is gekoppeld aan onze nieuwe plaats in de indexweergave hierboven, ziet u dit:
We hebben de Gii-gegenereerde weergavepagina aangepast en code toegevoegd om de Google Map te tekenen met behulp van de Yii2 Google Maps-extensie.
Hier is de
Uitzicht
actie in PlaceController.php:/ ** * Geeft een enkel plaatsmodel weer. * @param integer $ id * @return mixed * / public function actionView ($ id) $ model = $ this-> findModel ($ id); $ gps = $ model-> getLocation ($ id); return $ this-> render ('view', ['model' => $ model, 'gps' => $ gps,]);Hier is de
getLocation
methode in het Place.php-model. Het haalt de locatiecoördinaten uit dePlaceGPS
tafel:openbare functie getLocation ($ place_id) $ sql = 'Selecteer AsText (gps) als gps van % place_gps waar place_id ='. $ place_id; $ model = PlaceGPS :: findBySql ($ sql) -> one (); $ gps = nieuw \ stdClass; if (is_null ($ model)) return false; else list ($ gps-> lat, $ gps-> lng) = $ this-> string_to_lat_lon ($ model-> gps); retourneer $ gps;Hier is een gedeelte van het weergavebestand dat de pagina weergeeft. De linkerkant bestaat uit een standaard Yii2
detailoverzicht
widget voor nu. De rechterkant genereert de code die de kaart trekt:= DetailView::widget([ 'model' => $ model, 'attributen' => ['naam', 'place_type', 'website', 'full_address',],])?>if ($gps!==false) $coord = new LatLng(['lat' => $ gps-> lat, 'lng' => $ gps-> lng]); $ map = new Map (['center' => $ coord, 'zoom' => 14, 'width' => 300, 'height' => 300,]); $ marker = new Marker (['position' => $ coord, 'title' => $ model-> name,]); // Markering aan de kaart toevoegen $ map-> addOverlay ($ marker); echo $ map-> display (); else echo 'Er kunnen geen locatiecoördinaten voor deze plaats worden gevonden.'; ?>Toevoegen via de Google Places API
De automatisch aanvullen van Google Places is een ongelooflijk snelle en eenvoudige manier voor gebruikers om ontmoetingsplaatsen toe te voegen. Ik gebruik de Yii2 Google Places-extensie van 2amigOS.
In PlaceController.php voegen we een actie toe voor
Create_place_google
:/ ** * Maakt een nieuw plaatsmodel van Google Place * Als de creatie succesvol is, wordt de browser omgeleid naar de 'weergave'-pagina. * @return mixed * / public function actionCreate_place_google () $ model = nieuwe plaats (); if ($ model-> load (Yii :: $ app-> request-> post ())) ... wordt hieronder verder uitgelegd ... else return $ this-> render ('create_place_google', ['model' = > $ model,]);De
/frontend/views/place/create_place_google.php
bestand toont het formulier en initialiseert het JavaScript dat nodig is om automatisch aanvullen te ondersteunen:$gpJsLink= 'http://maps.googleapis.com/maps/api/js?' . http_build_query(array( 'libraries' => 'places', 'sensor' => 'false',)); echo $ this-> registerJsFile ($ gpJsLink); $ options = '"types": ["establishment"], "componentRestrictions": "country": "us"'; echo $ this-> registerJs ("(function () var input = document.getElementById ('place-searchbox'); var options = $ options; searchbox = new google.maps.places.Autocomplete (input, opties); setupListeners ();) (); ", \ yii \ web \ View :: POS_END); // 'setupBounds ('. $ bound_bl. ','. $ bound_tr. '); ?>= Html::encode($this->titel)?>
= $this->render ('_ formPlaceGoogle', ['model' => $ model,])?>Ontwikkelaar Petra Barus heeft een Google Places-extensie verstrekt voor Yii1.x. Voor deze zelfstudie heb ik de basisondersteuning voor Yii2 gecodeerd. Barus was echter zo vriendelijk om een paar dagen later een Yii2-extensie uit te brengen. Ik heb zijn code nog niet geïntegreerd. Dit is zijn nieuwste Yii2 Google Places Autocomplete-extensie.
Hier is de
MapAsset
bundel die ik aan het maken ben voor het bijbehorende JavaScript dat nodig is:Hier is de
_formPlaceGoogle.php
formuliercode:Voer een plaats of bedrijf in dat bekend is bij Google Places:
= $form->field ($ model, 'searchbox') -> textInput (['maxlength' => 255]) -> label ('Plaats')?> = BaseHtml::activeHiddenInput($model, 'name'); ?> = BaseHtml::activeHiddenInput($model, 'google_place_id'); ?> = BaseHtml::activeHiddenInput($model, 'location'); ?> = BaseHtml::activeHiddenInput($model, 'website'); ?> = BaseHtml::activeHiddenInput($model, 'vicinity'); ?> = BaseHtml::activeHiddenInput($model, 'full_address'); ?> = $form->field ($ model, 'place_type') -> dropDownList ($ model-> getPlaceTypeOptions (), ['prompt' => 'Welk type plaats is dit?']) -> label ('Type of Place')?>= Html::submitButton($model->isNewRecord? 'Maken': 'Update', ['class' => $ model-> isNewRecord? 'btn btn-success': 'btn btn-primary'])?>Er is een
zoekbox
veld dat de automatische invoer van de gebruiker accepteert. Er zijn ook een aantal verborgen velden die door onze JavaScript worden geladen met de resultaten van de Google Places-service.Hier is create_place.js die alle "magie" volbrengt:
functie setupListeners () // google.maps.event.addDomListener (venster, 'laden', initialiseren); // zoekvak is de var voor het google places-object dat is gemaakt op de pagina google.maps.event.addListener (searchbox, 'place_changed', function () var place = searchbox.getPlace (); if (! place.geometry) // Informeer de gebruiker dat een plaats niet is gevonden en retourneer. Return; else // migreert JSON-gegevens van Google naar verborgen formuliervelden populateResult (plaats);); functie populateResult (plaats) // verplaatst JSON-gegevens van Google naar verborgen formuliervelden // zodat Yii2 de gegevens $ ('# place-location') kan plaatsen. val (JSON.stringify (plaats ['geometry'] [ 'plaats'])); $ ( '# Place-google_place_id') val (plaats [ 'place_id']).; $ ( '# Place-full_address') val (plaats [ 'formatted_address']).; . $ ( '# Place-website') val (plaats [ 'website']); $ ( '# Place-omgeving') val (plaats [ 'omgeving']).; $ ( '# Plaats') val (plaats [ 'naam']).; loadMap (plaats [ 'geometrie] [locatie] plaats [ 'naam']); function loadMap (gps, naam) var mapcanvas = document.createElement ('div'); mapcanvas.id = 'mapcanvas'; mapcanvas.style.height = '300px'; mapcanvas.style.width = '300px'; mapcanvas.style.border = '1px effen zwart'; document.querySelector ( 'artikel') appendChild (mapcanvas).; var latlng = new google.maps.LatLng (gps ['k'], gps ['D']); var myOptions = zoom: 16, center: latlng, mapTypeControl: false, navigationControlOptions: style: google.maps.NavigationControlStyle.SMALL, mapTypeId: google.maps.MapTypeId.ROADMAP; var map = new google.maps.Map (document.getElementById ("mapcanvas"), myOptions); var marker = new google.maps.Marker (position: latlng, map: map, title: name);De
setupListeners ()
methode verbindt onzezoekbox
naar de service voor automatisch aanvullen van Google Places. Wanneer eenplace_changed
gebeurtenis treedt op,populateResult ()
wordt aangeroepen om de verborgen velden op het formulier te vullen met gegevens van Google en de kaart te laden die wordt weergegeven in de rechterhelft van het formulier.U kunt de browserfoutopsporing gebruiken om de verborgen velden te inspecteren nadat deze zijn ingevuld met formuliergegevens via JavaScript. Deze gegevens worden met het formulier bij indiening gepost zodat we ze kunnen toevoegen aan de plaatsdatabase.
Dit is het resterende element van de PlaceController
Create_place_google
Bewaar actie:public function actionCreate_place_google () $ model = nieuwe plaats (); if ($ model-> load (Yii :: $ app-> request-> post ())) if (Yii :: $ app-> user-> getIsGuest ()) $ model-> created_by = 1; else $ model-> created_by = Yii :: $ app-> user-> getId (); $ form = Yii :: $ app-> request-> post (); $ Model-> save (); // voeg GPS-invoer toe in PlaceGeometry $ model-> addGeometry ($ model, $ form ['Place'] ['location']); return $ this-> redirect (['view', 'id' => $ model-> id]);Het lijkt vrij veel op de
Create_geo
actie. We hebben een afzonderlijke methode met het Place.php-model om de verzameling van locatiegegevens te vereenvoudigen. hier isaddGeometry ()
:openbare functie addGeometry ($ model, $ location) $ x = json_decode ($ location, true); reset ($ x); $ lat = current ($ x); $ lon = volgende ($ x); $ pg = nieuwe PlaceGPS; $ PG-> place_id = $ model-> id; $ pg-> gps = new \ yii \ db \ Expression ("GeomFromText ('Point (". $ lat. "". $ lon. ")')"); $ PG-> save ();Geografische grensfilters instellen voor automatisch aanvullen zoeken
Met de Places Autocomplete-service kunt u ook een geografische grensrechthoek instellen om uw zoekopdracht binnenin te filteren. Wanneer de gebruiker begint te typen, gebruikt de autocomplete alleen plaatsen binnen tien mijl van de plaatsen. Omdat we de huidige locatie van de gebruiker niet hebben ingesteld als een sessievariabele, implementeer ik op dit moment de begrenzende rechthoek niet. Maar we kunnen dit later doen. Hier is een voorbeeld van
setupBounds ()
:functie setupBounds (pt1, pt2, pt3, pt4) defaultBounds = nieuwe google.maps.LatLngBounds (nieuwe google.maps.LatLng (pt1, pt2), nieuwe google.maps.LatLng (pt3, pt4)); searchbox.setBounds (defaultBounds);