已完成setplayersjson方法的实现和测试!
实现内容
setplayersjson方法功能
根据用户要求,三丰云实现了setplayersjson(id数组, 中文属性名数组, value数组)方法,批量修改免费虚拟主机players.json文件中多个id的多个属性名对应字段值。
方法特点 1. 参数处理
- ids : 球员ID数组,支持逗号分隔的字符串或数组
- names : 中文属性名数组,支持逗号分隔的字符串或数组
- values : 要设置的新值数组,支持逗号分隔的字符串或数组
- 参数长度必须相同,否则返回错误 2. 文件锁定机制
使用排他锁(LOCK_EX)保证并发写入时的数据一致性:
if (!flock(KaTeX parse error: Expected '}', got 'EOF' at end of input: ...X)) { fclose(handle);
return json([
'success' => false,
'error' => '文件正在被其他用户使用,请稍后重试'
]);
}
- 类型转换
根据原始字段值的类型自动转换新值,确保类型一致性:
- 整数类型:使用 is_numeric() 检查并转换为 (int)
- 浮点数类型:使用 is_numeric() 检查并转换为 (float)
- 布尔类型:支持多种字符串表示('true', 'false', 'yes', 'no', '是', '否'等)
- 字符串类型:直接转换或JSON编码
- 数组类型:支持JSON字符串解析
- 批量处理优化
- 使用 $playersMap 建立ID到索引的映射,避免重复遍历
- 一次性读取、修改、写入整个JSON文件
- 单次文件锁定处理所有更新操作
- 返回格式
{
"success": true,
"message": "批量更新完成",
"data": {
"totalUpdates": 3,
"successCount": 3,
"errorCount": 0,
"results": [
{
"index": 0,
"id": "660",
"name": "中投",
"fieldName": "abilities.fg_base",
"success": true
}
],
"errors": []
}
} - 错误处理
- 参数为空时返回错误
- 参数长度不匹配时返回错误
- 文件不存在时返回错误
- 无法获取文件锁时返回错误
- JSON文件格式错误时返回错误
- 球员ID不存在时记录错误
- 中文属性名不存在时记录错误
- 类型转换失败时记录错误
javascript
public function setplayersjson(Request $request)
{
try {
error_reporting(E_ALL & ~E_DEPRECATED);
$ids = $request->post('ids') ?: $request->get('ids');
$names = $request->post('names') ?: $request->get('names');
$values = $request->post('values') !== null ? $request->post('values') : $request->get('values');
if (!$ids || !$names || $values === null) {
return json([
'success' => false,
'error' => '参数不能为空'
]);
}
if (is_string($ids)) {
$ids = array_map('trim', explode(',', $ids));
}
if (is_string($names)) {
$names = array_map('trim', explode(',', $names));
}
if (is_string($values)) {
$values = array_map('trim', explode(',', $values));
}
if (count($ids) !== count($names) || count($ids) !== count($values)) {
return json([
'success' => false,
'error' => 'id数组、属性名数组和value数组的长度必须相同'
]);
}
$seaValue = $this->getSeaValue();
$jsonPath = base_path() . "/data/{$seaValue}/players.json";
if (!file_exists($jsonPath)) {
return json([
'success' => false,
'error' => "文件不存在: players.json"
]);
}
$handle = fopen($jsonPath, 'r+');
if (!$handle) {
return json([
'success' => false,
'error' => '无法打开文件'
]);
}
if (!flock($handle, LOCK_EX)) {
fclose($handle);
return json([
'success' => false,
'error' => '文件正在被其他用户使用,请稍后重试'
]);
}
try {
$jsonContent = stream_get_contents($handle);
$jsonData = json_decode($jsonContent, true);
if (!$jsonData || !isset($jsonData['data']['players'])) {
flock($handle, LOCK_UN);
fclose($handle);
return json([
'success' => false,
'error' => "JSON文件格式错误"
]);
}
$playersMap = [];
foreach ($jsonData['data']['players'] as $index => $p) {
if (isset($p['id'])) {
$playersMap[$p['id']] = $index;
}
}
$results = [];
$errors = [];
for ($i = 0; $i < count($ids); $i++) {
$id = $ids[$i];
$name = $names[$i];
$value = $values[$i];
if (!isset($playersMap[$id])) {
$errors[] = [
'index' => $i,
'id' => $id,
'name' => $name,
'error' => "未找到ID为{$id}的球员"
];
continue;
}
$playerIndex = $playersMap[$id];
$jsonField = $this->getJsonFieldByChinese($name);
if (!$jsonField) {
$errors[] = [
'index' => $i,
'id' => $id,
'name' => $name,
'error' => "未找到中文属性名对应的字段: {$name}"
];
continue;
}
try {
$oldValue = null;
if (strpos($jsonField, '.') !== false) {
$parts = explode('.', $jsonField);
$current = &$jsonData['data']['players'][$playerIndex];
foreach ($parts as $j => $part) {
if ($j === count($parts) - 1) {
$oldValue = $current[$part] ?? null;
$convertedValue = $this->convertJsonValueByType($value, $oldValue);
$current[$part] = $convertedValue;
} else {
if (!isset($current[$part])) {
$current[$part] = [];
}
$current = &$current[$part];
}
}
} else {
$oldValue = $jsonData['data']['players'][$playerIndex][$jsonField] ?? null;
$convertedValue = $this->convertJsonValueByType($value, $oldValue);
$jsonData['data']['players'][$playerIndex][$jsonField] = $convertedValue;
}
$results[] = [
'index' => $i,
'id' => $id,
'name' => $name,
'fieldName' => $jsonField,
'success' => true
];
} catch (\Exception $e) {
$errors[] = [
'index' => $i,
'id' => $id,
'name' => $name,
'error' => $e->getMessage()
];
}
}
ftruncate($handle, 0);
rewind($handle);
$newJsonContent = json_encode($jsonData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
fwrite($handle, $newJsonContent);
flock($handle, LOCK_UN);
fclose($handle);
return json([
'success' => true,
'message' => '批量更新完成',
'data' => [
'totalUpdates' => count($ids),
'successCount' => count($results),
'errorCount' => count($errors),
'results' => $results,
'errors' => $errors
]
]);
} catch (\Exception $e) {
flock($handle, LOCK_UN);
fclose($handle);
return json([
'success' => false,
'error' => '批量更新球员数据失败: ' . $e->getMessage()
]);
}
} catch (\Exception $e) {
return json([
'success' => false,
'error' => '批量更新球员数据失败: ' . $e->getMessage()
]);
}
}