英文:
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.
use App\Models\AccountStatus;
use App\Models\AccountType;
use App\Models\AlertLevel;
class ClientController extends Controller
{
public function getAccountStatuses() {
try {
$accountStatuses = AccountStatus::all();
return response()->json([
'error' => false,
'message' => 'OK',
'account_statuses' => $accountStatuses
]);
} catch (\Exception $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
], 500);
}
}
public function getAccountTypes() {
try {
$accountTypes = AccountType::all();
return response()->json([
'error' => false,
'message' => 'OK',
'account_types' => $accountTypes
]);
} catch (\Exception $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
], 500);
}
}
public function getAlertLevels() {
try {
$alertLevels = AlertLevel::all();
return response()->json([
'error' => false,
'message' => 'OK',
'alert_levels' => $alertLevels
]);
} catch (\Exception $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
], 500);
}
}
}
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:
class ResponseBuilder
{
public function createResponseFromData(string $dataResponseKey, $data)
{
try {
return response()->json([
'error' => false,
'message' => 'OK',
$dataResponseKey => $data
]);
} catch (\Exception $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
], 500);
}
}
}
This will respect Single Responsibility Principle, and in your Controller, just inject it and use it:
private ResponseBuilder $responseBuilder;
public function __construct(ResponseBuilder $responseBuilder)
{
$this->responseBuilder = $responseBuilder;
}
public function getAccountStatuses()
{
$accountStatuses = AccountStatus::all();
return $this->responseBuilder->createResponseFromData('account_statuses', $accountStatuses);
}
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:
class ResponseBuilder
{
public function createResponseFromData(string $dataResponseKey, $data)
{
try {
return response()->json([
'error' => false,
'message' => 'OK',
$dataResponseKey => $data
]);
} catch (\Exception $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
], 500);
}
}
}
This will respect Single Responsability Principle, and in your Controller, just inject it and use it:
private ResponseBuilder $responseBuilder;
public function __construct(ResponseBuilder $responseBuilder)
{
$this->responseBuilder = $responseBuilder;
}
public function getAccountStatuses()
{
$accountStatuses = AccountStatus::all();
return $this->responseBuilder->createResponseFromData('account_statuses', $accountStatuses);
}
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文件来处理响应。
<?php
namespace App\Http\Traits;
trait ResponseHandler {
public function successResponse($responseKey='data', $data) {
return response()->json([
'error' => false,
'message' => 'OK',
$responseKey => $data
]);
}
public function errorResponse($errorMessage) {
return response()->json([
'error' => true,
'message' => $errorMessage
], 500);
}
}
在您的ClientController.php中,您可以使用ResponseHandler.php。
<?php
use App\Models\AccountStatus;
use App\Models\AccountType;
use App\Models\AlertLevel;
use App\Http\Traits\ResponseHandler;
class ClientController extends Controller
{
use ResponseHandler;
public function getAccountStatuses()
{
try {
$accountStatuses = AccountStatus::all();
return $this->successResponse('account_types', $accountStatuses);
} catch (\Exception $e) {
return $this->errorResponse($e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine());
}
}
}
其他方法:
您还可以尝试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.
<?php
namespace App\Http\Traits;
trait ResponseHandler {
public function successResponse($responseKey='data', $data) {
return response()->json([
'error' => false,
'message' => 'OK',
$responseKey => $data
]);
}
public function errorResponse($errorMessage) {
return response()->json([
'error' => true,
'message' => $errorMessage
], 500);
}}
In Your Clientcontroller.php you can use ResponseHandler.php
<?php
use App\Models\AccountStatus;
use App\Models\AccountType;
use App\Models\AlertLevel;
use App\Http\Traits\ResponseHandler;
class ClientController extends Controller
{
use ResponseHandler;
public function getAccountStatuses()
{
try {
$accountStatuses = AccountStatus::all();
return $this->successResponse('account_types', $accountStatuses);
} catch (\Exception $e) {
return $this->errorResponse($e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine());
}
}
}
Other ways:
- Try Repository patterns
- 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
/**
* 将资源转换为数组。
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
// 在这里定义您的数据结构
return [
'users' => $this->resource
];
}
控制器
public function __invoke(Request $request)
{
$users = $this->userService->get(); // 返回一个模型集合
// 成功响应
return new UserListResource($users);
}
一个处理错误响应的简单示例。
创建错误资源
php artisan make:resource ErrorResource
ErrorResource
public function with(Request $request)
{
return [
'code' => 999, // 如果需要,可以是您系统的错误代码
'messages' => $this->resource->getMessage()
];
}
public function toArray(Request $request): array
{
return [];
}
在JSON解码响应后,应该是这样的:
{
'data': [],
'code': 999,
'messages': "错误消息"
}
处理异常
在app\Exceptions\Handler.php中
$this->renderable(function (Throwable $e, $request) {
if ($request->is('api/*')) { // 确保异常发生在API而不是Web中
return (new ExceptionResponse($e))->response()->setStatusCode(500);
}
});
您可以在这里找到文档。
英文:
There is a JsonResource
in Laravel can help you building json response.
Make a JsonResource
php artisan make:resource UserListResource
UserListResource
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
// Defined your data structure here
return [
'users' => $this->resource
];
}
Controller
public function __invoke(Request $request)
{
$users = $this->userService->get(); // Return a Model Collection
// Success response
return new UserListResource($users);
}
An simple example for handle error response.
Make error resource
php artisan make:resource ErrorResource
ErrorResource
public function with(Request $request)
{
return [
'code' => 999, // error code of your system if you need
'messages' => $this->resource->getMessage()
];
}
public function toArray(Request $request): array
{
return [];
}
After json decode the response should be:
{
'data': [],
'code': 999,
'messages': "error message"
}
Handle exceptions
In app\Exceptions\Handler.php
$this->renderable(function (Throwable $e, $request) {
if ($request->is('api/*')) { // Ensure exception is during api instead of web
return (new ExceptionResponse($e))->response()->setStatusCode(500);
}
});
You can find the document from here.
答案4
得分: -1
我们可以将此函数存储在一个特性中并使用它。传递模型名称,可以是任何你想要获取数据的模型。在你的情况下,account_statuses
、account_types
和 alert_levels
。
public function getData($model) {
try {
$data = $model::all();
return response()->json([
'error' => false,
'message' => 'OK',
'account_statuses' => $data
]);
} catch (\Exception $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
], 500);
}
}
例如:
$accountStatus = getData('AccountStatus');
$accountType = getData('AccountType');
$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
.
public function getData($model) {
try {
$data = $model::all();
return response()->json([
'error' => false,
'message' => 'OK',
'account_statuses' => $data
]);
} catch (\Exception $e) {
return response()->json([
'error' => true,
'message' => $e->getMessage() . ' ' . $e->getFile() . ' ' . $e->getLine()
], 500);
}
}
For eg :
$accountStatus = getData('AccountStatus');
$accountType = getData('AccountType');
$alertLevels = getData('AlertLevel');
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论