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

来源:互联网 发布:淘宝怎么搜迷幻蘑菇 编辑:程序博客网 时间:2024/04/28 10:20

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

结构预览

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

难点:

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 migratephp 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.phpclass 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

<?phpnamespace 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 PHPExtension 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 -ocomposer 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 --pretendphp artisan migratephp 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:rollbackphp 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设计指南

  • 命名清晰,准确(功能+思想=名称)
  • 第三方API最好有版本号,V0.1.1
  • RESTful.http://www.ruanyifeng.com/blog/2014/05/restful_api.html(切末生搬硬套。设计理论,不是规范)
原创粉丝点击