使用 Laravel 后模型中的动态键从嵌套数组填充平面数组

问题描述 投票:0回答:2

我想使用 DeepL 来翻译我的 Laravel Post 模型。问题是,他们的 API 要求我们提交一个平面数组的翻译。例如。我们的有效载荷是 -

{
    "target_lang": "ES",
    "text": [
        "The post title",
        "A quote goes here (translatable)",
        "<p>A content block goes here (translatable)</p>",
        "A quote goes here",
        "<p>A content block goes here (translatable)<\/p>"
    ]
}

但是,我的实际帖子使用“内容”数组来定义内容块,如下所示:

[
  {
    "type": "quote",
    "data": {
      "name": "A quote name",
      "quote": "A quote goes here (translatable)"
    }
  },
  {
    "type": "content",
    "data": {
      "content": "<p>A content block goes here (translatable)<\/p>"
    }
  },
  {
    "type": "quote",
    "data": {
      "name": "A quote name (not translatable)",
      "quote": "A quote goes here"
    }
  },
  {
    "type": "content",
    "data": {
      "content": "<p>A content block goes here (translatable)<\/p>"
    }
  }
]

上面的数据非常灵活多变,但始终取决于块类型。我可以使用如下所示轻松地将数据扁平化:

public function translatableAttributes(): array
{
    return [
        $this->title,
        ...collect($this->content)
            ->mapWithKeys(fn (array &$content) => match ($content['type']) {
                'quote' => $content['data']['quote'],
                'content' => $content['data']['content'],
            })->flatten()->toArray(),
    ];
}

但我遇到的大问题是将其推回到数组中。我只是想不出一种方法可以在保持灵活性的同时做到这一点。

我想过也许实现承诺,然后为每个键解决它们,但再次无法思考如何实现这一点。

我可以进行单独的 API 调用,但当我可以在一次 API 调用中一次翻译 50 个字符串时,这又是非常低效的。

php arrays laravel multidimensional-array deepl
2个回答
1
投票

我建议使用简单的 array_map()

public function translatableAttributes(): array
{
    return [
        $this->title,
        ...array_map(
            fn($content) => $content['data'][$content['type']],
            $this->content,
        ),
    ];
}

public function applyTranslations(array $translations): void
{
    $this->title = $translations[0];
    $this->content = array_map(
        static function ($content, $translation) {
            $content['data'][$content['type']] = $translation;
            return $content;
        },
        $this->content,
        array_slice($translations, 1),
    );
}

更复杂,但更灵活(例如,如果一个内容中有多个翻译字段;那么我们需要在 getTranslatableKeys() 中使用

foreach

public function translatableAttributes(): array
{
    return [
        $this->title,
        ...array_map(
            fn($key) => Arr::get($this->content, $key),
            $this->getTranslatableKeys(),
        ),
    ];
}

private function getTranslatableKeys(): array
{
    return array_map(
        fn($content, $index) => $index.'.data.'.$content['type'],
        $this->content,
        array_keys($this->content),
    );
}

public function applyTranslations(array $translations): void
{
    $this->title = $translations[0];
    foreach ($this->getTranslatableKeys() as $index => $key) {
        Arr::set($this->content, $key, $translations[$index + 1]);
    }
}

0
投票

具有数组解构语法的无体 foreach 循环可以通过动态键路径将所需值推送到结果数组中。

代码:(演示)(或使用循环体

$payload = [
    'target_lang' => 'ES',
    'text' => ['The post title']
];
foreach ($array as ['type' => $t, 'data' => [$t => $payload['text'][]]]);
var_export($payload);

输出:

array (
  0 => 'The post title',
  1 => 'A quote goes here (translatable)',
  2 => '<p>A content block goes here (translatable)</p>',
  3 => 'A quote goes here',
  4 => '<p>A content block goes here (translatable)</p>',
)
© www.soinside.com 2019 - 2024. All rights reserved.