【发布时间】:2017-11-13 23:01:17
【问题描述】:
我有一个调查表。每个问题都有 3-4 个预定义答案作为单选按钮。单选按钮的值是数据库中答案的主键。
由于所有问题的所有答案都存储在一个表中,如果用户增加值,ID 可能仍然是有效的外键,但它不属于该问题。
确保单选按钮的值不被操纵的最佳做法是什么?
【问题讨论】:
标签: php mysql laravel laravel-5
我有一个调查表。每个问题都有 3-4 个预定义答案作为单选按钮。单选按钮的值是数据库中答案的主键。
由于所有问题的所有答案都存储在一个表中,如果用户增加值,ID 可能仍然是有效的外键,但它不属于该问题。
确保单选按钮的值不被操纵的最佳做法是什么?
【问题讨论】:
标签: php mysql laravel laravel-5
在您的控制器中,您可以执行以下操作:
# Get the ids of the answers that are valid for that question
$validAnswerIds = $Question->answers->pluck('id')->toArray();
# Validate that the answer given is in there
$rules = ['answer' => Rule::in( $validAnswerIds ) ];
$request->validate( $rules );
【讨论】:
作为David has already mentioned,您需要验证您的业务逻辑。
最“laravelish”的方式,如you mentioned,是在您的请求类中执行验证,并在需要时开发额外的验证器扩展。像Erin has mentioned 那样用验证逻辑乱扔你的控制器根本不是一个好习惯;它虽然有效。
我假设您有两个独立的模型:Question 和 Answer。此外,它们之间的完整 1-N 关系设置为一个问题可以有多个答案并且每个答案都属于一个问题:
class Question extends Model
{
public function answers()
{
return $this->hasMany(Answer::class);
}
}
class Answer extends Model
{
public function question()
{
return $this->belongsTo(Question::class);
}
}
假设你也有一个SurveyController:
class SurveyController extends Controller
{
public function store(CreateSurveyRequest $request)
{
// Request is validated by now and you can be sure that the
// answer belongs to the question. Go on and create/store
// the Survey entity.
}
}
以及进行实际数据验证的请求类:
class CreateSurveyRequest extends FormRequest
{
public function rules()
{
// Assuming the request contains `answer_id` and `question_id` fields:
return [
'answer_id' => 'exists:answers,id,question_id,' . request('question_id'),
// e.g.
// 8 => 'exists:answers,id,question_id,10'
// Which loosly translates to "answer ID 8 should belong to question ID 10"
];
}
}
这样的exists 规则定义确保答案记录在questions 表上有一个外键,因此它是问题的有效答案。
关键是 Laravel 的 exists 规则 supports additional conditions。有趣的是,提交提案的人与您在这里的需求完全相同。
【讨论】:
belongs cutom 规则的良好候选者。但是,我个人更喜欢坚持通用核心功能,并尽可能避免增加复杂性。
确保单选按钮的值未被操纵
你不能,这是错误的方法。 总是假设客户端信息可以被操纵。
相反,验证向服务器发出的请求的业务逻辑。当您的服务器端代码收到一组提交的问题和答案时,请根据您拥有的数据验证提交的数据是否有效。
这可以通过首先查询数据库、执行验证逻辑然后保存数据来完成。可以通过创建存储过程或其他一些数据库端逻辑来确保数据有效,然后只与数据库交互一次。等等。无论哪种方式,都由您来定义和验证系统中规定的业务规则。
【讨论】:
Question 和Answer 模型之间是否存在关系。如果您需要更多详细信息,请考虑使用代码示例更新您的问题,包括您目前所做的工作、您拥有哪些模型以及您的控制器代码是什么样的。