Prevent repeating almost identical code in Laravel.

huangapple go评论92阅读模式
英文:

Prevent repeating almost identical code in laravel

问题

如何防止我重复编写这些几乎相同的代码?

英文:

I have a controller in my API that contains methods that fetches various data from different tables like account statuses, account types, etc and returns it to the API consumer.

  1. use App\Models\AccountStatus;
  2. use App\Models\AccountType;
  3. use App\Models\AlertLevel;
  4. class ClientController extends Controller
  5. {
  6. public function getAccountStatuses() {
  7. try {
  8. $accountStatuses = AccountStatus::all();
  9. return response()->json([
  10. 'error' => false,
  11. 'message' => 'OK',
  12. 'account_statuses' => $accountStatuses
  13. ]);
  14. } catch (\Exception $e) {
  15. return response()->json([
  16. 'error' => true,
  17. 'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
  18. ], 500);
  19. }
  20. }
  21. public function getAccountTypes() {
  22. try {
  23. $accountTypes = AccountType::all();
  24. return response()->json([
  25. 'error' => false,
  26. 'message' => 'OK',
  27. 'account_types' => $accountTypes
  28. ]);
  29. } catch (\Exception $e) {
  30. return response()->json([
  31. 'error' => true,
  32. 'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
  33. ], 500);
  34. }
  35. }
  36. public function getAlertLevels() {
  37. try {
  38. $alertLevels = AlertLevel::all();
  39. return response()->json([
  40. 'error' => false,
  41. 'message' => 'OK',
  42. 'alert_levels' => $alertLevels
  43. ]);
  44. } catch (\Exception $e) {
  45. return response()->json([
  46. 'error' => true,
  47. 'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
  48. ], 500);
  49. }
  50. }
  51. }

How do i prevent myself from repeating these almost identical code?

答案1

得分: 1

If you want to do some clean code, you should create a Class which will contain a function to handle your duplicate code:

  1. class ResponseBuilder
  2. {
  3. public function createResponseFromData(string $dataResponseKey, $data)
  4. {
  5. try {
  6. return response()->json([
  7. 'error' => false,
  8. 'message' => 'OK',
  9. $dataResponseKey => $data
  10. ]);
  11. } catch (\Exception $e) {
  12. return response()->json([
  13. 'error' => true,
  14. 'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
  15. ], 500);
  16. }
  17. }
  18. }

This will respect Single Responsibility Principle, and in your Controller, just inject it and use it:

  1. private ResponseBuilder $responseBuilder;
  2. public function __construct(ResponseBuilder $responseBuilder)
  3. {
  4. $this->responseBuilder = $responseBuilder;
  5. }
  6. public function getAccountStatuses()
  7. {
  8. $accountStatuses = AccountStatus::all();
  9. return $this->responseBuilder->createResponseFromData('account_statuses', $accountStatuses);
  10. }

You should declare an Interface (ResponseBuilderInterface) to inject it, this way your Controller won't be responsible for injection.

英文:

If you want to do some clean code, you should create a Class which will contain a function to handle your duplicate code:

  1. class ResponseBuilder
  2. {
  3. public function createResponseFromData(string $dataResponseKey, $data)
  4. {
  5. try {
  6. return response()->json([
  7. 'error' => false,
  8. 'message' => 'OK',
  9. $dataResponseKey => $data
  10. ]);
  11. } catch (\Exception $e) {
  12. return response()->json([
  13. 'error' => true,
  14. 'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
  15. ], 500);
  16. }
  17. }
  18. }

This will respect Single Responsability Principle, and in your Controller, just inject it and use it:

  1. private ResponseBuilder $responseBuilder;
  2. public function __construct(ResponseBuilder $responseBuilder)
  3. {
  4. $this->responseBuilder = $responseBuilder;
  5. }
  6. public function getAccountStatuses()
  7. {
  8. $accountStatuses = AccountStatus::all();
  9. return $this->responseBuilder->createResponseFromData('account_statuses', $accountStatuses);
  10. }

You should declare an Interface (ResponseBuilderInterface) to inject it, this way your Controller won't be responsible of injection.

答案2

得分: 1

Sure, here is the translated content:

好的,有许多方法可以防止重复相同的代码。这取决于开发者的技能、知识和经验。在我的情况下,我创建了一个trait文件来处理响应。

  1. <?php
  2. namespace App\Http\Traits;
  3. trait ResponseHandler {
  4. public function successResponse($responseKey='data', $data) {
  5. return response()->json([
  6. 'error' => false,
  7. 'message' => 'OK',
  8. $responseKey => $data
  9. ]);
  10. }
  11. public function errorResponse($errorMessage) {
  12. return response()->json([
  13. 'error' => true,
  14. 'message' => $errorMessage
  15. ], 500);
  16. }
  17. }

在您的ClientController.php中,您可以使用ResponseHandler.php。

  1. <?php
  2. use App\Models\AccountStatus;
  3. use App\Models\AccountType;
  4. use App\Models\AlertLevel;
  5. use App\Http\Traits\ResponseHandler;
  6. class ClientController extends Controller
  7. {
  8. use ResponseHandler;
  9. public function getAccountStatuses()
  10. {
  11. try {
  12. $accountStatuses = AccountStatus::all();
  13. return $this->successResponse('account_types', $accountStatuses);
  14. } catch (\Exception $e) {
  15. return $this->errorResponse($e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine());
  16. }
  17. }
  18. }

其他方法

  1. 尝试仓储模式
  2. 尝试服务仓储模式(我个人喜欢这种模式)

您还可以尝试Eloquent: API资源,这可以帮助您将模型和模型集合轻松转换为JSON。

英文:

Well, there can be many ways to stop repeating the identical codes. It depends on developer's skills, knowledge and experience. In my case I create A trait file to handel responses.

  1. &lt;?php
  2. namespace App\Http\Traits;
  3. trait ResponseHandler {
  4. public function successResponse($responseKey=&#39;data&#39;, $data) {
  5. return response()-&gt;json([
  6. &#39;error&#39; =&gt; false,
  7. &#39;message&#39; =&gt; &#39;OK&#39;,
  8. $responseKey =&gt; $data
  9. ]);
  10. }
  11. public function errorResponse($errorMessage) {
  12. return response()-&gt;json([
  13. &#39;error&#39; =&gt; true,
  14. &#39;message&#39; =&gt; $errorMessage
  15. ], 500);
  16. }}

In Your Clientcontroller.php you can use ResponseHandler.php

  1. &lt;?php
  2. use App\Models\AccountStatus;
  3. use App\Models\AccountType;
  4. use App\Models\AlertLevel;
  5. use App\Http\Traits\ResponseHandler;
  6. class ClientController extends Controller
  7. {
  8. use ResponseHandler;
  9. public function getAccountStatuses()
  10. {
  11. try {
  12. $accountStatuses = AccountStatus::all();
  13. return $this-&gt;successResponse(&#39;account_types&#39;, $accountStatuses);
  14. } catch (\Exception $e) {
  15. return $this-&gt;errorResponse($e-&gt;getMessage() . &#39; &#39; . $e-&gt;getFile() . &#39; &#39; . $e-&gt;getLine());
  16. }
  17. }
  18. }

Other ways:

  1. Try Repository patterns
  2. Try Service Repository Pattern (I personally like this pattern)

You should also try Eloquent: API Resources this can help you to expressively and easily transform your models and model collections into JSON.

答案3

得分: 1

在Laravel中有一个JsonResource可以帮助您构建JSON响应。

创建一个JsonResource

php artisan make:resource UserListResource

UserListResource

  1. /**
  2. * 将资源转换为数组。
  3. *
  4. * @return array<string, mixed>
  5. */
  6. public function toArray(Request $request): array
  7. {
  8. // 在这里定义您的数据结构
  9. return [
  10. 'users' => $this->resource
  11. ];
  12. }

控制器

  1. public function __invoke(Request $request)
  2. {
  3. $users = $this->userService->get(); // 返回一个模型集合
  4. // 成功响应
  5. return new UserListResource($users);
  6. }

一个处理错误响应的简单示例。

创建错误资源

php artisan make:resource ErrorResource

ErrorResource

  1. public function with(Request $request)
  2. {
  3. return [
  4. 'code' => 999, // 如果需要,可以是您系统的错误代码
  5. 'messages' => $this->resource->getMessage()
  6. ];
  7. }
  8. public function toArray(Request $request): array
  9. {
  10. return [];
  11. }

在JSON解码响应后,应该是这样的:

  1. {
  2. 'data': [],
  3. 'code': 999,
  4. 'messages': "错误消息"
  5. }

处理异常

在app\Exceptions\Handler.php中

  1. $this->renderable(function (Throwable $e, $request) {
  2. if ($request->is('api/*')) { // 确保异常发生在API而不是Web中
  3. return (new ExceptionResponse($e))->response()->setStatusCode(500);
  4. }
  5. });

您可以在这里找到文档。

英文:

There is a JsonResource in Laravel can help you building json response.

Make a JsonResource

php artisan make:resource UserListResource

UserListResource

  1. /**
  2. * Transform the resource into an array.
  3. *
  4. * @return array&lt;string, mixed&gt;
  5. */
  6. public function toArray(Request $request): array
  7. {
  8. // Defined your data structure here
  9. return [
  10. &#39;users&#39; =&gt; $this-&gt;resource
  11. ];
  12. }

Controller

  1. public function __invoke(Request $request)
  2. {
  3. $users = $this-&gt;userService-&gt;get(); // Return a Model Collection
  4. // Success response
  5. return new UserListResource($users);
  6. }

An simple example for handle error response.

Make error resource

php artisan make:resource ErrorResource

ErrorResource

  1. public function with(Request $request)
  2. {
  3. return [
  4. &#39;code&#39; =&gt; 999, // error code of your system if you need
  5. &#39;messages&#39; =&gt; $this-&gt;resource-&gt;getMessage()
  6. ];
  7. }
  8. public function toArray(Request $request): array
  9. {
  10. return [];
  11. }

After json decode the response should be:

  1. {
  2. &#39;data&#39;: [],
  3. &#39;code&#39;: 999,
  4. &#39;messages&#39;: &quot;error message&quot;
  5. }

Handle exceptions

In app\Exceptions\Handler.php

  1. $this-&gt;renderable(function (Throwable $e, $request) {
  2. if ($request-&gt;is(&#39;api/*&#39;)) { // Ensure exception is during api instead of web
  3. return (new ExceptionResponse($e))-&gt;response()-&gt;setStatusCode(500);
  4. }
  5. });

You can find the document from here.

答案4

得分: -1

我们可以将此函数存储在一个特性中并使用它。传递模型名称,可以是任何你想要获取数据的模型。在你的情况下,account_statusesaccount_typesalert_levels

  1. public function getData($model) {
  2. try {
  3. $data = $model::all();
  4. return response()->json([
  5. 'error' => false,
  6. 'message' => 'OK',
  7. 'account_statuses' => $data
  8. ]);
  9. } catch (\Exception $e) {
  10. return response()->json([
  11. 'error' => true,
  12. 'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
  13. ], 500);
  14. }
  15. }

例如:

  1. $accountStatus = getData('AccountStatus');
  2. $accountType = getData('AccountType');
  3. $alertLevels = getData('AlertLevel');
英文:

We can store this function in a trait and use it. Pass on the model name it can any model from which you want fetch data. In your case account_statuses, account_types and alert_levels.

  1. public function getData($model) {
  2. try {
  3. $data = $model::all();
  4. return response()-&gt;json([
  5. &#39;error&#39; =&gt; false,
  6. &#39;message&#39; =&gt; &#39;OK&#39;,
  7. &#39;account_statuses&#39; =&gt; $data
  8. ]);
  9. } catch (\Exception $e) {
  10. return response()-&gt;json([
  11. &#39;error&#39; =&gt; true,
  12. &#39;message&#39; =&gt; $e-&gt;getMessage() . &#39; &#39; . $e-&gt;getFile() . &#39; &#39; . $e-&gt;getLine()
  13. ], 500);
  14. }
  15. }

For eg :

  1. $accountStatus = getData(&#39;AccountStatus&#39;);
  2. $accountType = getData(&#39;AccountType&#39;);
  3. $alertLevels = getData(&#39;AlertLevel&#39;);

huangapple
  • 本文由 发表于 2023年6月13日 14:07:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76462082.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定