Vietnamese (Tiếng Việt) translation by Thai An (you can also view the original English article)



Hướng dẫn này là một phần của loạt bài Xây dựng Khởi nghiệp Với PHP của bạn trên Tuts. Trong loạt bài này, tôi hướng dẫn bạn thông qua việc khởi chạy một khởi động từ khái niệm này sang thực tế bằng ứng dụng Meeting Planner của tôi như một ví dụ thực tế về cuộc sống. Mỗi bước trên đường đi, chúng tôi sẽ phát hành mã Cuộc họp lập kế hoạch làm ví dụ nguồn mở mà bạn có thể học hỏi. Chúng tôi cũng sẽ giải quyết các vấn đề kinh doanh liên quan đến khởi động khi chúng phát sinh.
Trong hướng dẫn này, chúng ta sẽ xây dựng các vùng chính xung quanh dữ liệu của chính người dùng để sử dụng rộng rãi hơn thông qua ứng dụng:
- Chi tiết liên lạc: số điện thoại của người dùng và địa chỉ hội nghị truyền hình cho các cuộc họp ảo
- Cài đặt người dùng: để theo dõi các tùy chọn của người dùng trong ứng dụng
- Ảnh tiểu sử: cho phép người dùng tải lên ảnh mà chúng tôi có thể sử dụng trên các trang họp
Tất cả mã cho Công cụ lập kế hoạch cuộc họp được viết trong Khung công tác Yii2 cho PHP, đã hỗ trợ sẵn cho I18n. Nếu bạn muốn tìm hiểu thêm về Yii2, hãy xem loạt bài Lập trình Với Yii2 của chúng tôi tại Tuts.
Chỉ cần một lời nhắc nhở, tôi tham gia vào các chủ đề bình luận dưới đây. Tôi đặc biệt quan tâm nếu bạn có các cách tiếp cận khác nhau, ý tưởng bổ sung hoặc muốn đề xuất các chủ đề cho hướng dẫn trong tương lai.
Chi tiết liên lạc



Mục đích của chi tiết liên hệ là cho phép người dùng cung cấp số điện thoại và địa chỉ hội nghị video cho các cuộc họp ảo. Số điện thoại cũng hữu ích trước và sau cuộc họp.
Xây dựng tính năng này tương đối đơn giản. Như chúng ta đã làm trong các hướng dẫn trước, chúng tôi đã sử dụng trình tạo mã của Yii, Gii, để xây dựng mô hình cho các tệp UserContact và CRUD.
Chúng tôi cũng đã cập nhật thanh điều hướng để bao gồm liên kết đến tính năng Liên hệ người dùng. Trong giao diện người dùng / lượt xem / bố cục / main.php:
$menuItems[] = [ 'label' => 'Account', 'items' => [ [ 'label' => Yii::t('frontend','Friends'), 'url' => ['/friend'], ], [ 'label' => Yii::t('frontend','Contact information'), 'url' => ['/user-contact'], ], [ 'label' => Yii::t('frontend','Settings'), 'url' => ['/user-setting'], ], [ 'label' => Yii::t('frontend','Logout').' (' . Yii::$app->user->identity->username . ')', 'url' => ['/site/logout'], 'linkOptions' => ['data-method' => 'post'] ], ], ]; echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 'items' => $menuItems, ]);
Bạn cũng có thể thấy liên kết ở trên với tính năng Cài đặt người dùng sẽ được mô tả thêm bên dưới.
Thêm một lựa chọn thả xuống cho các loại là một phần mở rộng mô hình phổ biến, chúng tôi sử dụng để làm cho các hình thức thân thiện hơn. Xem danh sách thả xuống Loại liên hệ bên dưới:



Dưới đây là các định nghĩa kiểu mô hình và các phương thức trợ giúp để cho phép các trình đơn thả xuống thân thiện cho các dịch vụ kiểu liên hệ:
class UserContact extends \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; ... public function getUserContactType($data) { $options = $this->getUserContactTypeOptions(); return $options[$data]; } public function 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', ); }
Dưới đây là danh sách thả xuống được triển khai trong biểu mẫu:
<div class="user-contact-form"> <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'contact_type') ->dropDownList( $model->getUserContactTypeOptions(), ['prompt'=>Yii::t('frontend','What type of contact is this?')] )->label(Yii::t('frontend','Type of Contact')) ?>
Những người trợ giúp kiểu này là các cấu trúc phổ biến trong suốt Công cụ lập kế hoạch cuộc họp.
Bây giờ, hãy chuyển sang cài đặt người dùng.
Thiết lập người dùng
Khi Công cụ lập kế hoạch cuộc họp phát triển về chức năng, điều quan trọng là cho phép người dùng tùy chỉnh chức năng với một tập hợp các tùy chọn. Chúng tôi xây dựng một hệ thống con cài đặt người dùng để quản lý các tùy chọn này trong ứng dụng.
Bảng UserSetting hơi khác so với các mô hình khác ở chỗ mỗi người dùng chỉ có một bản ghi và mỗi bản ghi có nhiều trường đại diện cho một cài đặt của người dùng cụ thể. Điều này khác với khi người dùng thêm mục nhập liên hệ, trong đó mỗi người dùng có nhiều bản ghi mà mỗi người đại diện cho một mục nhập liên hệ.
Khi người dùng sửa đổi cài đặt của họ, chúng tôi cập nhật hồ sơ cài đặt cá nhân của họ. Chúng tôi cũng có thể mở rộng các trường của bảng theo thời gian để hỗ trợ các tùy chọn bổ sung.
Chúng ta sẽ cần tạo các hàm trợ giúp để tải các thiết lập của người dùng và tạo một bản ghi mặc định cho chúng nếu chúng không tồn tại.
Chúng tôi cũng cần tạo một biểu mẫu để định cấu hình cài đặt một cách dễ dàng. Chúng tôi có thể sử dụng bố cục của Bootstrap và tiện ích mở rộng tiện ích Yii2.
Chọn cài đặt người dùng đầu tiên của chúng tôi
Mặc dù số lượng cài đặt sẽ tăng theo thời gian, chúng ta hãy xem xét một số cài đặt chúng tôi muốn bắt đầu bằng:
- Ảnh hồ sơ người dùng (đường dẫn đến tệp họ sẽ tải lên)
- Nhận lời nhắc vào một ngày trước cuộc họp
- Nhận lời nhắc trong những ngày dẫn đến cuộc họp
- Chia sẻ chi tiết liên lạc với những người tham gia cuộc họp
- Chặn tất cả email từ hệ thống
Chúng ta có thể tạo bảng User Setting với một Active Record Migration và mở rộng nó với các di chuyển được cập nhật sau này.
./yii migrate/create create_user_setting_table
Đây là di chuyển với các trường cho cài đặt của chúng tôi — lưu ý mối quan hệ với bảng Người dùng:
<?php use yii\db\Schema; use yii\db\Migration; class m150124_003721_create_user_setting_table extends Migration { public function up() { $tableOptions = null; if ($this->db->driverName === 'mysql') { $tableOptions = 'CHARACTER 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}}'); } }
Chạy di chuyển:
./yii migrate/up Yii Migration Tool (based on Yii v2.0.2) Total 1 new migration to be applied: m150124_003721_create_user_setting_table Apply the above migration? (yes|no) [no]:yes *** applying m150124_003721_create_user_setting_table > create table {{%user_setting}} ... done (time: 0.017s) > add foreign key fk_user_setting_user_id: {{%user_setting}} (user_id) references {{%user}} (id) ... done (time: 0.009s) *** applied m150124_003721_create_user_setting_table (time: 0.031s) Migrated up successfully.
Viết mã
Chúng ta có thể sử dụng Gii để tạo ra các mô hình và các tập tin CRUD cho chúng ta. Tất nhiên, chúng ta sẽ phải sửa đổi CRUD để chỉ hiển thị bản ghi của người dùng hiện tại.
Dưới đây là các cài đặt cho Trình tạo mô hình:



Dưới đây là các cài đặt cho bộ điều khiển CRUD:



Khi người dùng nhấp vào Cài đặt trong thanh điều hướng, chúng tôi muốn thực sự hiển thị trang cài đặt cập nhật. Hãy xây dựng một số người trợ giúp để kiểm tra hồ sơ cài đặt của người dùng và tạo nó nếu nó không tồn tại.
Dưới đây là chuyển hướng chỉ mục đến hành động cập nhật:
/** * Default path - redirect to update * @return mixed */ public function actionIndex() { // returns record id not user_id $id = UserSetting::initialize(Yii::$app->user->getId()); return $this->redirect(['update', 'id' => $id]); }
Phương thức Initialize tạo một bản ghi cho người dùng đang hoạt động và thiết lập tất cả các thiết lập mặc định:
public static function initialize($user_id) { $us = UserSetting::find()->where(['user_id'=>$user_id])->one(); if (is_null($us)) { $us=new UserSetting; $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; $us->save(); } return $us->id; }
Tùy chỉnh biểu mẫu cài đặt
Chúng tôi phải thay thế một số mã biểu mẫu được tạo tự động để bao gồm các hộp kiểm và một danh sách thả xuống khác (như chúng tôi đã làm với UserContact Type ở trên). Tôi thích chức năng hộp kiểm của Yii bao gồm khả năng xác định các giá trị thiết lập và bỏ đặt định. Thông thường, các hộp kiểm biểu mẫu web trả lại một phần tử trống (tồn tại) cho đúng hoặc không trả lại (không tồn tại) cho sai.
<?= $form->field($model, 'reminder_eve')->checkBox(['label' => Yii::t('frontend','Send final reminder the day before a meeting'), 'uncheck' => $model::SETTING_NO, 'checked' => $model::SETTING_YES]); ?> <?= $form->field($model, 'reminder_hours') ->dropDownList( $model->getEarlyReminderOptions(), ['prompt'=>Yii::t('frontend','When would you like your early reminder?')] )->label(Yii::t('frontend','Early reminders')) ?> <?= $form->field($model, 'contact_share')->checkbox(['label' =>Yii::t('frontend','Share my contact information with meeting participants'),'uncheck' => $model::SETTING_NO, 'checked' => $model::SETTING_YES]); ?> <?= $form->field($model, 'no_email')->checkbox(['label' =>Yii::t('frontend','Turn off all email'),'uncheck' => $model::SETTING_NO, 'checked' => $model::SETTING_YES]); ?>
Đây là kết quả cuối cùng:



Hãy tiếp tục và mở rộng UserSetting để hỗ trợ ảnh tiểu sử.
Hình ảnh hồ sơ
Để hiển thị ảnh người dùng hiển thị trên các trang họp, chúng tôi cần hỗ trợ người dùng tải ảnh lên (trong hầu hết các trường hợp). Ngoài ra, ít nhất là theo mặc định, chúng tôi có thể sử dụng dịch vụ Gravatar liên kết ảnh tiểu sử theo địa chỉ email của người dùng. Tải lên và lưu tệp trên máy chủ luôn là nhiệm vụ phát triển web chi tiết và tinh tế mà chúng tôi sẽ giới thiệu trong thời gian ngắn.
Cấu hình các tab Bootstrap
Trước tiên, hãy bắt đầu bằng cách thêm các tab vào biểu mẫu cài đặt người dùng sẽ tách cài đặt chung khỏi hình ảnh hồ sơ. Sử dụng các định nghĩa kiểu tab navstrap, chúng tôi đưa ra điều này:
<!-- Nav tabs --> <ul class="nav nav-tabs" role="tablist"> <li class="active"><a href="#general" role="tab" data-toggle="tab">Settings</a></li> <li><a href="#photo" role="tab" data-toggle="tab">Upload Photo</a></li> </ul> <!-- Tab panes --> <div class="tab-content"> <div class="tab-pane active vertical-pad" id="general"> <?= $form->field($model, 'reminder_eve')->checkBox(['label' => Yii::t('frontend','Send final reminder the day before a meeting'), 'uncheck' => $model::SETTING_NO, 'checked' => $model::SETTING_YES]); ?> <?= $form->field($model, 'reminder_hours') ->dropDownList( $model->getEarlyReminderOptions(), ['prompt'=>Yii::t('frontend','When would you like your early reminder?')] )->label(Yii::t('frontend','Early reminders')) ?> <?= $form->field($model, 'contact_share')->checkbox(['label' =>Yii::t('frontend','Share my contact information with meeting participants'),'uncheck' => $model::SETTING_NO, 'checked' => $model::SETTING_YES]); ?> <?= $form->field($model, 'no_email')->checkbox(['label' =>Yii::t('frontend','Turn off all email'),'uncheck' => $model::SETTING_NO, 'checked' => $model::SETTING_YES]); ?> </div> <div class="tab-pane vertical-pad" id="photo"> <?= $form->field($model, 'image')->widget(FileInput::classname(), [ 'options' => ['accept' => 'image/*'], 'pluginOptions'=>['allowedFileExtensions'=>['jpg','gif','png']], ]); ?> </div> <!-- end of upload photo tab --> </div>
Nó trông như thế này:



Theo mặc định, nếu không có hình ảnh được tải lên, chúng tôi sẽ cố gắng hiển thị Gravatar của người dùng.
Tiện ích mở rộng Yii2 hữu ích cho hình ảnh hồ sơ
Có bốn tiện ích mở rộng Yii2 mà tôi muốn bao gồm để hỗ trợ hình ảnh hồ sơ:
- Gravatar Carsten Brandt để trưng bày gravatars
- Đầu vào tệp Kartik Visweswaran để hỗ trợ tải lên tệp hình ảnh
- Yii Hãy tưởng tượng để chia tỷ lệ hình ảnh thành các kích thước khác nhau
- Trình quản lý tài nguyên 2Amigos để hỗ trợ sau cho bộ nhớ Amazon S3
Visweswaran và 2Amigos đã tạo ra một số phần mở rộng Yii2 siêu hữu ích và chúng thường cung cấp tài liệu vững chắc.
Vì vậy, hãy thêm các tiện ích mở rộng này vào tệp composer.json của bạn:
"cebe/yii2-gravatar": "*", "kartik-v/yii2-widget-fileinput": "*", "yiisoft/yii2-imagine": "*", "2amigos/yii2-switch-widget": "0.1.*", "2amigos/yii2-resource-manager-component": "0.1.*"
Và cập nhật nhà soạn nhạc:
composer update
Sử dụng Gravatar Images
Nếu không có cấu hình ảnh hồ sơ nào, chúng tôi sẽ hiển thị gravatar của người dùng. Dịch vụ Gravatar tham chiếu đến địa chỉ email của người dùng đã đăng ký. Đây là mã để hiển thị Gravatar:
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()->where(['id'=>Yii::$app->user->getId()])->one()->username, ], 'size' => 128, ]);
Nó sẽ trông như thế này Nếu người dùng đã định cấu hình Gravatar, bạn sẽ thấy hình ảnh đã chọn của họ.



Tải lên một hình ảnh hồ sơ
Để tải lên hình ảnh, chúng tôi sẽ sử dụng tiện ích nhập tệp xuất sắc của Kartik. Ông cũng cung cấp một giải thích rất tốt đẹp về cách sử dụng nó.
Đây là mã cho biểu mẫu cập nhật của chúng tôi hiển thị tiện ích con trong ngăn Tải ảnh lên:
<div class="tab-pane vertical-pad" id="photo"> <?= $form->field($model, 'image')->widget(FileInput::classname(), [ 'options' => ['accept' => 'image/*'], 'pluginOptions'=>['allowedFileExtensions'=>['jpg','gif','png']], ]); ?> </div> <!-- end of upload photo tab -->
Phần đầu của biểu mẫu bao gồm mã hóa cho dữ liệu biểu mẫu nhiều phần:
<div class="user-setting-form"> <?php $form = ActiveForm::begin([ 'options'=>['enctype'=>'multipart/form-data']]); // important ?>
Biểu mẫu có dạng như sau:



Chúng tôi cũng thêm quy tắc vào mô hình UserSetting để hạn chế tải lên jpg, gif và png và giới hạn kích thước tải lên 100kb.
public function rules() { return [ [['user_id', ], 'required'], [['user_id', ], 'unique'], [['image'], 'safe'], [['image'], 'file', 'extensions'=>'jpg, gif, png'], [['image'], 'file', 'maxSize'=>'100000'], [['filename', 'avatar'], 'string', 'max' => 255], [['user_id', 'reminder_eve', 'reminder_hours', 'contact_share', 'no_email', 'created_at', 'updated_at'], 'integer'], ]; }
Nhân tiện, các trình duyệt tính hợp lệ của Yii2 có một phạm vi khả năng tuyệt vời cho nhiều nhà phát triển web hoạt động phổ biến thường có thể xây dựng bằng tay. Tôi sẽ cố gắng để khám phá điều này trong một lập trình tương lai Với hướng dẫn Yii2.
Đây là mã xử lý bài đăng từ biểu mẫu cập nhật. Nói chung, nó có thể là một ý tưởng tốt để làm lại thêm mã này vào các phương thức mô hình và giảm lượng phức tạp trong các bộ điều khiển.
if ($model->load(Yii::$app->request->post())) { $image = UploadedFile::getInstance($model, 'image'); if (!is_null($image)) { // save with image // store the source file name $model->filename = $image->name; $ext = end((explode(".", $image->name))); // generate a unique file name to prevent duplicate filenames $model->avatar = Yii::$app->security->generateRandomString().".{$ext}"; // the path to save file, you can set an uploadPath // in Yii::$app->params (as used in example below) Yii::$app->params['uploadPath'] = Yii::$app->basePath . '/web/uploads/avatar/'; $path = Yii::$app->params['uploadPath'] . $model->avatar; $model->user_id = Yii::$app->user->getId(); if($model->update()){ $image->saveAs($path);
Các hình ảnh cần phải được lưu trữ nơi chúng có thể được xem bởi máy chủ web. Tôi đã tạo một thư mục upload / avatar trong cây / frontend / web.
Chia tỷ lệ hình ảnh với hình ảnh
Chúng tôi thực sự muốn lưu trữ hình ảnh theo ba kích thước: kích thước đầy đủ, một hình vuông nhỏ để hiển thị trong thanh điều hướng hoặc chế độ xem danh sách và một hình vuông có kích thước trung bình cho các trang họp.
Chúng tôi sẽ sử dụng tiện ích mở rộng Yii2 Imagine để chia tỷ lệ hình ảnh; nó mở rộng thư viện thao tác hình ảnh Imagine cho PHP.
Dưới đây là mã quy mô và lưu các kích thước hình ảnh bổ sung:
$image->saveAs($path); Image::thumbnail(Yii::$app->params['uploadPath'].$model->avatar, 120, 120) ->save(Yii::$app->params['uploadPath'].'sqr_'.$model->avatar, ['quality' => 50]); Image::thumbnail(Yii::$app->params['uploadPath'].$model->avatar, 30, 30) ->save(Yii::$app->params['uploadPath'].'sm_'.$model->avatar, ['quality' => 50]);
Đây là biểu mẫu đã hoàn thành hiển thị hình ảnh vuông trên trang hồ sơ người dùng:



Làm sạch hình ảnh không sử dụng
Khi người dùng tải lên một ảnh mới, chúng tôi cần xóa hình ảnh cũ và các bản sao được chia tỷ lệ kèm theo của nó. Chúng tôi sẽ mở rộng bộ điều khiển để gọi phương thức xóa mới:
$image = UploadedFile::getInstance($model, 'image'); if (!is_null($image)) { // path to existing image for post-delete $image_delete = $model->avatar; ... $model->deleteImage(Yii::$app->params['uploadPath'],$image_delete);
Đây là phương pháp deleteImage trong UserSetting:
public function deleteImage($path,$filename) { $file =array(); $file[] = $path.$filename; $file[] = $path.'sqr_'.$filename; $file[] = $path.'sm_'.$filename; foreach ($file as $f) { // check if file exists on server if (!empty($f) && file_exists($f)) { // delete file unlink($f); } } }
Sử dụng Amazon S3 để lưu trữ hình ảnh
Lưu trữ hình ảnh do người dùng tải lên trên máy chủ web của chúng tôi có thể tạo ra sự phức tạp. Nó có nghĩa là ngoài việc sao lưu MySQL, chúng ta cũng cần luôn sao lưu một phần của hệ thống tập tin. Nó có thể làm phức tạp các hoạt động khôi phục máy chủ và di chuyển. Nó cũng đặt một tải trên ngăn xếp LAMP của chúng tôi bất cứ khi nào hình ảnh được tải.
Sử dụng Amazon S3 tách nhiệm vụ này khỏi máy chủ web chính của bạn và có thể cải thiện hiệu suất và đơn giản hóa việc quản lý máy chủ theo thời gian, đặc biệt là về tính di động, khả năng mở rộng và nâng cấp. Tôi sẽ xem xét việc tải lên và truy cập các tệp từ Amazon S3 trong một hướng dẫn trong tương lai.
Cái gì tiếp theo?
Tôi hy vọng bạn đã học được một số khía cạnh áp dụng của Yii, ActiveRecord, Bootstrap, biểu mẫu, tải lên tệp và thao tác hình ảnh. Tôi thích làm việc với một số tiện ích JQuery mới có sẵn dưới dạng tiện ích mở rộng Yii. Xem các hướng dẫn sắp tới trong loạt bài Xây dựng Khởi nghiệp Với PHP của bạn — có rất nhiều tính năng thú vị sắp ra mắt. Trong thực tế, chúng tôi đang tiến gần hơn đến việc có thể lên lịch cuộc họp đầu tiên của mình!
Xin vui lòng thêm câu hỏi và bình luận của bạn dưới đây; Tôi thường tham gia vào các cuộc thảo luận. Bạn cũng có thể liên hệ với tôi trên Twitter @reifman hoặc gửi email trực tiếp cho tôi.
Liên kết liên quan
- Lập trình với Yii2: Bắt đầu
- Giới thiệu về khung công tác Yii
- Trao đổi nhà phát triển Yii2, trang mẹo của tác giả cho Yii2