Laravel框架下如何从控制器向模型传递通配符变量
解决Laravel路由通配符传递到模型查询的问题
嘿,刚接触Laravel是吧?我来帮你搞定把路由通配符传到模型查询里的问题,顺便给你优化下现有代码的小问题~
首先先说说你当前代码里的几个小坑:
- Eloquent的
scope方法写法不对:scope开头的方法第一个参数必须是$query查询构建器实例,不是直接传$id,这是Laravel的规范。 - 直接把$id拼进SQL语句有严重的SQL注入风险,绝对不能这么写!
- 其实Laravel的Eloquent已经帮你封装了现成的查询方法,不用自己写原生SQL啦。
下面一步步给你修正:
第一步:修正模型的Scope方法
按照Laravel的规范重写scope方法,同时用安全的参数绑定(或者直接用Eloquent的查询方法):
namespace App; use Illuminate\Database\Eloquent\Model; class Product extends Model { protected $table = "product"; public $timestamps = false; // 正确的scope写法:第一个参数是$query,第二个是要传递的id public function scopeSingleProduct($query, $id){ // 用Eloquent的where方法,自动处理参数绑定,安全又简洁 return $query->where('id', $id)->first(); // 如果你坚持要用原生SQL,一定要用参数绑定避免注入: // return DB::select("SELECT * FROM product WHERE id = ?", [$id]); } }
第二步:定义带通配符的路由
在routes/web.php里定义接收通配符的路由,参数名可以自定义:
Route::get('/products/{productId}', 'ProductController@showSingleProduct');
第三步:控制器接收参数并调用模型方法
补全控制器代码,接收路由里的productId参数,然后调用模型的scope方法(注意调用时不用写scope前缀):
namespace App\Http\Controllers; use App\Product; class ProductController extends Controller { public function showSingleProduct($productId){ // 调用模型的scope方法 $product = Product::SingleProduct($productId); // 更简单的方式:直接用Eloquent自带的find方法,完全不用自己写scope // $product = Product::find($productId); // 把数据传给视图 return view('product.detail', compact('product')); } }
进阶玩法:路由模型绑定
如果你的路由通配符是模型的主键(比如这里的id),可以用Laravel的路由模型绑定,连查询代码都省了:
- 修改路由:
Route::get('/products/{product}', 'ProductController@showSingleProduct');
- 控制器直接接收模型实例:
public function showSingleProduct(Product $product){ // Laravel会自动根据路由里的{product}值(id)查询对应的Product模型 return view('product.detail', compact('product')); }
这样是不是更简单?而且完全不用担心SQL注入的问题~
内容的提问来源于stack exchange,提问作者Frosty
相关产品推荐
相关产品推荐

