Deze tutorial is onderdeel 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. We zullen ook opstartgerelateerde zakelijke problemen aanpakken zodra deze zich voordoen.
In deze zelfstudie gaan we belangrijke gebieden rond de eigen gegevens van de gebruiker uitbreiden voor een breder gebruik via de toepassing:
Alle code voor Meeting Planner is geschreven in het Yii2 Framework voor PHP, die ingebouwde ondersteuning voor I18n heeft. 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 in verschillende benaderingen, aanvullende ideeën of onderwerpen voor toekomstige zelfstudies.
Het doel van contactgegevens is om gebruikers toe te staan telefoonnummers en videoconferentieadressen te verstrekken voor virtuele vergaderingen. Het telefoonnummer is ook nuttig voor en na de vergadering.
Het bouwen van deze functie is relatief eenvoudig. Zoals we in eerdere tutorials deden, gebruikten we Yi's codegenerator, Gii, om het model voor UserContact- en CRUD-bestanden te bouwen.
We hebben ook de navigatiebalk bijgewerkt met een koppeling naar de functie Gebruikerscontact. In frontend / views / layouts / main.php:
$ menuItems [] = ['label' => 'Account', 'items' => [['label' => Yii :: t ('frontend', 'Friends'), 'url' => ['/ vriend '],], [' label '=> Yii :: t (' frontend ',' Contactinformatie '),' url '=> [' / user-contact '],], [' label '=> Yii: : t ('frontend', 'Instellingen'), 'url' => ['/ user-setting'],], ['label' => Yii :: t ('frontend', 'Logout'). ' ('. Yii :: $ app-> gebruiker-> identiteit-> gebruikersnaam.') ',' Url '=> [' / site / logout '],' linkOptions '=> [' data-methode '=>' post ']],],]; echo Nav :: widget (['options' => ['class' => 'navbar-nav navbar-right'], 'items' => $ menuItems,]);
Je kunt ook een link hierboven zien met de functie Gebruikersinstellingen die hieronder wordt beschreven.
Het toevoegen van een vervolgkeuzemenu voor typen is een veelgebruikte modeluitbreiding die we gebruiken om formulieren vriendelijker te maken. Zie de Type contact dropdown hieronder:
Hier zijn de definities van modeltypen en hulpmethoden om vriendelijke vervolgkeuzes toe te staan voor contacttype-services:
class UserContact breidt \ yii \ db \ ActiveRecord const TYPE_OTHER = 0; const TYPE_PHONE = 10; const TYPE_SKYPE = 20; const TYPE_FACEBOOK = 30; const TYPE_GOOGLE = 40; const TYPE_MSN = 50; const TYPE_AIM = 60; const TYPE_YAHOO = 70; const TYPE_ICQ = 80; const TYPE_JABBER = 90; const TYPE_QQ = 100; const TYPE_GADU = 110; ... openbare functie getUserContactType ($ data) $ options = $ this-> getUserContactTypeOptions (); return $ options [$ data]; openbare functie getUserContactTypeOptions () return array (self :: TYPE_PHONE => 'Phone', self :: TYPE_SKYPE => 'Skype', self :: TYPE_OTHER => 'Other', self :: TYPE_FACEBOOK => 'Facebook Messenger' , self :: TYPE_GOOGLE => 'Google Talk', self :: TYPE_MSN => 'MSN Messenger', self :: TYPE_AIM => 'AIM', self :: TYPE_YAHOO => 'Yahoo! Messenger', self :: TYPE_ICQ = > 'ICQ', self :: TYPE_JABBER => 'Jabber', self :: TYPE_QQ => 'QQ', self :: TYPE_GADU => 'Gadu-Gadu',);
Hier is de dropdown geïmplementeerd in de vorm:
= $form->field ($ model, 'contact_type') -> dropDownList ($ model-> getUserContactTypeOptions (), ['prompt' => Yii :: t ('frontend', 'Wat voor soort contact is dit?')]) -> label (Yii :: t ('frontend', 'Type contactpersoon'))?>Deze type helpers zijn algemene constructies in Meeting Planner.
Laten we nu naar de gebruikersinstellingen gaan.
Gebruikersinstellingen
Aangezien Meeting Planner functioneel wordt, is het belangrijk gebruikers toe te staan de functionaliteit aan te passen met een aantal voorkeuren. We bouwen een subsysteem voor gebruikersinstellingen om deze voorkeuren binnen de applicatie te beheren.
De tabel UserSetting wijkt enigszins af van andere modellen omdat elke gebruiker slechts één record heeft en elke record veel velden heeft die de instellingen van een bepaalde gebruiker vertegenwoordigen. Dit is anders dan wanneer gebruikers contactvermeldingen toevoegen, waarbij elke gebruiker veel records heeft die elk een contactpersooninvoer vertegenwoordigen.
Wanneer gebruikers hun instellingen wijzigen, werken we hun individuele instellingenrecord bij. We kunnen ook de velden van de tabel op termijn uitbreiden om extra opties te ondersteunen.
We moeten helperfuncties maken die de instellingen van een gebruiker laden en een standaardrecord voor hen maken als ze niet bestaan.
We moeten ook een formulier maken om het configureren van de instellingen tot een eenvoudig proces te maken. We kunnen gebruik maken van Bootstrap's lay-outs en Yii2 widget-extensies.
Onze eerste gebruikersinstellingen kiezen
Hoewel het aantal instellingen in de loop van de tijd zal toenemen, moeten we enkele van de instellingen bekijken waarmee we willen beginnen:
- Gebruikersprofielfoto (pad naar een bestand dat ze uploaden)
- Herinneringen ontvangen op de dag vóór een vergadering
- Herinneringen ontvangen in de dagen voorafgaand aan een vergadering
- Deel contactgegevens met deelnemers aan de vergadering
- Blokkeer alle e-mail van het systeem
We kunnen de tabel Gebruikersinstelling met een actieve recordmigratie maken en deze uitbreiden met bijgewerkte migraties later.
./ yii migreren / create create_user_setting_table makenDit is de migratie met velden voor onze instellingen - noteer de relatie met de gebruikerstabel:
db-> driverName === 'mysql') $ tableOptions = 'KARAKTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB'; $ this-> createTable ('% user_setting', ['id' => Schema :: TYPE_PK, 'user_id' => Schema :: TYPE_BIGINT. 'NOT NULL', 'filename' => Schema :: TYPE_STRING. 'NOT NULL', 'avatar' => Schema :: TYPE_STRING. 'NOT NULL', 'reminder_eve' => Schema :: TYPE_SMALLINT. 'NOT NULL', 'reminder_hours' => Schema :: TYPE_INTEGER. 'NOT NULL ',' contact_share '=> Schema :: TYPE_SMALLINT.' NOT NULL ',' no_email '=> Schema :: TYPE_SMALLINT.' NOT NULL ',' created_at '=> Schema :: TYPE_INTEGER.' NOT NULL ',' updated_at ' => Schema :: TYPE_INTEGER. 'NOT NULL',], $ tableOptions); $ this-> addForeignKey ('fk_user_setting_user_id', '% user_setting', user_id ',' % user ',' id ',' CASCADE ',' CASCADE '); public function down () $ this-> dropForeignKey ('fk_user_setting_user_id', '% user_setting'); $ This-> dropTable ( '% user_setting');Voer de migratie uit:
./ yii migreer / up Yii Migration Tool (gebaseerd op Yii v2.0.2) Totaal 1 nieuwe migratie die moet worden toegepast: m150124_003721_create_user_setting_table Pas de bovenstaande migratie toe? (ja | nee) [nee]: ja *** toepassen m150124_003721_create_user_setting_table> tabel maken % user_setting ... done (time: 0.017s)> externe sleutel toevoegen fk_user_setting_user_id: % user_setting (user_id) references % gebruiker (id) ... klaar (tijd: 0.009s) *** toegepast m150124_003721_create_user_setting_table (tijd: 0.031s) Migratie succesvol uitgevoerd.De code schrijven
We kunnen Gii gebruiken om het model en de CRUD-bestanden voor ons te genereren. Natuurlijk moeten we de CRUD aanpassen om alleen het record van de huidige gebruiker weer te geven.
Dit zijn de instellingen voor de Model Generator:
Dit zijn de instellingen voor de CRUD-controller:
Wanneer de gebruiker op Instellingen in de navigatiebalk klikt, willen we de pagina met update-instellingen daadwerkelijk weergeven. Laten we een aantal helpers bouwen voor het controleren van de instellingen van de gebruiker en deze aanmaken als deze niet bestaat.
Dit is de indexomleiding naar de updateactie:
/ ** * Standaardpad - omleiden om bij te werken * @return mixed * / public function actionIndex () // geeft record-id terug niet user_id $ id = UserSetting :: initialiseren (Yii :: $ app-> gebruiker-> getId () ); return $ this-> redirect (['update', 'id' => $ id]);De methode Initialiseren maakt een record voor de actieve gebruiker en stelt alle standaardinstellingen in:
public static function initialize ($ user_id) $ us = UserSetting :: find () -> where (['user_id' => $ user_id]) -> one (); if (is_null ($ us)) $ us = nieuwe gebruikersinstelling; $ us-> user_id = $ user_id; $ us-> filename = "; $ us-> avatar ="; $ us-> reminder_eve = self :: SETTING_YES; $ us-> no_email = self :: SETTING_NO; $ us-> contact_share = self :: SETTING_YES; $ us-> reminder_hours = 48; $ Ons-> save (); return $ us-> id;Het instellingenformulier aanpassen
We moeten een deel van de automatisch gegenereerde formuliercode vervangen door selectievakjes en een andere vervolgkeuzelijst (zoals we hierboven met het hierboven beschreven gebruikerscontacttype hebben gedaan). Ik vind het leuk dat de checkbox-functionaliteit van Yii de mogelijkheid bevat om ingestelde en niet-ingestelde waarden te specificeren. Doorgaans keren webformuliervakken een leeg element (bestaande) terug voor waar of keren ze niet terug (bestaat niet) voor onwaar.
= $form->field ($ model, 'reminder_eve') -> checkBox (['label' => Yii :: t ('frontend', 'Laatste herinnering verzenden de dag voor een vergadering'), 'uncheck' => $ model :: SETTING_NO , 'checked' => $ model :: SETTING_YES]); ?> = $form->field ($ model, 'reminder_hours') -> dropDownList ($ model-> getEarlyReminderOptions (), ['prompt' => Yii :: t ('frontend', 'Wanneer wil je je eerste herinnering?')]) - > label (Yii :: t ('frontend', 'Early reminders'))?> = $form->field ($ model, 'contact_share') -> checkbox (['label' => Yii :: t ('frontend', 'Deel mijn contactgegevens met deelnemers aan de vergadering'), 'uncheck' => $ model :: SETTING_NO, 'checked' => $ model :: SETTING_YES]); ?> = $form->field ($ model, 'no_email') -> checkbox (['label' => Yii :: t ('frontend', 'Zet alle e-mail uit'), 'uncheck' => $ model :: SETTING_NO, 'checked' => $ model :: SETTING_YES]); ?>Dit is het eindresultaat:
Laten we doorgaan en UserSetting uitbreiden om profielfoto's te ondersteunen.
Profielafbeeldingen
Om gebruikersfoto's te laten zien op vergaderingspagina's, moeten we gebruikers ondersteunen die een foto uploaden (in de meeste gevallen). Als alternatief kunnen we, tenminste voor standaard, de Gravatar-service gebruiken die een profielfoto koppelt aan het e-mailadres van de gebruiker. Het uploaden en opslaan van bestanden op een server is altijd een gedetailleerde en delicate webontwikkelingstaak die we binnenkort zullen doorlopen.
Bootstrap-tabbladen configureren
Laten we eerst beginnen met het toevoegen van tabbladen aan het gebruikersinstellingenformulier dat algemene instellingen van profielafbeeldingen zal scheiden. Gebruikmakend van de stijldefinities van de Bootstrap-nav-tab, bedenken we dit:
- instellingen
- Upload foto
= $form->field ($ model, 'reminder_eve') -> checkBox (['label' => Yii :: t ('frontend', 'Laatste herinnering verzenden de dag voor een vergadering'), 'uncheck' => $ model :: SETTING_NO , 'checked' => $ model :: SETTING_YES]); ?> = $form->field ($ model, 'reminder_hours') -> dropDownList ($ model-> getEarlyReminderOptions (), ['prompt' => Yii :: t ('frontend', 'Wanneer wil je je eerste herinnering?')]) - > label (Yii :: t ('frontend', 'Early reminders'))?> = $form->field ($ model, 'contact_share') -> checkbox (['label' => Yii :: t ('frontend', 'Deel mijn contactgegevens met deelnemers aan de vergadering'), 'uncheck' => $ model :: SETTING_NO, 'checked' => $ model :: SETTING_YES]); ?> = $form->field ($ model, 'no_email') -> checkbox (['label' => Yii :: t ('frontend', 'Zet alle e-mail uit'), 'uncheck' => $ model :: SETTING_NO, 'checked' => $ model :: SETTING_YES]); ?>= $form->field ($ model, 'image') -> widget (FileInput :: classname (), ['options' => ['accept' => 'image / *'], 'pluginOptions' => ['allowedFileExtensions' => ['jpg', 'gif', 'png']],]); ?>Het ziet er zo uit:
Als er geen geüploade afbeelding is, proberen we standaard de Gravatar van de gebruiker weer te geven.
Nuttige Yii2-extensies voor profielafbeeldingen
Er zijn vier Yii2-extensies die ik wil opnemen voor ondersteuning van profielafbeeldingen:
- Carsten Brandt's Gravatar om gravatars te laten zien
- Kartik Visweswaran-bestandsinvoer ter ondersteuning van uploads van afbeeldingsbestanden
- Yii Stel u voor om afbeeldingen naar verschillende formaten te schalen
- 2Amigos Resource Manager voor latere ondersteuning voor Amazon S3-opslag
Visweswaran en de 2Amigos hebben een aantal Yii2-extensies geproduceerd die super handig zijn en ze bieden over het algemeen ook solide documentatie..
Voeg deze extensies toe aan uw composer.json-bestand:
"cebe / yii2-gravatar": "*", "kartik-v / yii2-widget-fileinput": "*", "yiisoft / yii2-imagine": "*", "2 amigos/yii2-switch-widget": "0.1. *", "2 amigos/yii2-resource-manager -component": "0.1. *"En update componist:
update van de componistGravatar-afbeeldingen gebruiken
Als er geen profielafbeelding is geconfigureerd, geven we de gravatar van de gebruiker weer. De Gravatar-service verwijst naar het e-mailadres van de geregistreerde gebruiker. Hier is de code om de Gravatar weer te geven:
echo \ cebe \ gravatar \ Gravatar :: widget (['email' => common \ models \ User :: find () -> where (['id' => Yii :: $ app-> user-> getId () ]) -> one () -> email, 'options' => ['class' => 'profile-image', 'alt' => common \ models \ User :: find () -> waar (['id '=> Yii :: $ app-> gebruiker-> getId ()]) -> one () -> gebruikersnaam,],' size '=> 128,]);Het zal er ongeveer zo uitzien. Als de gebruiker een Gravatar heeft geconfigureerd, ziet u de gekozen afbeelding.
Een profielafbeelding uploaden
Voor het uploaden van afbeeldingen gebruiken we de uitstekende widget voor bestandsinvoer van Kartik. Hij biedt ook een erg leuke uitleg over hoe het te gebruiken.
Hier is de code voor ons updateformulier dat de widget in het deelvenster Uploadfoto toont:
= $form->field ($ model, 'image') -> widget (FileInput :: classname (), ['options' => ['accept' => 'image / *'], 'pluginOptions' => ['allowedFileExtensions' => ['jpg', 'gif', 'png']],]); ?>De bovenkant van het formulier bevat enctype voor uit meerdere delen bestaande formuliergegevens:
[ 'Enctype' => 'multipart / form-data']]); // belangrijk?>Het formulier ziet er zo uit:
We voegen ook regels toe aan het UserSetting-model om uploads te beperken tot jpg, gif en png en om de uploadgrootte te beperken tot 100kb.
public function rules () return [[[user_id ',],' required '], [[' user_id ',],' unique '], [[' image '],' safe '], [[' afbeelding '],' file ',' extensions '=>' jpg, gif, png '], [[' afbeelding '],' file ',' maxSize '=>' 100000 '], [[' bestandsnaam ',' avatar '],' string ',' max '=> 255], [[' user_id ',' reminder_eve ',' reminder_hours ',' contact_share ',' no_email ',' created_at ',' updated_at '],' integer '] ,];Overigens hebben de Yii2-validators een verbazingwekkende hoeveelheid mogelijkheden voor veel voorkomende activiteiten die webontwikkelaars normaal gesproken met de hand kunnen bouwen. Ik zal dit in een toekomstige zelfstudie Programming With Yii2 proberen te verkennen.
Hier is de code die de post behandelt van het updateformulier. Over het algemeen is het waarschijnlijk een goed idee om meer van deze code te herwerken in modelmethoden en de hoeveelheid complexiteit in de controllers te verminderen.
if ($ model-> load (Yii :: $ app-> request-> post ())) $ image = UploadedFile :: getInstance ($ model, 'image'); if (! is_null ($ afbeelding)) // opslaan met afbeelding // sla de bronbestandsnaam $ model-> bestandsnaam = $ afbeelding-> naam op; $ ext = end ((explode (".", $ image-> name))); // genereer een unieke bestandsnaam om dubbele bestandsnamen te voorkomen $ model-> avatar = Yii :: $ app-> security-> generateRandomString (). ". $ ext"; // het pad om het bestand op te slaan, u kunt een uploadpad // instellen in Yii :: $ app-> params (zoals gebruikt in het onderstaande voorbeeld) Yii :: $ app-> params ['uploadPath'] = Yii :: $ app -> basePath. '/ Web / uploads / avatar /'; $ path = Yii :: $ app-> params ['uploadPath']. $ Model-> avatar; $ model-> user_id = Yii :: $ app-> gebruiker-> getId (); if ($ model-> update ()) $ image-> saveAs ($ path);De afbeeldingen moeten worden opgeslagen waar ze kunnen worden bekeken door de webserver. Ik heb een uploads / avatar-map gemaakt in de / frontend / web-tree.
Afbeeldingen schalen met Imagine
We willen de afbeelding eigenlijk in drie formaten opslaan: volledige grootte, een klein vierkant voor weergave in de navigatiebalk of lijstweergaven en een middelgroot vierkant voor vergaderpagina's.
We gebruiken de Yii2 Imagine-extensie om afbeeldingen te schalen; het breidt de Imagine beeldmanipulatiebibliotheek voor PHP uit.
Dit is de code die de extra afbeeldingsgrootten schaalt en opslaat:
$ Beeld-> SaveAs ($ path); Afbeelding :: thumbnail (Yii :: $ app-> params ['uploadPath']. $ Model-> avatar, 120, 120) -> opslaan (Yii :: $ app-> params ['uploadPath']. 'Sqr_' . $ model-> avatar, ['kwaliteit' => 50]); Afbeelding :: thumbnail (Yii :: $ app-> params ['uploadPath']. $ Model-> avatar, 30, 30) -> opslaan (Yii :: $ app-> params ['uploadPath']. 'Sm_' . $ model-> avatar, ['kwaliteit' => 50]);Dit is het voltooide formulier met de vierkante afbeelding op de pagina met het gebruikersprofiel:
Ongebruikte afbeeldingen opruimen
Wanneer gebruikers een nieuwe foto uploaden, moeten we de oude afbeelding en de bijbehorende geschaalde exemplaren verwijderen. We zullen de controller uitbreiden om een nieuwe verwijdermethode aan te roepen:
$ image = UploadedFile :: getInstance ($ model, 'image'); if (! is_null ($ afbeelding)) // path to existing image for post-delete $ image_delete = $ model-> avatar; ... $ model-> deleteImage (Yii :: $ app-> params ['uploadPath'], $ image_delete);Dit is de methode deleteImage in UserSetting:
public function deleteImage ($ path, $ filename) $ file = array (); $ bestand [] = $ pad. $ bestandsnaam; $ file [] = $ path.'sqr _ '. $ bestandsnaam; $ file [] = $ path.'sm _ '. $ bestandsnaam; foreach ($ bestand als $ f) // controleer of bestand op server bestaat als (! empty ($ f) && file_exists ($ f)) // verwijder bestand ontkoppelen ($ f);Amazon S3 gebruiken om afbeeldingen op te slaan
Het opslaan van door gebruikers geüploade afbeeldingen op onze webserver kan complexiteit veroorzaken. Dit betekent dat we niet alleen een back-up van MySQL moeten maken, maar ook altijd een back-up moeten maken van een deel van het bestandssysteem. Het kan serverherstelbewerkingen en -migraties bemoeilijken. Het laadt ook onze LAMP-stapel wanneer afbeeldingen worden geladen.
Het gebruik van Amazon S3 scheidt deze taak van uw primaire webserver en kan de prestaties verbeteren en het serverbeheer in de loop van de tijd vereenvoudigen, met name wat betreft draagbaarheid, schaalbaarheid en upgrades. Ik zal het uploaden en toegang krijgen tot bestanden van Amazon S3 bespreken in een toekomstige zelfstudie.
Wat is het volgende?
Ik hoop dat je enkele toegepaste aspecten van Yii, ActiveRecord, Bootstrap, formulieren, bestandsupload en beeldmanipulatie hebt geleerd. Ik heb genoten van het werken met enkele van de nieuwe JQuery-widgets die beschikbaar zijn als Yii-extensies. Kijk uit voor komende tutorials in onze Building Your Startup With PHP-serie - er komen veel leuke functies aan. Sterker nog, we komen dichterbij bij het kunnen plannen van onze eerste vergadering!
Aarzel niet om uw vragen en opmerkingen hieronder toe te voegen; Ik neem over het algemeen deel aan de discussies. Je kunt me ook bereiken via Twitter @reifman of mij rechtstreeks een e-mail sturen.
Gerelateerde Links
- Programmeren met Yii2: Aan de slag
- Introductie tot het Yii Framework
- De Yii2 Developer Exchange, de site met de tips voor de auteur voor Yii2