Ci-dessous
Laravel La colonne du didacticiel présentera à Laravel la méthode de conversion automatique de flocons de neige entiers longs en chaîne. J'espère que cela sera utile aux amis dans le besoin. !
Lors de la conception d'une API, pour des raisons telles que la sécurité, il est parfois nécessaire d'abandonner l'utilisation d'identifiants auto-incrémentés pour rendre les identifiants non continus et indevinables. Cela peut généralement être réalisé en utilisant un identifiant de hachage, un UUID, un identifiant Snowflake, etc.
Dans un projet récent, j'ai essayé d'utiliser Snowflake ID. Après de nombreuses recherches, j'ai trouvé que les performances sont assez élevées et que la mise en œuvre est assez simple. Cependant, lorsque j'ai continué à retrousser mes manches et à me connecter à la partie frontale, il y a eu un problème de perte de précision JS car l'ID stocké était une valeur bigint non signée. (Quant à la raison pour laquelle il y a une perte de précision, je ne l'expliquerai pas en détail ici. Si vous n'êtes pas sûr, vous pouvez la rechercher par vous-même). Cet article présente principalement des solutions.
Pour résoudre ce problème, le principe de base est très simple, c'est-à-dire convertir l'ID en chaîne puis le renvoyer au front-end.
Au début, j'ai pensé à utiliser l'accesseur de modèle du modèle Laravel Eloquent. Ajoutez simplement un getIdAttribute au modèle qui doit être converti et convertissez l'ID en chaîne, n'est-ce pas ?
Par exemple : dans le modèle AppModelsUser c'est écrit comme ceci :
/**
* @return string
*/public function getIdAttribute(){
return strval($this->attributes['id']);}
Copier après la connexion
Mais ce n'est pas le cas, l'accesseur d'attribut peut en effet faire devenir l'ID renvoyé par l'API au front end une chaîne. Mais cela affectera également les résultats de l'insertion et de la modification du modèle associé. Par exemple, si l'utilisateur est associé au modèle de publication, utilisez $user->posts()->saveMany(…); de cette façon. Le user_id correspondant sera vide.
Ce n'est pas difficile à comprendre, car l'accesseur du modèle doit participer au traitement lié au modèle. L'accesseur convertit l'ID d'un nombre en chaîne, ce qui conduit naturellement à une confusion des données.
Calmez-vous et décidez de bien réfléchir avant d'agir. Après avoir vérifié la documentation officielle, j'ai trouvé que Resource était exactement ce que je voulais. La ressource n'affectera que les données renvoyées au front-end. Nous pouvons personnaliser la ressource pour implémenter la structure, la conversion de type et d'autres fonctions du résultat de retour de l'API. Il est facile de changer d'identifiant.
Pour éviter les ennuis, je modifie directement la classe de base AppHttpResource. Surchargez simplement sa méthode toArray() et utilisez la récursivité pour convertir les valeurs qui peuvent dépasser la plage de sécurité de JS. Vous pouvez également créer une nouvelle classe Resource, telle que UserResource, en fonction de votre situation réelle.
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class Resource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
*
* @return array
*/
public function toArray($request)
{
$parentReturn = parent::toArray($request);
foreach (array_keys($parentReturn) as $key) {
// 为方便演示这里把所有整型字段都转成字符串
if (is_int($parentReturn[$key])) {
$parentReturn[$key] = strval($parentReturn[$key]);
}
// 关联的字段,如 $user->post,相当于递归处理
if (is_array($parentReturn[$key])) {
$parentReturn[$key] = new Resource($parentReturn[$key]);
}
}
return $parentReturn;
}
}
Copier après la connexion
Ensuite, renvoyez Resource dans le contrôleur d'interface pour renvoyer des données, et la valeur du champ entier deviendra automatiquement une chaîne.
<?php
namespace App\Http\Controllers;
use App\Http\Resources\Resource;
use App\Models\User;
use Illuminate\Http\Request;
class TestController extends Controller
{
/**
* @return \App\Http\Resources\Resource
*/
public function __invoke(Request $request)
{
$user = User::first();
return new Resource($user);
}
}
Copier après la connexion
Le résultat est le suivant :
- Parce que cette méthode utilise traversal , et il existe un traitement récursif, qui peut avoir un certain impact sur les performances lorsque la structure des données est complexe et que la quantité de données est importante. Je pense que c'est une façon paresseuse d'écrire. Si vous recherchez des performances, il serait préférable de personnaliser la classe Resource, puis de la convertir en fonction de noms de champs connus spécifiques
- car elle renvoie. L'ID du front-end est converti en chaîne. Le front-end effectue des comparaisons et des jugements, en particulier ===. Portez une attention particulière à
.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!