Je crée un système de gestion où les enseignants peuvent gérer les projets finaux des étudiants et où les étudiants peuvent voir ce que les autres étudiants ont créé.
Je suis un nouveau venu dans le monde de Laravel et j'ai des problèmes pour optimiser les requêtes et valider les urls.
Voici mes schémas de tables :
Cursos
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| curso | varchar(255) | NO | | NULL | |
+-------+------------------+------+-----+---------+----------------+
Trienios
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| data_trienio | varchar(255) | NO | | NULL | |
| curso_id | int(11) | NO | | NULL | |
| oe_id | int(11) | NO | | NULL | |
+--------------+------------------+------+-----+---------+----------------+
Alunos
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| id_cartao | int(10) unsigned | NO | UNI | NULL | |
| nome | varchar(255) | NO | | NULL | |
| email | varchar(255) | NO | UNI | NULL | |
| trienio_id | int(11) | NO | | NULL | |
+------------+------------------+------+-----+---------+----------------+
PAP
+-----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| nome | varchar(255) | NO | | NULL | |
| descricao | text | NO | | NULL | |
| nota | int(11) | NO | | NULL | |
| aluno_id | int(11) | NO | | NULL | |
+-----------+------------------+------+-----+---------+----------------+
Jusqu'à présent, j'ai réussi à mettre en place des urls dynamiques basées sur les enregistrements définis dans la table cursos et trienios, comme ceci : http://localhost:8000/TGEI/2014-2017
(TGEI étant un enregistrement dans la table cursos qui permet de récupérer les enregistrements trienio associés et 2014-2017 étant un enregistrement dans la table trienios qui est lié à un enregistrement curso dans une relation 1-to-many et qui permet de récupérer les enregistrements pap associés).
tout cela fonctionne bien, mais j'ai des difficultés à optimiser des requêtes extrêmement inefficaces qui deviendront un problème très important lorsque la base de données s'étoffera
voici mes relations :
Curso.php
public function trienio()
{
return $this->hasMany('App\Trienio');
}
Trienio.php
public function curso()
{
return $this->belongsTo('App\Curso');
}
public function oe()
{
return $this->belongsTo('App\OE');
}
public function aluno()
{
return $this->hasMany('App\Aluno');
}
Aluno.php
public function trienio()
{
return $this->belongsTo('App\Trienio');
}
public function pap()
{
return $this->hasOne('App\PAP');
}
PAP.php
protected $table = 'pap';
public function aluno()
{
return $this->belongsTo('App\Aluno');
}
et ce sont les contrôleurs qui sont chargés de servir les pages accessibles à l'utilisateur :
CursoController.php
public function index(Curso $curso)
{
$cursos = $curso->all();
return view('curso')->withCursos($cursos);
}
TrienioController.php
public function index(Trienio $trienio, $curso)
{
$trienios = $trienio->whereHas('curso', function ($query) use ($curso) {
$query->where('curso', '=', $curso);
})->get();
return view('trienio')->withTrienios($trienios);
}
PapController.php
public function index(Pap $pap, $curso, $trienio)
{
$pap = $pap->whereHas('aluno.trienio', function ($query) use ($curso, $trienio) {
$query->where('data_trienio', '=', $trienio)->whereHas('curso', function ($query) use ($curso) {
$query->where('curso', '=', $curso);
});
})->toSql();
dd($pap);
return view('pap')->withPap($pap);
}
public function show(Pap $pap, $curso, $trienio, $id)
{
$pap = $pap->find($id);
dd($pap);
return view('show')->withPap($pap);
}
comme vous pouvez le constater, dans le cas de la méthode d'indexation du contrôleur PAP, la requête qui demande les données est un énorme désordre qui est l'exemple même du problème n+1 :
"select * from `pap` where exists (select * from `alunos` where `pap`.`aluno_id` = `alunos`.`id` and exists (select * from `trienios` where `alunos`.`trienio_id` = `trienios`.`id` and `data_trienio` = ? and exists (select * from `cursos` where `trienios`.`curso_id` = `cursos`.`id` and `curso` = ?)))"
L'objectif de cette requête est de récupérer les enregistrements PAP liés à un enregistrement trienio, lui-même lié à un enregistrement curso, en fonction des données saisies par l'utilisateur dans l'url (j'ai montré un exemple ci-dessus). Le problème est que, comme je suis un débutant dans ce domaine en général, je n'ai pas pu appliquer les concepts de chargement anticipé à la requête que je veux exécuter.
J'ai également un problème avec la validation des urls dans lesquelles l'utilisateur peut saisir ce qui suit :
http://localhost:8000/qwfkjnfwq/qjqtikjn/1
et la méthode show du contrôleur récupérera un enregistrement pap sans tenir compte des paramètres que l'utilisateur a saisis deux niveaux plus haut, ce qui posera évidemment un problème de "sécurité".
et ce que je voulais faire, c'était.. :
http://localhost:8000/TGEI/2014-2017/1
la méthode du contrôleur show chargera la relation imbriquée aluno.trienio, puis récupérera l'identifiant trienio lié au modèle aluno conformément à l'élément 2014-2017
puis récupérer l'identifiant du curso lié au modèle trienio conformément au paramètre TGEI
paramètre
et donc, des choses comme ça
http://localhost:8000/qwfkjnfwq/qjqtikjn/1
serait invalidée au lieu d'être exécutée.
Je comprends que certaines parties de ma question peuvent ne pas être claires (d'autant plus que l'anglais n'est pas ma langue maternelle) et dans ce cas, je peux les clarifier autant que vous le souhaitez.
et pour une meilleure information, voici mon fichier web.php
Route::get('/', 'CursoController@index');
Route::get('/{curso}', 'TrienioController@index');
Route::get('/{curso}/{trienio}', 'PapController@index');
Route::get('/{curso}/{trienio}/{id}', 'PapController@show');