在我的Laravel项目中,这意味着寻找建筑物租金,我使用了一个具有多态关系的Eloquent模型来存储用户和租金的资格。所以,我有三个相关的模型来解释这个问题:'User'、'Alquiler'(租金)和'Calificacion'(资格),具有在其中定义的多态关系。
在我的“Alquiler”模型中,我定义了:
public function getRouteKeyName()
{
return 'slug';
}
所以当我有一个这样定义的路由时:
GET|HEAD alquileres/{alquiler} .... alquileres.show › AlquilerController@show
在我的“AlquilerController”中,我可以做:
public function show(Alquiler $alquiler){
return view('alquileres.show',compact('alquiler'));
}
要轻松获得与已发布租金对应的模型示例,在我的Blade视图中:<a href="{{route('alquileres.show',$alquiler)}}">...</a>
因此,呈现的链接看起来像:'http://localhost:8000/alquileres/capital-federal-arcos-3130-7-a'
在我的“User”模型中,我没有定义“getRouteKeyName()”方法,所以这个方法只是默认的ID字段。
尽管我可以很容易地为'User'和'Alquiler'执行依赖注入,但当必须在控制器方法中接收的模型可以是'User'或'Alquiler'时,我无法实现类似的东西,这取决于我的路由中定义的第一个参数,所以我编写了以下代码:
web.php:
Route::get('/calificaciones/calificar/{modelo}/{instancia}', [CalificacionesController::class,'calificar'])->name('calificaciones.calificar');
Route::post('/calificaciones/guardarCalificacion/{modelo}/{instancia}', [CalificacionesController::class,'guardarCalificacion'])->name('calificaciones.guardarCalificacion');
CalificacionesController.php:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Alquiler;
use App\Models\Calificacion;
class CalificacionesController extends Controller{
...
public function calificar(Request $request, $modelo=null, $identificador=null) {
$instancia=null;
if($modelo=='usuario'){
$instancia=User::find((int) $identificador);
}
else if($modelo=='alquiler'){
$instancia=Alquiler::where('slug', $identificador)->firstOrFail();
}
return view('calificaciones.calificar',compact(['modelo','instancia']));
}
public function guardarCalificacion(Request $request, $modelo=null, $identificador=null) {
$calificador=auth()->user();
$instancia=null;
if($modelo=='usuario'){
$instancia=User::find((int) $identificador);
}
else if($modelo=='alquiler'){
$instancia=Alquiler::where('slug', $identificador)->firstOrFail();
}
Calificacion::create([
'calificacionable_id' => $instancia->id,
'calificacionable_type' => get_class($instancia),
'puntuacion' => $request->puntuacion,
'comentario' => $request->comentario,
'calificador_id' => $calificador->id
]);
return redirect()->route('calificaciones.calificacionesRealizadas');
}
...
}
所以我得到的一些可能的链接是:
http://localhost:8000/calificaciones/calificar/alquiler/buenos-aires--lomas-del-mirador-liniers-554-12
http://localhost:8000/calificaciones/calification/usuario/2
通过执行<a href="{{route('calificaciones.calificar',['alquiler',$alquiler])}}"
或<a href="{{route('calificaciones.calificar',['usuario',$alquiler->publicador])}}"
我在其他路由和控制器方法中也有类似的东西。
尽管这种方法有效,但我发现它是一种非常丑陋的方法,因为我无法通过执行依赖注入在方法中获得所需的模型示例,而是通过执行Eloquent查询手动获得。除此之外,如果我在我的“User”模型中定义了一个“getRouteKeyName()”方法,或者如果我在我的“Alquiler”模型中更改了它,那么这段代码将不再工作,所以我需要在所有使用相同方法的方法中编辑它。
我试图通过在我的RouteServiceProvider上做一个显式的路由模型绑定来解决这个问题,如Laravel官方文档和其他地方所示:
https://laravel.com/docs/10.x/routing#route-model-binding www.example.com
然而,我试过的这些方法都不起作用。
有没有人可以建议一个更好的方法来实现我想要的结果,通过能够根据每种情况下我需要的模型执行DI?(或者至少是为了改进我现在的代码)
如果有任何更多的信息需要,或没有正确理解的东西,请让我知道。
太感谢了!
Leandro
编辑:
我几乎找到了一种实现这一点的方法,通过上下文绑定:
我写了一个这样的合约(接口):
Calificable.php:
<?php
namespace App\Contracts;
interface Calificable {}
在我的模型定义中,我做了:
use App\Contracts\Calificable;
class Alquiler extends Model implements Calificable {...
还有:
use App\Contracts\Calificable;
class User extends Model implements Calificable {...
然后,在我的RouteServiceProvider.php中,我添加了:
....
public function boot() {
...
Route::bind('modelo', function (string $value) {
error_log("Entro al bind de modelo");
if($value=='usuario'){
$this->app->singleton(Calificable::class, User::class);
}
else if($value=='alquiler'){
$this->app->singleton(Calificable::class, Alquiler::class);
}
return $value;
});
....
最后,在我的控制器方法中,我有:
public function calificar(Request $request, string $modelo, Calificable $instancia){
error_log(get_class($instancia));
error_log(json_encode($instancia));
return view('calificaciones.calificar',compact(['modelo','instancia']));
}
当查看'calife'的第一个'error_log'的结果时,我正确地得到:
应用\型号\用户
或者说:
应用程序\模型\Alquiler
在相应的案例中。
然而,在第二个'error_log'中,我看到了一个空的模型,而不是我应该得到的模型。当我在我的控制器方法上用“Alquiler”或“User”输入提示我的参数时,这不会发生,得到一个成功的结果。
有没有什么方法来完成我试图通过这种方式做什么,只是通过编辑一点点我目前在RouteServiceProvider.php?我想我差不多完成了。
1条答案
按热度按时间5lwkijsr1#
1-静态方法,可维护性更好
考虑到你只有2个选择,实现你的目标的最简单和最干净的方法是像这样分割路线:
web.php
CalificacionesController.php
没有魔法绑定会让你的代码非常干净,便于将来的开发。
2-动态方法
但如果你或其他人阅读这需要一个更动态的方法,你可以使用这个:
RouteServiceProvider.php
CalificacionesController.php