Ag和Laravel开发仿知乎笔记-后端

这里写图片描述
这里写图片描述

结构预览

这里写图片描述
这里写图片描述

难点:

Laravel表机制:保证结构复杂的数据的一致性,如何规划数据结构,如何封装为易用且运行稳定的API

使用composer安装laravel

php composer.phar create-project laravel/laravel project disable-tls(前提把composer.phar放在安装目录)

报错:

 The openssl extension is required for SSL/TLS protection but is not available. If you can not enable the openssl extensi
  on, you can disable this error, at your own risk, by setting the 'disable-tls' option to true.

解决:php.ini中extension=php_openssl.dll打开

运行

php artisan --version 查看版本
F:\phpStudy\WWW\Larvael>php -S localhost:8000 -t project/public

配置国内全量镜像Packagist:composer.json

"repositories": {
    "packagist": {
        "type": "composer",
        "url": "https://packagist.phpcomposer.com"
    }
}

小技巧(win):shift 点击鼠表邮件,cmd

Migration:数据库的版本控制
- . 解决团队合作下数据库结构不统一的问题
- SQL语句->PHP语句

create table users(
  id int(10) unsigned not null auto_increment,
  username varchar(12),
  password varchar(255) not null,
  primary key(id),
  UNIQUE KEY users_username_unique(username)
) engine=innodb;
mysqldump -uroot -p *** > wangba.sql

这里写图片描述

创建Migration
up:

php artisan make:migration create_table_table1(生成在databaseartisanlaravel里面的一个命令行工具 
class CreateTableTable1 extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
        Schema::create('table',function(Blueprint $table){
          $table->increments('id');
          $table->string('name',12)->nullable()->unique();
           $table->text('name')->nullable();
        });
    }
php artisan migrate

这里写图片描述
这里写图片描述
回滚(down):

   public function down()
    {
        //
        Schema::drop('table1');
    }
php artisan migrate:rollback

参数:–pretend,预先查看
这里写图片描述

开发user表:

php artisan make:migration create_table_users --create=users
 public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('username')->unique();
            $table->text('avatar_url')->nullable(); //默认代替
            $table->string('email')->unique()->nullable();
            $table->string('phone')->unique()->nullable(); // string or number 区号+,或者未来x
            $table->string('password',255);
            $table->text('intro')->nullable();
            $table->timestamps();
        });
    }
php artisan migrate
php artisan migrate:rollback(保证都能正确执行)
php artisan migrate

这里写图片描述

注册API的实现

App->Http->routes.php(处理所有网络连接的设置)
这里写图片描述
如果是字符串,默认返回html/text
如果是数组,默认返回json
这里写图片描述

laravel 5.3之后就不存在route文件了。
而是改用routes文件夹中的web.php文件。routes->web.php

Route::any('api',function(){
    return ['version' => '2.0'];
});
调用user模块
Route::any('api/user',function(){
    $user = new App\User;
    return $user->signup();
});
php artisan make:model User 创建一个模板
app->User.php
class User extends Model
{
    //
    public function signup(){
        return 'signup';
    }
}

注册API的实现

http://localhost:8000/public/index.php/api/user?username=%E7%8E%8B%E6%B7%B3%E9%BE%99&password=123

dd dorp and die 就是debug

<?php

namespace App;


use Illuminate\Database\Eloquent\Model;
use Request;

class User extends Model
{
    //
    public function signup(){
        //
        dd(Request::get('age'));
        dd(Request::has('age'));
        dd(Request::all());
//        return 'signup';
    }
}

加密密码:Hash::make( passwordbcrypt( password)

登陆API的实现

登陆接口:

function user_ins(){
    return new App\User;
}
Route::any('api/login',function(){

    return user_ins()->login();
});

登陆函数:

public function login(){
        //  监测用户名和密码是否存在
        // 接受Url参数
        $has_username_and_password = $this->has_username_and_password();
        if(!$has_username_and_password){
            return ['status' => 0,'msg' => '用户名和密码皆不可为空'];
        };

        $username = $has_username_and_password[0];
        $password = $has_username_and_password[1];

        // 监测用户是否存在
        $user = $this->where('username',$username)->first();
        if(!$user){
            return ['status' => 0,'msg' => '用户不存在 '];
        }
        // 监测密码是否正确
        $hashed_possword =$user->password;
        if(!Hash::check($password,$hashed_possword))
            return ['status' => 0,'msg' => '密码有误 '];
        return 1;
    }

注意Laravel的php版本问题。For Laravel 5 you need:

The Laravel framework has a few system requirements:

PHP >= 5.4 
Mcrypt PHP Extension 
OpenSSL PHP Extension 
Mbstring PHP
Extension Tokenizer PHP Extension
vendor/laravel/framework/src/Illuminate/Foundation/helpers.php on line 49(做其他项目时切换了下,没注意这个问题)

session:


session()->put('username',$user->username);
session()->set('person.name.wangchunlong.age','20');//支持多级嵌套
删除session:
$_username = session()->pull('username'); //拿出来,剪切
session()->forget('username');
session()->put('username',null);
session()->flush();

问题API的实现

Question Migration的建立(Up和Down)
php artisan make:migration create_table_questions --create=questions

突然写错了,发现删除后重新执行命令报错

[ErrorException]
  include(F:\phpStudy\WWW\Larvael\project\vendor\composer/../../database/migrations/2017_05_25_062526_create_table_questions.php): failed to open stream: No such file or directory

解决方法:

php artisan cache:clear 删除缓存文件(bootstrap文件夹)
composer dump-autoload -o
composer update 重新加载再生成包含在项目中的列表文件
    public function up()
    {
        Schema::create('questions', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title',64);
            $table->text('desc')->nullable()->comment('description'); //description
            $table->unsignedInteger('user_id'); //无符号整形
            $table->unsignedInteger('admin_id'); //防止误操作
            $table->string('status')->default('ok'); //status,举报折叠问题

            $table->timestamps();


            $table->foreign('user_id')->references('id')->on('users');
        });
    }
php artisan migrate 

报错,说users表已经创建,原来这个表之前就没有创建成功。

[Illuminate\Database\QueryException]
  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_username_unique`(`username`))

经过查询,是数据库版本过低的原因造成的。
Laravel 5.4更改了默认数据库字符集,现在utf8mb4它包括支持存储emojis。这只会影响新的应用程序,只要你运行MySQL v5.7.7或更高版本,你就不需要做任何事情。
添加代码,限制索引长度:
迁移指南:
编辑AppServiceProvider.php文件,并在boot方法中设置一个默认的字符串长度:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}

删表,重新执行,Good Job。

路由的建立和方法的建立

注意方法名不要和内置方法冲突

function question_ins(){
    return new App\Question;
}
Route::any('api/question/add',function(){

    return question_ins()->add();
});
php artisan make:model Question
问题添加:
class Question extends Model
{
    //
    public function add(){
        if(!user_ins()->is_logged_in()){
            return ['status' => 0,'msg' => 'login required'];
        };
        if(!rq('title')){
            return ['status' => 0,'msg' => 'required title'];
        }
        if(rq('desc'))
            $this->desc = rq('desc');

        $this->title = rq('title');
        $this->user_id = session('user_id');

        return $this->save() ? ['status' => 1,'id' => $this->id] : ['status' => 0,'msg' => 'db insert failed'];
    }
}

小贴士:使用laravel validation可以验证长度,数据类型
自己看

问题更新:
//更新问题
Route::any('api/question/refresh',function(){

    return question_ins()->refresh();
});
    //更新问题API
    public function refresh(){
        //检查用户是否登陆
        if(!user_ins()->is_logged_in()){
            return ['status' => 0,'msg' => 'login required'];
        }
        //检查传参中是否有ID
        if(!rq('id'))
            return ['status' => 0,'msg' => 'id is required'];

        //获取指定ID的model
        $question = $this->find(rq('id')); //返回主键对应的那一行

        //用户不存在中断
        if(!$question)
            return ['status' => 0,'msg' => 'user not exisits'];

        if($question->user_id != session('user_id')){
            return ['status' => 0,'msg' => 'permission denied'];
        }

        //加判断的原因是有什么更新什么。
        if(rq('title'))
            $question->title = rq('title');

        if(rq('desc'))
            $question->desc = rq('desc');

        return $question->save() ? ['status' => 1,] : ['status' => 0,'msg' => 'db refresh failed'];

    }

查看问题,删除问题(略)……….

回答API的实现

Answers Migration的建立(Up和Down)
php artisan make:migration create_table_answers --create=answers
public function up()
    {
        Schema::create('answers', function (Blueprint $table) {
            $table->increments('id');
            $table->text('content');
            $table->unsignedInteger('user_id');
            $table->unsignedInteger('question_id');
            $table->timestamps();

            $table->foreign('user_id')->references('id')->on('users');
            $table->foreign('question_id')->references('id')->on('questions');

        });
    }
php artisan migrate --pretend
php artisan migrate
php artisan make:model Answer

………

通用API的实现(跨表查询)

点赞和取消赞实现:

answer和user是多对多的关系
Answer模块和User模块下添加注册函数(指明两模块的关系):

 public function users(){
        return $this->belongsToMany('App\User');
    }
 public function answers(){
        return $this->belongsToMany('App\Answer');
    }

建立一个连接表,把answers表和users表通过一个轴表(中间表)连接起来

php artisan make:migration create_table_answer_user --create=answer_user(连接表例外,必须单数)
    public function up()
    {
        Schema::create('answer_user', function (Blueprint $table) {
            $table->increments('id');
            $table->unsignedInteger('user_id');  //主键
            $table->unsignedInteger('answer_id'); //主键
            $table->unsignedSmallInteger('vote'); //赞同1,反对0
            $table->timestamps();

            $table->foreign('user_id')->references('users')->on('users');
            $table->foreign('answer_id')->references('users')->on('answers');
        });
    }

user_id,answer_id,vote三者组合必须为1,所有需要限制一下(unique)。

$table->unique(['user_id','answer_id','vote']);
php artisan migrate
添加
php artisan migrate:rollback
php artisan migrate

添加接口,写vote方法

    public function vote(){
        if(!user_ins()->is_logged_in())
            return ['status' => 0,'msg' => 'logined required'];

//        answer_id是否存在,赞成还是反对
        if(!rq('id') || !rq('vote'))
            return ['status' => 0,'msg' => 'id or vote is required'];

        //回答是否存在
        $answer = $this->find(rq('id'));
        if(!$answer) return ['status' => 0,'msg' => 'answer not exists'];

//        1赞同 2反对
        $vote = rq('vote') <= 1 ? 1 : 2;

//         在中间表查找是否有该键,检查用户是否在相同问题下投过票(如果投过票,则delete)
        $answer
            ->users()
            ->newPivotStatement() //进入user_answer连接表进行操作
            ->where('user_id',session('user_id'))
            ->where('answer_id',rq('id'))
            ->delete();
//       在连接表中添加数据
        $answer->users()->attach(session('user_id'),['vote' => $vote]);

        return ['status' => 1];

    }
时间线API实现
php artisan make:controller CommonController位置在Http->Controllers->Comm.....

接口

//时间线 @相当于分隔符
Route::any('api/timeline','CommonController@timeline');
class CommonController extends Controller
{
    public function timeline(){
        list($limit,$skip) = paginate(rq('page'),rq('limit'));
        $questions = question_ins()
            ->limit($limit)
            ->skip($skip)
            ->orderBy('created_at','desc')
            ->get();

        $answers = answer_ins()
            ->limit($limit)
            ->skip($skip)
            ->orderBy('created_at','desc')
            ->get();

        //合并两张表数据
        $data = $questions->merge($answers);
//       按照时间线来排序,把每一条数据存为item
        $data = $data->sortByDesc(function($item){
           return $item->created_at;
        });
//        只取值,不取键
        $data = $data->values()->all();
        return ['status' => 1, 'data' => $data];
    }
}

API设计指南

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值