注:关于项目的配置就不多说了,请自行进行配置并且能够成功运行项目。本文主要来讲解代码,而非项目配置。
本文以趣编程项目的“添加想学”这个任务为例,并且只显示主要代码,无关的代码会用省略号代替
路由
首先要写的肯定就是路由啦,没有路由就无法访问我们想要的数据。在laravel5.3之前可以到 app/Http/routes.php
下写,laravel5.3的话将路由文件提取出来移到了 routes
文件夹下,并且分为了 web.php
和 api.php
。找到适当的文件就可以了。同时,项目一般使用了 dingo/api
这个lib,除了前缀有些不太相同之外,主体内容都是一致的。
$api->version('v1.0', ['namespace' => 'App\Http\V1_0\Controllers'], function ($api) { .... // 需提供 JWT $api->group(['middleware' => 'jwt.auth', 'providers' => 'jwt'], function ($api) { .... $api->post('learn_things', 'LearnThingscontroller@store'); // 添加想学 }); });
如果对什么是GET、POST、PATCH等不太清楚的话,推荐阅读书籍《图解HTTP》
控制器
注意到上面的routes里有一个 ['namespace' => 'App\Http\V1_0\Controllers']
了么,接下来我们在 app/Http/V1_0/Controllers
文件夹下新建 LearnThingsController.php
。由于我们还没有写Model的相关代码,此时可以先简单的写个返回字符串就好了,后面再来进行修改。
<?phpnamespace App\Http\V1_0\Controllers; use JWTAuth; class LearnThingsController extends ApiController { public function store(Request $request) { $user = JWTAuth::parseToken()->authenticate(); return ‘添加想学’; } }
此时你们可能会有些困惑, JWTAuth::parseToken()->authenticate()
这段代码是什么意思。不要急,还记得我们写的路由么,添加想学的路由是在一个group下面的,意味着这个group下面的所有路由都需要符合这个group的配置(要求),那么具体就是 ['middleware' => 'jwt.auth', 'providers' => 'jwt']
这段,这里我们使用了jwt来进行登录验证,只有成功登陆的才可以访问下面的路由。而我们路由器里的那段代码就是用来获取成功登录的token的,表示我们已经成功登录,并且还能够获取token里的相关信息。此时使用Postman进行测试的话会返回 [‘添加想学’]
。
migration & seeds
迁移比较简单就不说了,主要说一下数据填充,填充主要是通过工厂方式来进行。首先我们要在 app/Entity
文件夹下建立LearThing的Model,取名 LearnThing.php
。
<?phpnamespace App\Entity; use Illuminate\Database\Eloquent\Model; class LearnThing extends Model { protected $fillable = ['created_user_id', 'tech_category_id', 'content', 'is_handled', 'remark']; public function user() { return $this->belongsTo(UserInfo::class, 'created_user_id', 'user_id'); } public function techCategory() { return $this->belongsTo(TechCategory::class, 'tech_category_id', 'id'); } }
上面的代码中我们创建了Model,下面的两个function是用来处理和其他Model之间的关系的,暂时先不用考虑。接着在 database/facroties/ModelFactory.php
文件下加入下面的代码。
$factory->define(LearnThing::class, function(Faker\Generator $faker) { return [ 'created_user_id' => UserInfo::all()->random()->user_id, 'tech_category_id' => TechLevel::all()->random()->id, 'content' => $faker->sentence(5), 'is_handled' => $faker->numberBetween(0, 1), 'remark' => $faker->sentence(5), ]; });
接着在 database/seeds/DatabaseSeeder.php
下通过简单的一句 factory(LearnThing::class, 100)->create();
来填充100条数据了。
*
此时需要了解的知识: Migration | Model | 数据填充
相关文档: Laravel-migration
| Laravel-Model
| Laravel-seeding
*
数据处理 & 仓库模式
在基础已经搭建好之后接下来就要进行逻辑处理了,在面向对象这种编程思想中,MVC三块是相互分离的,Model的处理在这里用到了仓库模式。那么在控制器里只要调用相应的接口就可以使用了,而不用理会具体的细节是如何实现的。在 app/Repositories/Interfaces
下新建 LearnThingInterface.php
,在 app/Repositories
下新建 LearnThingRepository.php
。
<?phpnamespace App\Repositories\Interfaces; interface LearnThingInterface { public function storeLearnThing($userId, $techCategoryId, $content); }
LearnThingInterface.php
<?phpnamespace App\Repositories; use App\Entity\LearnThing; use App\Repositories\Interfaces\LearnThingInterface; class LearnThingRepository implements LearnThingInterface { public function storeLearnThing($userId, $techCategoryId, $content) { $learnThing = LearnThing::create([ 'created_user_id' => $userId, 'tech_category_id' => $techCategoryId, 'content' => $content ]); return $learnThing; } }
LearnThingRepository.php
在上面的代码中,运行成功会新建一个LearnThing的对象,那么就会实现我们所要求的效果了。但是,此时直接去控制器里面调用的话是无法成功的,我们需要到 app/Providers/AppServiceProvider.php
下进行注册才能使用。
class AppServiceProvider extends ServiceProvider { public function register() { $this->app->bind(LearnThingInterface::class, LearnThingRepository::class); } }
*
此时需要了解的知识: Eloquent ORM
相关文档: Laravel-Eloquent
*
重构控制器 & 格式化输出内容
还记得我们之前的控制器只是返回了一个字符串么,接下来需要调用我们刚才写好的接口了。
<?phpnamespace App\Http\V1_0\Controllers; use App\Repositories\Interfaces\LearnThingInterface; use App\Http\V1_0\Transformers\LearnThingTransformer; use Illuminate\Http\Request; use JWTAuth; class LearnThingsController extends ApiController { public function __construct(LearnThingInterface $learnThingInterface) { $this->learnThingInterface = $learnThingInterface; } public function store(Request $request) { $this->validate($request, [ 'tech_category_id' => 'required|numeric', 'content' => 'required' ]); $user = JWTAuth::parseToken()->authenticate(); $userId = $user->id; $techCategoryId = $request->tech_category_id; $content = $request->content; $learnThing = $this->learnThingInterface->storeLearnThing($userId, $techCategoryId, $content); return $this->response->item($learnThing, new LearnThingTransformer()); } }
在这段代码中出现了2个新的知识点,一个是validate,另一个是transformer。其中validate是用来验证我们的请求的,只有符合验证的数据才会进行下一步操作,否则会返回错误。而transformer则是用来格式化我们的数据的。因为我们创建的数据有时候可能只是保留了一个id,而我们想要与之对应的Object,有些数据返回了8个字段,而我们只想要显示其中的5个字段,这个时候就需要用到transformer了(transformer的代码请到 app/Transformers
下查看)。
*
此时需要了解的知识: 验证 | Transformer
相关文档: Laravel-validation
| Transformer
*
至此,一个API已经基本写完了。其他的API写起来也是大同小异,主要就是体现在操控Model时候的逻辑不太一样,到时候具体问题具体分析就可以了。