PHPackages                             nieknijland/motor-occasion-php - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. nieknijland/motor-occasion-php

ActiveLibrary

nieknijland/motor-occasion-php
==============================

PHP Package to fetch from motoroccasion.nl

v1.1.1(1mo ago)2750↓42.9%[1 PRs](https://github.com/NiekNijland/motoroccasion-php/pulls)MITPHPPHP ^8.3CI passing

Since Feb 17Pushed 1mo agoCompare

[ Source](https://github.com/NiekNijland/motoroccasion-php)[ Packagist](https://packagist.org/packages/nieknijland/motor-occasion-php)[ Docs](https://github.com/nieknijland/motoroccasion-php)[ GitHub Sponsors](https://github.com/NiekNijland)[ RSS](/packages/nieknijland-motor-occasion-php/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (9)Dependencies (14)Versions (10)Used By (0)

motoroccasion-php
=================

[](#motoroccasion-php)

PHP client for [motoroccasion.nl](https://www.motoroccasion.nl) -- the largest used motorcycle marketplace in the Netherlands. Search listings, browse brands and types, view special dealer offers, and fetch full listing details with photos and specifications.

Requirements
------------

[](#requirements)

- PHP 8.3+
- `ext-dom`

Installation
------------

[](#installation)

```
composer require nieknijland/motoroccasion-php
```

Quick start
-----------

[](#quick-start)

```
use NiekNijland\MotorOccasion\MotorOccasion;
use NiekNijland\MotorOccasion\Data\SearchCriteria;

$client = new MotorOccasion();

// Find all Yamaha MT-07 listings
$brands = $client->getBrands();
$yamaha = $brands[3]; // YAMAHA

$types = $client->getTypesForBrand($yamaha);
$mt07 = $types[12]; // MT 07

$results = $client->search(new SearchCriteria(brand: $yamaha, type: $mt07));

echo "{$results->totalCount} motorcycles found\n";

foreach ($results->results as $listing) {
    echo "{$listing->brand} {$listing->model} - EUR {$listing->askingPrice} ({$listing->year})\n";
    // BMW R 1250 GS Adventure - EUR 18950 (2021)
}
```

Usage
-----

[](#usage)

### Brands and types

[](#brands-and-types)

Brands and types are the two-level hierarchy used by motoroccasion.nl. A brand is e.g. "BMW", and a type is e.g. "R 1250 GS". Both carry a `name` (display label) and `value` (internal ID used for searching).

```
$brands = $client->getBrands();
// [Brand(name: 'APRILIA', value: '1'), Brand(name: 'BMW', value: '4'), ...]

$types = $client->getTypesForBrand($brands[1]); // BMW
// [Type(name: 'C 1', value: '434'), Type(name: 'R 1250 GS', value: 'g911'), ...]

// Each type carries a reference back to its brand
echo $types[0]->brand->name; // "BMW"
```

### Categories

[](#categories)

Categories group motorcycles by style (Naked, Toer, Sport, etc.) and are parsed from the homepage.

```
$categories = $client->getCategories();
// [Category(name: 'All Off Road', value: '1'), Category(name: 'Naked', value: '43'), ...]
```

### Searching

[](#searching)

Pass a `SearchCriteria` object to `search()`. All filter fields are optional -- omit any you don't need.

```
use NiekNijland\MotorOccasion\Data\SearchCriteria;

// Simple: just a brand
$results = $client->search(new SearchCriteria(brand: $yamaha));

// Narrow it down: brand + type + price range + recent years
$results = $client->search(new SearchCriteria(
    brand: $yamaha,
    type: $mt07,
    priceMin: 4000,
    priceMax: 8000,
    yearMin: 2018,
));

// Filter by category, engine size, license type, etc.
$results = $client->search(new SearchCriteria(
    category: $categories[6],      // Naked
    engineCapacityMin: 600,
    engineCapacityMax: 900,
    license: LicenseCategory::A2,
    odometerMax: 30000,
));

// Search near a postal code
$results = $client->search(new SearchCriteria(
    brand: $yamaha,
    postalCode: '1012AB',
    radius: 50,
));

// Free-text keyword search
$results = $client->search(new SearchCriteria(
    keywords: 'quickshifter',
));

// Sort by price (low to high)
$results = $client->search(new SearchCriteria(
    brand: $yamaha,
    sortOrder: SortOrder::PriceAscending,
));

// Sort by year (newest first)
$results = $client->search(new SearchCriteria(
    brand: $yamaha,
    sortOrder: SortOrder::YearDescending,
));
```

All available `SearchCriteria` fields:

FieldTypeDescription`brand``?Brand`Filter by brand`type``?Type`Filter by type (model)`category``?Category`Filter by category (Naked, Sport, etc.)`priceMin` / `priceMax``?int`Price range in EUR`yearMin` / `yearMax``?int`Build year range`odometerMin` / `odometerMax``?int`Mileage range`engineCapacityMin` / `engineCapacityMax``?int`Engine displacement in cc`powerMin` / `powerMax``?int`Power in kW`license``?LicenseCategory`License type (A, A1, A2, AM, B)`electric``?bool`Electric motorcycles only`vatDeductible``?bool`VAT-deductible (BTW) only`postalCode``?string`Dutch postal code for proximity search`radius``?int`Radius in km (used with `postalCode`)`keywords``?string`Free-text search`selection``?string`Selection filter`sortOrder``?SortOrder`Sort order (default: relevance)`page``int`Page number (default: 1)`perPage``int`Results per page (default: 50, max: 50)### Search results and pagination

[](#search-results-and-pagination)

`search()` returns a `SearchResult` with the listings and pagination metadata.

```
$results = $client->search(new SearchCriteria(brand: $yamaha));

echo $results->totalCount;  // 1842
echo $results->currentPage;  // 1
echo $results->perPage;      // 50
echo $results->totalPages();  // 37
echo $results->hasNextPage(); // true

// Fetch page 2
$page2 = $client->search(new SearchCriteria(brand: $yamaha, page: 2));

// Use a smaller page size
$page1 = $client->search(new SearchCriteria(brand: $yamaha, perPage: 10));
```

Each result in the array is a `Result` object:

```
foreach ($results->results as $listing) {
    $listing->id;                  // 12345 (numeric listing ID, or null)
    $listing->brand;               // "YAMAHA"
    $listing->model;               // "MT 07"
    $listing->askingPrice;         // 6450 (EUR, or null for "prijs op aanvraag")
    $listing->priceType;           // PriceType::Asking (Asking, OnRequest, Negotiable, Bidding)
    $listing->year;                // 2019
    $listing->odometerReading;     // 23500
    $listing->odometerReadingUnit; // OdometerUnit::Kilometers
    $listing->image;               // "https://www.motoroccasion.nl/fotos/..."
    $listing->url;                 // "/motor/12345/yamaha-mt-07"
    $listing->originalPrice;       // 7200 (or null)
    $listing->monthlyLease;        // 134 (EUR/month, or null)
    $listing->seller->name;        // "Goedhart Motoren"
    $listing->seller->province;    // Province::ZuidHolland (or null)
    $listing->seller->website;     // "https://www.goedhart.nl"
}
```

### Listing details

[](#listing-details)

Fetch the full detail page for a listing. This provides additional info like color, power, photos, technical specs, description, and dealer contact details.

```
$detail = $client->getDetail($listing);

$detail->id;               // 12345 (numeric listing ID, or null)
$detail->brand;            // "YAMAHA"
$detail->model;            // "MT 07"
$detail->askingPrice;      // 6450 (EUR, or null for "prijs op aanvraag")
$detail->priceType;        // PriceType::Asking
$detail->originalPrice;    // 7200 (or null)
$detail->monthlyLease;     // 134 (EUR/month, or null)
$detail->year;             // 2019
$detail->odometerReading;  // 23500
$detail->odometerReadingUnit; // OdometerUnit::Kilometers
$detail->color;            // "ZWART"
$detail->powerKw;          // 55 (kW, or null)
$detail->license;          // LicenseCategory::A2 (or null)
$detail->warranty;         // true (or null)
$detail->images;           // ["https://...photo1.jpg", "https://...photo2.jpg", ...]
$detail->description;      // "Mooie MT-07 in perfecte staat..."
$detail->specifications;   // ["Merk" => "YAMAHA", "Model" => "MT 07", "Cilinderinhoud" => "689 cc", ...]
$detail->url;              // "/motor/12345/yamaha-mt-07"

// Engine sub-DTO (all fields nullable)
$detail->engine->capacityCc;      // 755 (engine displacement in cc)
$detail->engine->type;            // "Vloeistofgekoelde 4-takt paralleltwin"
$detail->engine->cylinders;       // 2
$detail->engine->valves;          // 8
$detail->engine->boreAndStroke;   // "87 mm x 87 mm"
$detail->engine->compressionRatio; // "11.0:1"
$detail->engine->fuelDelivery;    // "PGM-FI elektronische benzine injectie"
$detail->engine->fuelType;        // "Benzine"
$detail->engine->isElectric;      // false
$detail->engine->ignition;        // "Computergestuurde digitale transistor..."
$detail->engine->maxTorque;       // "75 Nm bij 7250 tpm"
$detail->engine->clutch;          // "Natte meerplaatskoppeling"
$detail->engine->gearbox;         // "6 versnellingen, manuele koppeling"
$detail->engine->driveType;       // "Ketting" (Ketting/Kardan/Riem)
$detail->engine->starter;         // "electrisch"
$detail->engine->topSpeed;        // "200 km/h"

// Chassis sub-DTO (all fields nullable)
$detail->chassis->abs;             // true
$detail->chassis->frameType;       // "Stalen buizenframe, diamant type"
$detail->chassis->frontSuspension; // "Showa 43 mm SFF-CA USD, 190 mm veerweg"
$detail->chassis->rearSuspension;  // "Pro-Link swingarm, 190 mm veerweg"
$detail->chassis->frontBrake;      // "Dubbele remschijf 310 x 4,5 mm..."
$detail->chassis->rearBrake;       // "enkelvoudige remschijf 256 x 6,0 mm..."
$detail->chassis->frontTire;       // "90/90-21"
$detail->chassis->rearTire;        // "150/70-18"

// Dimensions sub-DTO (all fields nullable)
$detail->dimensions->seatHeightMm;     // 830 (mm)
$detail->dimensions->wheelbaseMm;      // 1535 (mm)
$detail->dimensions->lengthMm;         // 2325 (mm)
$detail->dimensions->widthMm;          // 838 (mm)
$detail->dimensions->heightMm;         // 1450 (mm)
$detail->dimensions->tankCapacityLiters; // 16.9 (liters)
$detail->dimensions->weightKg;         // 208 (dry weight in kg)

// Listing-level fields (all nullable)
$detail->vatDeductible;          // false (VAT deductible)
$detail->licensePlate;           // "AB-123-CD" (Dutch license plate)
$detail->damageStatus;           // "schadevrij"
$detail->bodyType;               // "Naked"
$detail->roadTaxStatus;          // "Vrijgesteld"
$detail->availableColors;        // "Ross White Metallic, Mat Ballistic Black"
$detail->isNew;                  // true
$detail->modelYear;              // 2025 (distinct from build year)
$detail->factoryWarrantyMonths;  // 72 (factory warranty in months)
$detail->dealerDescription;      // "Voor kwaliteit en betrouwbaarheid..."

// Seller details
$detail->seller->name;       // "MotoPort Goes"
$detail->seller->website;    // "https://www.motoport.nl/goes"
$detail->seller->address;    // "Nobelweg 4"
$detail->seller->city;       // "Goes"
$detail->seller->phone;      // "0113-231640"
$detail->seller->postalCode; // "4462 GK" (Dutch postal code, or null)
```

Structured fields are extracted from both the technical specifications table and key-value pairs in descriptions. Data from both sources is merged -- description values take precedence over tech table values for the same field. Not all listings contain these details -- when absent, fields are `null`. The raw `specifications` array and `description` remain available as fallback.

### Special offers

[](#special-offers)

Fetch dealer offers (discounted listings). These are paginated separately with 40 results per page by default.

```
$offers = $client->getOffers();

echo $offers->totalCount; // 1334
echo $offers->results[0]->originalPrice; // 11999 (was-price)
echo $offers->results[0]->monthlyLease;  // 134 (EUR/month)

// Paginate offers
$page2 = $client->getOffers(page: 2);
$page1 = $client->getOffers(page: 1, perPage: 20);

// Sort offers by price (default: recently updated)
$offers = $client->getOffers(sortOrder: SortOrder::PriceDescending);
```

### Province enum

[](#province-enum)

Seller locations are mapped to a `Province` enum. The site uses variable-length abbreviations (e.g. "NH", "Z-H", "GLD") which are automatically resolved.

```
use NiekNijland\MotorOccasion\Data\Province;

$listing->seller->province;          // Province::NoordHolland
$listing->seller->province->value;   // "Noord-Holland"

// Manual lookup
Province::tryFromAbbreviation('NH');  // Province::NoordHolland
Province::tryFromAbbreviation('Z-H'); // Province::ZuidHolland
Province::tryFromAbbreviation('GLD'); // Province::Gelderland
```

### OdometerUnit enum

[](#odometerunit-enum)

Odometer readings use the `OdometerUnit` enum instead of raw strings.

```
use NiekNijland\MotorOccasion\Data\OdometerUnit;

$listing->odometerReadingUnit;          // OdometerUnit::Kilometers
$listing->odometerReadingUnit->value;   // "KM"

// Available cases
OdometerUnit::Kilometers; // "KM"
OdometerUnit::Miles;      // "MI"
```

### LicenseCategory enum

[](#licensecategory-enum)

Dutch motorcycle license categories are represented as a `LicenseCategory` enum.

```
use NiekNijland\MotorOccasion\Data\LicenseCategory;

$detail->license;          // LicenseCategory::A2
$detail->license->value;   // "A2"

// Available cases
LicenseCategory::A;   // "A"  - full motorcycle license
LicenseCategory::A1;  // "A1" - light motorcycles (max 125cc / 11kW)
LicenseCategory::A2;  // "A2" - medium motorcycles (max 35kW)
LicenseCategory::AM;  // "AM" - mopeds
LicenseCategory::B;   // "B"  - trikes/quads (car license)

// Use in search criteria
$results = $client->search(new SearchCriteria(license: LicenseCategory::A2));
```

### PriceType enum

[](#pricetype-enum)

Listings can have different pricing models. The `PriceType` enum indicates how to interpret the `askingPrice` field.

```
use NiekNijland\MotorOccasion\Data\PriceType;

$listing->priceType;          // PriceType::Asking
$listing->priceType->value;   // "asking"

// Available cases
PriceType::Asking;      // "asking"     - regular asking price (askingPrice is set)
PriceType::OnRequest;   // "on_request" - "prijs op aanvraag" (askingPrice is null)
PriceType::Negotiable;  // "negotiable" - "n.o.t.k." (askingPrice is null)
PriceType::Bidding;     // "bidding"    - open for bids (askingPrice is null)

// Handle different price types
match ($listing->priceType) {
    PriceType::Asking     => "€ {$listing->askingPrice}",
    PriceType::OnRequest  => 'Prijs op aanvraag',
    PriceType::Negotiable => 'Nader overeen te komen',
    PriceType::Bidding    => 'Bieden',
};
```

### SortOrder enum

[](#sortorder-enum)

Control the order of search results and offers with the `SortOrder` enum.

```
use NiekNijland\MotorOccasion\Data\SortOrder;

// Available cases
SortOrder::Default;          // "default"   - relevance (search default)
SortOrder::RecentlyUpdated;  // "update"    - most recently updated (offers default)
SortOrder::BrandAscending;   // "merk-asc"  - brand + type A-Z
SortOrder::BrandDescending;  // "merk-desc" - brand + type Z-A
SortOrder::YearAscending;    // "bwjr-asc"  - year old to new
SortOrder::YearDescending;   // "bwjr-desc" - year new to old
SortOrder::PriceAscending;   // "pric-asc"  - price low to high
SortOrder::PriceDescending;  // "pric-desc" - price high to low

// Use in search
$results = $client->search(new SearchCriteria(
    brand: $yamaha,
    sortOrder: SortOrder::PriceAscending,
));

// Use in offers
$offers = $client->getOffers(sortOrder: SortOrder::YearDescending);
```

### Serialization

[](#serialization)

All DTOs support `toArray()` and `fromArray()` for serialization (e.g. caching or storing in a database). Enum values are serialized as their string backing values.

```
$array = $listing->toArray();
// ['brand' => 'YAMAHA', 'model' => 'MT 07', 'askingPrice' => 6450, 'priceType' => 'asking', 'odometerReadingUnit' => 'KM', 'seller' => ['name' => '...', ...], ...]

$restored = Result::fromArray($array);

// Also works for Brand, Category, Type, Seller, ListingDetail
$brand->toArray();                   // ['name' => 'BMW', 'value' => 'bmw']
Brand::fromArray($brandArray);
```

### Caching

[](#caching)

Pass any PSR-16 (`psr/simple-cache`) implementation to cache brands and categories, avoiding repeated HTTP requests.

```
use NiekNijland\MotorOccasion\MotorOccasion;

$client = new MotorOccasion(
    cache: $yourPsr16Cache,
    cacheTtl: 3600, // seconds (default: 1 hour)
);

$brands = $client->getBrands();      // fetched from site, stored in cache
$brands = $client->getBrands();      // returned from cache (no HTTP)
$categories = $client->getCategories(); // also cached
```

Calling `resetSession()` invalidates both in-memory and external cache entries.

### Session management

[](#session-management)

The client automatically manages PHP session cookies required by motoroccasion.nl. Sessions are established on the first API call and reused for subsequent calls. To force a fresh session:

```
$client->resetSession();
```

### Interface

[](#interface)

The client implements `MotorOccasionInterface`, which can be used for type-hinting and mocking in tests.

```
use NiekNijland\MotorOccasion\MotorOccasionInterface;

public function __construct(private MotorOccasionInterface $client) {}
```

### Error handling

[](#error-handling)

All public methods throw `MotorOccasionException` on HTTP failures or unexpected HTML structures.

```
use NiekNijland\MotorOccasion\Exception\MotorOccasionException;

try {
    $results = $client->search(new SearchCriteria(brand: $brand));
} catch (MotorOccasionException $e) {
    // "Could not fetch AJAX results from /mz.php"
    // "Could not retrieve session from motoroccasion.nl"
    echo $e->getMessage();
}
```

Testing
-------

[](#testing)

```
composer test
```

### Testing your application

[](#testing-your-application)

This package ships with a `FakeMotorOccasion` client and DTO factories in `NiekNijland\MotorOccasion\Testing\` to make it easy to test code that depends on this package — no HTTP mocking required.

#### FakeMotorOccasion

[](#fakemotoroccasion)

A drop-in replacement for the real client. Seed it with data and use it via dependency injection.

```
use NiekNijland\MotorOccasion\Testing\FakeMotorOccasion;
use NiekNijland\MotorOccasion\Testing\BrandFactory;
use NiekNijland\MotorOccasion\Testing\ResultFactory;

$fake = new FakeMotorOccasion(
    brands: BrandFactory::makeMany(5),
    results: ResultFactory::makeMany(10),
);

// Use it like the real client
$brands = $fake->getBrands();           // returns seeded brands
$results = $fake->search($criteria);    // paginates seeded results

// Assert calls were made
$fake->assertCalled('getBrands');
$fake->assertCalledTimes('search', 1);
$fake->assertNotCalled('getOffers');

// Simulate errors
$fake->shouldThrow(new MotorOccasionException('Service down'));
```

Fluent setters for configuration:

```
$fake = (new FakeMotorOccasion())
    ->setBrands(BrandFactory::makeMany(3))
    ->setCategories(CategoryFactory::makeMany(5))
    ->setResults(ResultFactory::makeMany(20));
```

For detail pages, map results to details:

```
$result = ResultFactory::make();
$detail = ListingDetailFactory::make(url: $result->url);

$fake->setDetail($result, $detail);
$fake->getDetail($result); // returns the seeded detail
```

#### DTO Factories

[](#dto-factories)

Every DTO has a factory with sensible defaults. Override only what you need:

```
use NiekNijland\MotorOccasion\Testing\ResultFactory;
use NiekNijland\MotorOccasion\Testing\ListingDetailFactory;
use NiekNijland\MotorOccasion\Testing\SellerFactory;

// One-liner with all defaults
$result = ResultFactory::make();

// Override specific fields
$result = ResultFactory::make(brand: 'Honda', askingPrice: 5000, year: 2023);

// Generate multiple
$results = ResultFactory::makeMany(10);

// ListingDetail — no more 17-parameter constructors
$detail = ListingDetailFactory::make(color: 'ROOD', warranty: false);

// Seller variants
$dealer = SellerFactory::makeDealer();   // full dealer info (address, phone, etc.)
$private = SellerFactory::makePrivate(); // "Particulier" with no contact info
```

Available factories:

FactoryMethod(s)Default`BrandFactory``make()`, `makeMany()`BMW`CategoryFactory``make()`, `makeMany()`Naked`TypeFactory``make()`, `makeMany()`R 1250 GS (BMW)`SellerFactory``make()`, `makeDealer()`, `makePrivate()`De Motor Shop`ResultFactory``make()`, `makeMany()`BMW R 1250 GS, EUR 18,950`ListingDetailFactory``make()`BMW R 1250 GS with full specs`EngineFactory``make()`All fields null`ChassisFactory``make()`All fields null`DimensionsFactory``make()`All fields nullLicense
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

47

—

FairBetter than 94% of packages

Maintenance89

Actively maintained with recent releases

Popularity23

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity55

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 97.3% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~4 days

Total

9

Last Release

54d ago

Major Versions

v0.1.4 → v1.0.02026-03-04

### Community

Maintainers

![](https://www.gravatar.com/avatar/4d9cb12c53e7e4ec9fdc27f74e8bbd725c61a8280780cffe7136c74f1df7570e?d=identicon)[NiekNijland](/maintainers/NiekNijland)

---

Top Contributors

[![NiekNijland](https://avatars.githubusercontent.com/u/43474728?v=4)](https://github.com/NiekNijland "NiekNijland (36 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

NiekNijlandmotoroccasion-php

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/nieknijland-motor-occasion-php/health.svg)

```
[![Health](https://phpackages.com/badges/nieknijland-motor-occasion-php/health.svg)](https://phpackages.com/packages/nieknijland-motor-occasion-php)
```

###  Alternatives

[laravel/framework

The Laravel Framework.

34.7k509.9M17.0k](/packages/laravel-framework)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[civicrm/civicrm-core

Open source constituent relationship management for non-profits, NGOs and advocacy organizations.

728272.9k20](/packages/civicrm-civicrm-core)[nutgram/nutgram

The Telegram bot library that doesn't drive you nuts

714214.9k8](/packages/nutgram-nutgram)[guanguans/notify

Push notification SDK(AnPush、Bark、Chanify、DingTalk、Discord、Gitter、GoogleChat、IGot、Lark、Mattermost、MicrosoftTeams、NowPush、Ntfy、Push、Pushback、PushBullet、PushDeer、PushMe、Pushover、PushPlus、QQ、RocketChat、ServerChan、ShowdocPush、SimplePush、Slack、Telegram、WeWork、WPush、XiZhi、YiFengChuanHua、ZohoCliq、ZohoCliqWebHook、Zulip).

682104.9k7](/packages/guanguans-notify)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

595.2M386](/packages/shopware-core)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
