Products in the Laravel shop are not managed directly. They are imported from the CakePHP image processing tool (tool.rugartisan.com), which is the source of truth for the product catalog. The import is triggered manually via an Artisan command and pulls data through an HTTP API.
| System | Role | Port |
|---|---|---|
tool.rugartisan.com |
Source of truth — designs, products, pricing, images | api.rugartisan.com (API), tool.rugartisan.com (media) |
rugartisan.com |
Storefront — receives and stores imported products | 8001 |
The two systems have separate databases. Laravel stores a copy of the product data after import, along with ra_product_id as a foreign key back to the CakePHP product.
php artisan import:run {design_category} {local_category_name}
| Argument | Description | Example |
|---|---|---|
design_category |
Category slug on the CakePHP side — filters which products the API returns | geometric |
local_category_name |
Category name in Laravel's DB — the category imported products are assigned to | "Geometric" |
php artisan import:run geometric "Geometric"
This fetches all products tagged geometric from the CakePHP API and assigns them to the "Geometric" collection category in Laravel.
If no arguments are passed, design_category is empty (returns all products from CakePHP) and products will have no category assigned.
Note: There is no UI button for this. It must be run manually from the terminal over SSH.
Calls POST /api/getColors and upserts results into Laravel's attribute_options table for the color attribute. New colors are added; existing ones (matched by seo_name/slug) are updated.
Calls POST /api/getTags and upserts results into attribute_options for the producttags attribute. Same upsert logic as colors.
POST https://api.rugartisan.com/api/export?category={design_category}
Returns a flat array of product records. Each record contains SKU, name, weaving type, material, shape, pricing per currency, image URLs, tags, available customization options, and more.
Authentication uses authkey and token headers (configured via API_ENDPOINT_AUTH_KEY and API_ENDPOINT_VENDOR_KEY in .env).
For each product returned by the API:
products by SKU.weavingtype, material, and shape values are looked up in attribute_options by their seo_name to get Laravel's internal IDs.productRepository->update() — Bagisto's repository writes to products, product_flat, product_attribute_values, and product_images.product_attribute_values. This step overwrites those back to human-readable names (e.g. Handknotted, Rectangle) so they display correctly.product_flat across locales — the custom rug fields (available_shapes, available_materials, available_weaving_types, and their labels) are copied from the default locale row to all other locale rows.Image URLs from CakePHP's product_media array are stored in Laravel's product_images table. The CakePHP product ID in the URL is replaced with the SKU. Images are not downloaded — the URLs point to the CakePHP media server at https://tool.rugartisan.com/media/.
| Laravel Field | CakePHP Source Field | Notes |
|---|---|---|
sku |
sku |
Used as the unique key for upsert |
name |
name |
|
ra_product_id |
id |
Foreign key back to CakePHP |
price |
price_usd_ft / price_gbp_ft / etc. |
Selected based on active channel currency |
cost |
price_usd_cm / price_gbp_cm / etc. |
Per-cm price, used for custom size calculation |
weavingtype |
weaving_type |
Resolved to attribute_option.id |
material |
material |
Resolved to attribute_option.id |
shape |
shape |
Resolved to attribute_option.id |
design_color |
color_weight_new[0] |
Primary color data for the design |
pile_height |
pile_height |
|
available_shapes |
avalable_shapes |
JSON list of shapes the rug can be ordered in |
available_weaving_types |
available_weaving_types |
JSON list of weaving options |
available_materials |
available_materials |
JSON list of material options |
delivery_time |
shipment_time |
|
meta_keywords |
keywords |
|
is_default |
is_default |
|
producttags |
product_tags |
Resolved to attribute_option slugs |
product_media |
product_media[].image_url |
Image URLs with ID replaced by SKU |
thumbnail |
product_media where image_type = thumbnail |
|
url_key |
Constructed from name + weaving_type + shape + material |
e.g. custom-rug/custom-floral-handknotted-rectangle-wool-rug.html |
| Table | What is written |
|---|---|
products |
One row per SKU; ra_product_id links back to CakePHP |
product_flat |
Denormalized product data per channel + locale combination |
product_attribute_values |
EAV values for all product attributes |
product_images |
Image URL paths pointing to CakePHP media server |
attribute_options |
Color and tag options synced from CakePHP |
The command is safe to re-run. Products are matched by SKU:
| Command | Purpose |
|---|---|
import:run |
Full product import from CakePHP API |
updateprice:run |
Re-fetches and updates pricing only, in paginated batches |
API_ENDPOINT=https://api.rugartisan.com/api
API_ENDPOINT_AUTH_KEY=...
API_ENDPOINT_VENDOR_KEY=...
DESIGN_TOOL_BASE_URL=https://tool.rugartisan.com/
TOOL_BASE_IMAGE_URL=https://tool.rugartisan.com/media/