RESTful架构与实战

课程地址:https://www.imooc.com/learn/811
代码地址:https://github.com/Lining128/RESTful
本质:一种软件架构风格
核心:面向资源
解决问题:降低开发的复杂性、提高系统的可伸缩性

设计概念和准则
网络上的所有事物都可以被抽象为资源。
每个资源都有唯一的资源标识,对资源的操作不会改变这些标识。
所有的操作都是无状态的。

HTTP属于应用层的协议

schema://host[:port]/path[?query-string][#anchor]
scheme:指定底层使用的协议(http,https,ftp等)
host:服务器的ip地址或者域名
port:服务器端口,默认:80
path:访问资源路径
query-string: 发送给http服务器的数据
anchor:锚

HTTP协议-请求

格式:Method Request-URI HTTP-Version CRLF
举例:GET / HTTP/1.1 CRLF

GET 获取资源
POST 在资源后附加心得数据
HEAD 请求获取资源的响应消息报头
PUT 请求服务器存储一个资源
DELETE 请求服务器删除资源
OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求

HTTP协议-响应

状态行:HTTP-Version Status-code Reason-Phrase CRLF
HTTP/1.1 200 OK
200 OK 客户端请求成功
400 Bad Request 客户端请求有语法错误,不能被服务器所理解
401 Unauthorized 服务器收到请求,但是拒接提供服务
404 Not Found 请求资源不在
500 Internal Server Error 服务器发生不可预期的错误
503 Server Unavailable 服务器当前不能处理客户端的请求

如何设计RESTful API

资源路径
每个网址代表一种资源,所以网址中不能有动词,只能名词。一般来说API中的应该使用复数
举例:有一个API提供动物园(zoo)的信息,还包含各种动物和雇员的信息
https://api.example.com/v1/zoos 动物园资源
https://api.example.com/v1/animals 动物资源
https://api.example.com/v1/employees 雇员资源
HTTP动词
对于资源的操作(CURD)由HTTP动词(谓词)表示
GET:从服务器取出资源
POST:在服务器新建一个资源
PUT:在服务器更新资源(客户端提供改变后的完整属性)
PATCH:在服务器更新资源(客户端提供改变的属性)
DELETE:从服务器删除资源
举例:
POST/zoos:新建一个动物园
GET/zoos/ID:获取某个指定动物园的信息
PUT/zoos/ID:更新某个指定动物园的信息
DELETE/zoos/ID:删除某个动物园
过滤词
如果记录数量很多,服务器不可能都将他们返回给用户。
API应该提供参数,过滤返回结果
举例:
?offset=10:指定返回记录的开始位置
?page=2&per_page=100:指定第几页,以及每一页的记录数
?sortby=name&order=asc:指定返回结果排序,以及排序顺序
?animal_type_id=1:指定筛选条件
状态码
服务器向用户返回的状态码和提示信息,使用标准的HTTP状态码
200 OK服务器成功返回用户请求的数据,该操作是幂等的
201 CREATES 新建或者修改数据成功
204 NO CONTENT 删除数据成功
400 BAD REQUEST 用户发送的请求有误,该操作是幂等的
401 Unauthorized 表示用户没有认证,无法进行当前操作
403 Forbidden 表示用户访问是被禁止的
422 Unprocesable Entity 当创建一个对象时,发生一个验证错误
500 INTERNAL SERVER ERROR 服务器放生错误,用户将无法判断发出的请求是否成功
错误处理
如果状态码是4xx或者5xx,就应向用户返回错误信息,返回信息将error作为键名出错信息为键值
{
“error” : “参数错误”
}
返回结果
GET/collections : 返回资源对象的列表(数组)
GET/collections/identity:返回单个资源对象
POST/collections:返回新生成的资源对象
PUT/collections/identity:返回完整的资源对象
PATCH/collections/identity:返回被修改的属性
DELETE//collections/identity:返回一个空文档

开发环境搭建

下载UPUPW.NET集成环境

添加虚拟主机,以及取消跨站目录限制
添加虚拟主机的本地hosts解析

实体代码

User.php

<?php


require __DIR__.'/errorcode.php';
class User
{
  private $db;
  public function __construct($_db)
  {
    $this->$_db = $_db;
  }

    /**
     * @param $username
     * @param $password
     * @return mixed
     * @throws ErrorException
     */
    public function login($username, $password)
  {
      if (empty($username)){
          throw new ErrorException("用户名不能为空",errorcode::USERNAME_CANNOT_EMPTY);
      }
      if (empty($password)) {
          throw new ErrorException("密码不能为空", errorcode::PASSWORD_CANNOT_EMPTY);
      }
      $sql = 'select * from user where username =:username and  password =:password';
      $password = $this->_md5($password);
      $stmt = $this->_db->prepare($sql);
      $stmt->bindParam(':username',$username);
      $stmt->bindParam(':password',$password);
      $stmt->execute();
      $user = $stmt->fetch(PDO::FETCH_ASSOC);
      if (empty($user)){
          throw new ErrorException("用户名密码错误",errorcode::USERNAME_OR_PASSWORD_INVALID);
      }
      unset($user['password']);
      return $user;
  }

    /**
     * @param $username
     * @param $password
     * @return array
     * @throws ErrorException
     */
    public function register($username, $password)
  {
      if (empty($username)){
          throw new ErrorException("用户名不能为空",errorcode::USERNAME_CANNOT_EMPTY);
      }
      if ($this->_isUsernameExists($username)) {
          throw new Exception("用户名已存在", errorcode::USERNAME_EXISTS);
      }
      if (empty($password)) {
          throw new ErrorException("密码不能为空", errorcode::PASSWORD_CANNOT_EMPTY);
      }
      $sql = 'insert into user (username,password,created_at) value (:username,:password,:created_at)';
      $created_at = time();
      $password = $this->_md5($password);
      $stmt = $this->prepare($sql);
      $stmt->bindParam(':username',$username);
      $stmt->bindParam(':password',$password);
      $stmt->bindParam(':created_at',$created_at);
      if (!$stmt->execute()){
          throw new ErrorException("注册失败",errorcode::REGISTER_FAIL);
      }
      return[
          'userId' => $this->_db->lastInsertId(),
          'username' => $username,
          'created_at' => $created_at

      ];
  }
  private function _md5($string,$key = 'imooc')
  {
      return md5($string . $key);
  }

    /**
     * @param $username
     * @return bool
     */
    private function _isUsernameExists($username)
  {
    $exists = false;
    $sql = 'select * from user where username =:username';
    $stmt = $this->_db->prepare($sql);
    $stmt->bindParam(':username',$username);
    $stmt->execute();
    $result = $stmt->fetch(PDO::FETCH_ASSOC);
    return !empty($result);
  }
}

index.php

<?php
require __DIR__.'/lib/User.php';
$pdo = require __DIR__.'/lib/db.php';
$user = new User($pdo);
print_r($user->register('admin1','123'));


errorcode.php

<?php


class errorcode
{
    const USERNAME_EXISTS = 1;
    const PASSWORD_CANNOT_EMPTY = 2;
    const USERNAME_CANNOT_EMPTY = 3;
    const REGISTER_FAIL = 4;
    const USERNAME_OR_PASSWORD_INVALID = 5;
}

db.php

<?php

$pdo = new PDO('mysql:host=localhost;dbname=mydb','root','123');
return $pdo;
?>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值