Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,32 @@ class UserFeedItem extends FeedItem
}
```

#### Adding an array of elements

In some cases, you need to place an array of elements with the same names. For example:

```xml
<picture>https://via.placeholder.com/640x480.png/009966?text=beatae</picture>
<picture>https://via.placeholder.com/640x480.png/000011?text=deleniti</picture>
<picture>https://via.placeholder.com/640x480.png/009999?text=voluptates</picture>
```

To do this, add a symbol of `@` to the beginning of the key name:

```php
use DragonCode\LaravelFeed\Feeds\Items\FeedItem;

class UserFeedItem extends FeedItem
{
public function toArray(): array
{
return [
'@picture' => $this->model->images,
];
}
}
```

#### Header information

If it is necessary to change the file cap, override the `header` method in the feed class:
Expand Down
26 changes: 24 additions & 2 deletions src/Services/ConvertToXml.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
use DOMElement;
use DragonCode\LaravelFeed\Feeds\Items\FeedItem;
use Illuminate\Container\Attributes\Config;
use Illuminate\Support\Str;

use function htmlspecialchars;
use function is_array;
use function is_bool;
use function preg_replace;
use function str_replace;
use function str_starts_with;

class ConvertToXml
{
Expand Down Expand Up @@ -54,6 +57,7 @@ protected function performItem(DOMElement $parent, array $items): void
$this->isAttributes($key) => $this->setAttributes($parent, $value),
$this->isCData($key) => $this->setCData($parent, $value),
$this->isMixed($key) => $this->setMixed($parent, $value),
$this->isArray($key) => $this->setItemsArray($parent, $value, $key),
default => $this->setItems($parent, $key, $value),
};
}
Expand All @@ -74,6 +78,11 @@ protected function isMixed(string $key): bool
return $key === '@mixed';
}

protected function isArray(string $key): bool
{
return str_starts_with($key, '@');
}

protected function createElement(string $name, bool|float|int|string|null $value = ''): DOMElement
{
return $this->document->createElement($name, $this->convertValue($value));
Expand Down Expand Up @@ -101,6 +110,15 @@ protected function setMixed(DOMElement $element, string $value): void
$element->appendChild($fragment);
}

protected function setItemsArray(DOMElement $parent, mixed $value, string $key): void
{
$key = Str::substr($key, 1);

foreach ($value as $item) {
$this->setItems($parent, $key, $item);
}
}

protected function setItems(DOMElement $parent, string $key, mixed $value): void
{
$element = $this->createElement($key, is_array($value) ? '' : $this->convertValue($value));
Expand All @@ -117,13 +135,17 @@ protected function toXml(DOMElement $item): string
return $this->document->saveXML($item);
}

protected function convertKey(string $key): string
protected function convertKey(int|string $key): string
{
return str_replace(' ', '_', $key);
return str_replace(' ', '_', (string) $key);
}

protected function convertValue(bool|float|int|string|null $value): string
{
if (is_bool($value)) {
return $value ? 'true' : 'false';
}

return $this->removeControlCharacters(
htmlspecialchars((string) $value)
);
Expand Down
6 changes: 6 additions & 0 deletions tests/.pest/snapshots/Feature/YandexTest/export.snap
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<price>100</price>
<currencyId>RUR</currencyId>
<vendor>The Best</vendor>
<picture>https://via.placeholder.com/640x480.png/008877?text=repudiandae</picture>
</offer>
<offer id="2" available="true" type="vendor.model">
<url>http://localhost/products/GD-PRDCT-2</url>
Expand All @@ -34,6 +35,9 @@
<price>250</price>
<currencyId>RUR</currencyId>
<vendor>The Best</vendor>
<picture>https://via.placeholder.com/640x480.png/009966?text=beatae</picture>
<picture>https://via.placeholder.com/640x480.png/000011?text=deleniti</picture>
<picture>https://via.placeholder.com/640x480.png/009999?text=voluptates</picture>
</offer>
<offer id="3" available="false" type="vendor.model">
<url>http://localhost/products/GD-PRDCT-3</url>
Expand All @@ -44,6 +48,8 @@
<price>400</price>
<currencyId>RUR</currencyId>
<vendor>The Best</vendor>
<picture>https://via.placeholder.com/640x480.png/000044?text=asperiores</picture>
<picture>https://via.placeholder.com/640x480.png/0055ff?text=expedita</picture>
</offer>
</offers>

Expand Down
26 changes: 12 additions & 14 deletions workbench/app/Data/ProductFakeData.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace Workbench\App\Data;

use function json_encode;

class ProductFakeData
{
public static function toArray(): array
Expand All @@ -22,9 +20,9 @@ public static function toArray(): array

'brand' => 'The Best',

'images' => json_encode([
'https://via.placeholder.com/640x480.png/00ff55?text=s1',
]),
'images' => [
'https://via.placeholder.com/640x480.png/008877?text=repudiandae',
],

'created_at' => '2025-08-31 00:00:00',
'updated_at' => '2025-08-31 20:00:00',
Expand All @@ -40,11 +38,11 @@ public static function toArray(): array

'brand' => 'The Best',

'images' => json_encode([
'https://via.placeholder.com/640x480.png/00ff55?text=s20',
'https://via.placeholder.com/640x480.png/00ff55?text=s21',
'https://via.placeholder.com/640x480.png/00ff55?text=s22',
]),
'images' => [
'https://via.placeholder.com/640x480.png/009966?text=beatae',
'https://via.placeholder.com/640x480.png/000011?text=deleniti',
'https://via.placeholder.com/640x480.png/009999?text=voluptates',
],

'created_at' => '2025-08-30 00:00:00',
'updated_at' => '2025-08-30 19:00:00',
Expand All @@ -60,10 +58,10 @@ public static function toArray(): array

'brand' => 'The Best',

'images' => json_encode([
'https://via.placeholder.com/640x480.png/00ff55?text=s30',
'https://via.placeholder.com/640x480.png/00ff55?text=s31',
]),
'images' => [
'https://via.placeholder.com/640x480.png/000044?text=asperiores',
'https://via.placeholder.com/640x480.png/0055ff?text=expedita',
],

'created_at' => '2025-08-29 00:00:00',
'updated_at' => '2025-08-29 18:00:00',
Expand Down
4 changes: 2 additions & 2 deletions workbench/app/Feeds/Items/YandexFeedItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function attributes(): array
return [
'id' => $this->model->id,

'available' => ! empty($this->model->quantity) ? 'true' : 'false',
'available' => ! empty($this->model->quantity),

'type' => 'vendor.model',
];
Expand All @@ -40,7 +40,7 @@ public function toArray(): array
'currencyId' => 'RUR',
'vendor' => $this->model->brand,

// 'picture' => $this->model->images,
'@picture' => $this->model->images,
];
}
}
4 changes: 4 additions & 0 deletions workbench/app/Models/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ class Product extends Model

'images',
];

protected $casts = [
'images' => 'array',
];
}
6 changes: 2 additions & 4 deletions workbench/database/factories/ProductFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

use function json_encode;

class ProductFactory extends Factory
{
public function definition(): array
Expand All @@ -24,11 +22,11 @@ public function definition(): array
'quantity' => fake()->numberBetween(0, 10),
'currency' => fake()->currencyCode(),

'images' => json_encode([
'images' => [
fake()->imageUrl(),
fake()->imageUrl(),
fake()->imageUrl(),
]),
],
];
}
}