// +---------------------------------------------------------------------- declare (strict_types = 1); namespace app\Api\Controller\V1; use think\facade\Validate; use ywxapp\controller\ApiBase; use addon\articles\model\Article as ArticleModel; class Article extends ApiBase { /** * 免登录白名单:仅只读接口对外公开。 * * 历史写法是 ['*'] + $needRight = ['*']:而 ApiBase 只认 $noNeedLogin/$noNeedVerify, * $needRight 根本不存在,等于 create/update/delete 全部裸奔——任何人都能改全站文章。 * 写操作必须登录,且只能操作自己的文章(见 assertOwner())。 */ protected $noNeedLogin = ['index', 'detail', 'init']; public function initialize() { $this->model = new ArticleModel(); } /** * 文章列表 */ public function index() { $page = $this->request->param('page/d', 1); $limit = $this->request->param('limit/d', 15); $list = $this->model->with(['category'])->page($page, $limit)->order('id', 'desc')->select(); $this->result->success($list); } /** * 创建文章 */ public function create(\think\Request $request) { // 字段白名单:绝不能把 $request->post() 全量塞进 create(), // 否则客户端可自行伪造 uid/status/create_at 等本该由服务端决定的字段。 $data = $request->only( ['title', 'cover_image', 'summary', 'content', 'author', 'cid', 'status'], 'post' ); if (empty($data['title'])) { $this->result->error('标题不能为空', 404); } // 归属以登录态为准,不接受客户端指定 $data['uid'] = $this->uid(); $res = $this->model->create($data); if ($res) { event('article_create_after', $res); $this->result->success($res, '创建成功'); } $this->result->error('创建失败'); } /** * 越权保护:只能改/删自己的文章。 * * @param \addon\articles\model\Article $info * @return void */ protected function assertOwner($info): void { $uid = $this->uid(); if ($uid <= 0 || (int) ($info->uid ?? 0) !== $uid) { $this->result->error('无权操作他人文章', 403); } } /** * 文章详情 * @route GET /detail, method:GET * @param int $uid 文章ID */ public function detail(\think\Request $request, int $uid= 0 ) { if (!$uid) $this->result->error('Invalid parameters', 404); $info = $this->model->with(['category', 'tags'])->find($uid); if (! $info) { $this->result->error('文章不存在', 404); } $this->result->success($info); } /** * 更新文章 * @route PUT /update, method:PUT * @param int $uid 文章ID */ public function update(\think\Request $request, int $uid= 0 ) { if (!$uid) $this->result->error('Invalid parameters', 404); $info = $this->model->find($uid); if (! $info) { $this->result->error('文章不存在', 404); } $this->assertOwner($info); $data = $request->only( ['title', 'cover_image', 'summary', 'content', 'author', 'cid', 'status'], 'put' ); $info->save($data); event('article_update_after', $info); $this->result->success($info, '更新成功'); } /** * 删除文章(软删除) * @route DELETE /update, method:DELETE * @param int $uid 文章ID */ public function delete(\think\Request $request, int $uid= 0 ) { if (!$uid) $this->result->error('Invalid parameters', 404); $info = $this->model->find($uid); if (! $info) { $this->result->error('文章不存在', 404); } $this->assertOwner($info); $info->delete(); event('article_delete_after', $info); $this->result->success('', '删除成功'); } public function init() { return json(['message' => 'This is version 1 of the API']); } }