12/08/2018, 12:59

[Parse]Bước cơ bản làm việc với Parse

Theo phương thức truyền thống thì khi lập trình viên mobile khi tạo ra 1 ứng dụng mà cần liên quan đến dữ liệu thì sẽ cần phải kèm theo một web developer để tạo 1 backend để có thể kết nối đến cơ sơ dữ liệu cũng như làm việc trên nó. Như vậy các lập trình viên di động sẽ cần phải đợi chờ backend và ...

Theo phương thức truyền thống thì khi lập trình viên mobile khi tạo ra 1 ứng dụng mà cần liên quan đến dữ liệu thì sẽ cần phải kèm theo một web developer để tạo 1 backend để có thể kết nối đến cơ sơ dữ liệu cũng như làm việc trên nó. Như vậy các lập trình viên di động sẽ cần phải đợi chờ backend và viết ra những service phục vụ cho công việc yêu cầu. Nếu cứ theo mô hình như vậy khi làm gì cũng phải phụ thuộc vào web develop và khi cần chỉnh sửa gì thì chỉ có đợi backend và đôi khi việc backend trả giá trị như thế nào thì chỉ biết như vậy. Điều này khiến cho các lập trình viên mobile khó linh động và luôn phải chờ đợi. Điều này giờ đã được giải quyết bằng cách các lập trình viên mobile sẽ làm việc trực tiếp qua 1 serice trung gian chuyên xử lý dự liệu là Parse. Trong bài viết này tôi xin hướng dẫn các bạn 1 cách cơ bản làm quen với việc sử dụng Parse cho việc lập trình cho mobile (Android) và Backend (Php).

Trước khi đi vào chi tiết tôi xin giới thiệu qua cho các bạn Parse là gì và hỗ trợ gì cho chúng ta. Bạn có thể vào trực tiếp trang chủ của Parse để có thể tìm hiểu cũng như đăng ký cho mình 1 tài khoản hoàn toàn miễn phí. Khi vào trang chủ của Parse chúng ta có thể thấy Parse cung cấp cho chúng ta 3 dịch vụ chính đó là:

  1. Xử lý dữ liệu: Sẽ cung cấp cho ứng dụng của bạn lưu trữ dữ liệu, làm việc dễ dàng với cơ sở dữ liệu đồng thời có thể dễ dàng trao đổi dữ liệu từ server đến Parse.
  2. Push notification: Đây là 1 dịch vụ rất tiện lợi cho các nhà phát triển mobile vì Parse cung cấp sẵn việc Push notification một cách tiện lợi và vô cùng đơn giản (Tôi sẽ nói rõ hơn khi hướng dẫn làm việc với Android).
  3. Thống kê: Đây là dịch vụ để nhà phát triển nắm bắt được sự phát triển của ứng dụng mình làm ra để có những phương án phát triển tiếp theo.

Một điều đáng nói nữa là Parse cung cấp cho lập trình viên bộ thư viện đầy đủ cho gần như toàn bộ các ngôn ngữ lập trình cho Mobile (iOs, Android, Windows Phone, Unity, Xamarin, ..), cho web hay ứng dụng desktop (OsX, Windows, Php, Unity,..). Thực sự mọi người lập trình viên đều có thể làm việc với Parse vì được cung cấp tài liệu hướng dẫn đầy đủ cho từng ngôn ngữ lập trình tại đây.

Để bắt tay vào làm quen với Parse tôi sẽ đưa ra 1 yêu cầu khá đơn giản đó là sẽ tạo ra 1 Object là Blog gồm các trường là name - author - content. Công việc yêu cầu phía backend (Php) thì cần quản trị được các Blog này và khi thêm mới sẽ gửi 1 thông báo về các client về Blog mới được thêm này. Còn về phía Client (Android App) sẽ hiển thị các Blog và hiển thị thông báo và click vào đó thì sẽ ra list các Blog gồm cả Blog mới được thêm.

Tạo app mới từ Parse

Sau khi đăng ký mới 1 tài khoản chúng ta đã bắt đầu có thể sử dụng Parse cho công việc của mình, đầu tiên ta cần tạo 1 app mới. Sau khi App mới được tạo ra thì tại màn hình quản lý App ta vào phần Setting rồi vào phần Keys.

Tại đây App sẽ sinh ra các Key cho mục đích làm việc của lập trình. Ví dụ như Backend Php sẽ cần đến Application Id, REST API KeyMaster Key, Android thì cần Application IDClinet Key

Backend

Để cài đặt và sử dụng Parse cho Php ta cần phải cài Composer trước sau đó tạo 1 file là composer.json có nội dung như sau:

{
    "require": {
       "parse/php-sdk" : "1.1.*"
    }
}

Sau đó download Parse bằng lệnh composer install . Sau khi chạy xong thì ta sẽ có thư viện Parse trong folder Vendor. Và ở đây để làm việc với Parse, tôi tạo thêm 1 file có tên là parse.php trong folder vendor vừa sinh ra. Nội dung file đó như sau

<?php
require "autoload.php";
//Load toàn bộ thư viện và các hàm của Parse
use ParseParseObject;
use ParseParseQuery;
use ParseParseACL;
use ParseParsePush;
use ParseParseUser;
use ParseParseInstallation;
use ParseParseException;
use ParseParseAnalytics;
use ParseParseFile;
use ParseParseCloud;
use ParseParseClient;

class Parse
{
  //Để chạy được Parse thì cần 3 thông số được nhập ở dưới đây là app_id, rest_id và master_id
  private $_app_id = ';
  private $_rest_key = ';
  private $_master_key = ';
  private $_object_name = ';

  //Khởi tạo class với tên của Object, tên Object có thể để trống
  public function __construct($sObject = ')
  {
      $this->_object_name = $sObject;
      $this->init();
  }
  //Hàm khởi tạo Parse
  public function init()
  {
      ParseClient::initialize($this->_app_id, $this->_rest_key, $this->_master_key);
  }
  /**
  Hàm gửi push notification đến mọi máy di động có sử dụng đến Parse
  $sMessage: Là nội dung thông báo gửi đến các máy client.
  Parse có cung cấp cho người dùng gửi push notification đến những người dùng chọn lọc và có 2 cách chọn lọc là Chanel và Advance Targeting.
  Ở đây là dùng cách Advancer Targetting với việc gửi cho tất cả các máy
  */
  public function sendPushNotification($sMessage)
  {
      $data = array("alert" => $sMessage);
      $this->init();
      $query = ParseInstallation::query();
      ParsePush::send(array(
        "where" => $query,
        "data" => $data
      ));
  }
  /**
  Hàm thêm dữ liệu vào object, dữ liệu truyền vào là các mảng với key là filed và value là giá trị còn đưa vào
  Hàm trả về id của object do Parse sinh ra
  */
  public function add($aVals = [])
  {
      $oObject = new ParseObject($this->_object_name);
      foreach ($aVals as $sField => $val) {
          $oObject->set($sField, $val);
      }
      try {
          $oObject->save();
          return $oObject->getObjectId();
      } catch (ParseException $ex) {
          return false;
      }
  }

  /**
    Hàm lấy tất cả dữ liệu của 1 Object
  */
  public function getList()
  {
      $query = new ParseQuery($this->_object_name);
      $results = $query->find();
      return $results;
  }
  /**
    Hàm lấy toàn bộ thông tin của 1 Item vừa vào Id của Parse đã cung cấp lúc thêm mới
    Hàm trả về là 1 Object
  */
  public function getItemById($sObjectId)
  {
      $query =  new ParseQuery($this->_object_name);
      return $query->get($sObjectId);
  }
  /**
    Hàm cập nhật dữ liệu vào object, dữ liệu truyền vào là các mảng với key là filed và value là giá trị còn đưa vào
    Hàm trả về item với thông tin mới cập nhật
  */
  public function update($aVals, $sObjectId)
  {
      if ($oObject = $this->getItemById($sObjectId)) {
          foreach ($aVals as $sField => $val) {
              $oObject->set($sField, $val);
          }
          $oObject->save();
      }
      return $oObject->fetch();
  }
  /**
    Xóa 1 item từ database với id của Parse
  */
  public function delete($sObjectId)
  {
      if ($oObject = $this->getItemById($sObjectId)) {
          $oObject->destroy();
      }
      return true;
  }
}

Giờ khi cần làm việc với Parse ta chỉ cần thêm dòng require "vendor/parse.php";. Theo yêu cầu của đề bài đưa ra thì chúng ta sẽ cần 2 trang là màn hình danh sách các Blog và xóa từng Blog và màn hình thứ 2 cho việc thêm mới, sửa xóa Blog. Tương ứng với 2 trang này tôi tạo ra 2 file index.php và add.php.

File index.php

Trang này sẽ thực hiện 2 chức năng là hiển thị toàn bộ Blog đã được thêm và, với mỗi Blog sẽ có 2 đường link để sửa và xóa từng Blog, và thêm 1 đường link để thêm mới Blog. Để xóa 1 Blog thì sẽ cần gửi đến link của file này với biến là delete có giá trị là id của Blog này lấy từ dữ liệu trả về từ Parse và sau khi xóa xong thì hiển thị danh sách mới. Tương tự link để update Blog này sẽ sang file app.php với id là Id của Blog này.

Tại đây ta có thể mỗi Item mà Parse trả về đều ở dạng Object và muốn lấy các trường trong đấy ta dùng đến hàm get(tên trường), tuy nhiên có 3 hàm đặc biệt riêng của Parse đó là

  • Hàm getObjectId() là để lấy id của Item.
  • Hàm getUpdatedAt() lấy thời điểm cập nhật gần nhất.
  • Hàm getCreatedAt() lấy thời gian tạo ra Item.
<?php
//Load parse class
require "vendor/parse.php";

//Khởi tạo Object Blog
$oBlogs = new Parse('Blog');

//Kiểm tra xem có truyền biến delete hay không và lưu giá trị này vào biến $iDeleteId
if (isset($_GET['delete']) && $iDeleteId = $_GET['delete']) {
  //Xóa Blog khỏi database
  $oBlogs->delete($iDeleteId);
  //Quay lại trang index.php
  header('location: index.php');
}
$aBlogs = $oBlogs->getList();
?>
<!DOCTYPE html>
<html>
  <head>
    <title>Parse sample</title>
  </head>
  <body>
    <h1>Parse Sample - Viblo</h1>
    <ul>
        <?php foreach($aBlogs as $aBlog) { ?>
            <li>
                <?php
                echo $aBlog->get('name');?>
                <a href="add.php?id=<?php echo $aBlog->getObjectId() ?>">Edit</a>
                <a href="?delete=<?php echo $aBlog->getObjectId() ?>">Delete</a>
            </li>
         <?php } ?>
    </ul>
    <a href="add.php">Add</a>
  </body>
</html>

File add.php

Trang này thực hiện chức năng thêm mới và sửa một Blog. Sự khác nhau giữa thêm mới và sửa là khi gửi đi sẽ có thêm biến Id trên đường dẫn gửi đến file này. Và sau khi thêm mới thành công sẽ thêm 1 push notification với nội dung thông báo có 1 Blog mới và có tên của Blog. Và sau khi thực hiện thì chuyển về trang index.php

<?php
require "vendor/parse.php";
//Load class Parse
$oBlog = new Parse('Blog');

// Kiểm tra xem có biến Id gửi đến không.
if (isset($_GET['id']) && $iId = $_GET['id']) {
    //Lấy thông tin của 1 Blog theo Id gửi đến
    $aBlog = $oBlog->getItemById($iId);
}

//Kiểm tra xem có phải gửi có gửi dữ liệu từ Form lên không?
if ($aVals = $_POST) {
    //Kiểm tra xem có phải đang chỉnh sửa
    if (isset($iId)) {
        //Cập nhật BLog
        $oBlog->update($aVals, $aVals['id']);
    } else {
        //Thêm mới BLog
        $oBlog->add($aVals);
        //Gửi pushs notification
        $oBlog->sendPushNotification('Parse have new blog "' . $aVals['name'] . '"');
    }
    //Chuyển về trang index.php
    header('location: index.php');
}

?>
<!DOCTYPE html>
<html>
  <head>
      <title>Parse sample</title>
  </head>
  <body>
      <h1>Parse Sample - Viblo</h1>
      <form method="POST">
          <table>
              <tr>
                  <td>Name :</td>
                  <td>
                      <input name="name" value="<?php if (isset($aBlog)) echo $aBlog->name;?>">
                      <?php if (isset($aBlog)) { ?>
                          <input type="hidden" name="id" value="<?php echo $aBlog->getObjectId(); ?>">
                      <?php } ?>
                  </td>
              </tr>
              <tr>
                  <td>Author :</td>
                  <td><input name="author"value="<?php if (isset($aBlog)) echo $aBlog->author;?>"></td>
              </tr>
              <tr>
                  <td>Content :</td>
                  <td><input name="content"value="<?php if (isset($aBlog)) echo $aBlog->content;?>"></td>
              </tr>
              <tr>
                  <td colspan="2">
                      <input type="submit" value="Submit">
                  </td>
              </tr>
          </table>
      </form>
  </body>
</html>

Client

Trong bài này, chúng ta sẽ viết app cho Android sử dụng Android Studio với SDK version 19 tương đương với Android 4.4. Để sử dụng thư viện của Parse thì cần thêm vào file guild.gradle đoạn code sau:

    compile 'com.parse.bolts:bolts-android:1.+'
    compile 'com.parse:parse-android:1.+'

Sau khi thêm dòng đó thì để kết nối được đến Parse thì bạn cần chạy đoạn code này:

  Parse.initialize(this, "{app_id}", "{client_id}");
  ParseInstallation.getCurrentInstallation().saveInBackground();

Và đoạn code này chúng ta cần đưa vào file Application của Android vì Plugin Parse chỉ cần được load 1 lần duy nhất. Và để load duy nhất 1 lần chúng ta cần tạo 1 file và extends đến class Application của Android và trong file AndroidManifest.xml khai báo thêm tên file class đó. Cụ thể ta sẽ tạo 1 file là ParseApplication.java với nội dung như sau:

package com.example.framgianguyenquanghuy.parsesample;

import android.app.Application;

import com.parse.Parse;
import com.parse.ParseInstallation;

/**
* Created by FRAMGIA
guyen.quang.huy on 26/11/2015.
*/
public class ParseApplication extends Application {
  @Override
  public void onCreate() {
      super.onCreate();
      Parse.initialize(this, "{app_id}", "{client_id}");
      ParseInstallation.getCurrentInstallation().saveInBackground();
  }
}

File AndroidManifest.xml

Đây là file thiết lập các cấu hình cho app. Như đã nói ở trên thì ta cần phải khai báo thêm một thuộc tính để chỉ load Plugin Parse một lần khi chạy app, ta cần thêm thuộc tính name trong thẻ application. Và cũng để chạy được chức năng push notification thì theo tài liệu này thì ta cần làm các bước sau: Thêm đoạn dưới đây trong thẻ application:

<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParsePushBroadcastReceiver"
    android:exported="false">
  <intent-filter>
    <action android:name="com.parse.push.intent.RECEIVE" />
    <action android:name="com.parse.push.intent.DELETE" />
    <action android:name="com.parse.push.intent.OPEN" />
    </intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND">
  <intent-filter>
    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

    <category android:name="com.parse.starter" />
  </intent-filter>
</receiver>

và thay đổi thuộc tính android:name trong thẻ category bằng tên của app. Tức là thay tên của app vào đoaạn <category android:name="com.parse.starter" />.

Để chạy được push notification cho app thì cũng cần phải thêm bên ngoài thẻ application như sau:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<permission android:protectionLevel="signature"
    android:name="com.parse.starter.permission.C2D_MESSAGE" />
<uses-permission android:name="com.parse.starter.permission.C2D_MESSAGE" />

và cũng thay đổi thuộc tính android:name cho 2 thẻ dưới thành tên của app. Như vậy nội dung của file AndroidManifest.xml sẽ như sau:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.framgianguyenquanghuy.parsesample" >
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission android:protectionLevel="signature"
        android:name="com.example.framgianguyenquanghuy.parsesample.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.example.framgianguyenquanghuy.parsesample.permission.C2D_MESSAGE" />
    <application
        android:allowBackup="true"
        
                                          
0