Products
To
Creating Products
One of the very few abilities of the admin panel is to create products. It should be straightforward enough, so not detailing that part here.
However if you need to create products from code, here are some examples:
Minimal Product
use Vanilo\Product\Models\Product;
// A product must have at least a name and an SKU:
$product = Product::create([
'name' => 'Dell Latitude E7240 Laptop',
'sku' => 'DLL-74237'
]);
echo $product->name;
// "Dell Latitude E7240 Laptop"
echo $product->slug;
// "dell-latitude-e7240-laptop"
The slugs are generated using the Eloquent-Sluggable library.
All Product Fields
Product::create([
'name' => 'Maxi Baxi 2000',
'sku' => 'MXB-2000',
'stock' => 123.4567,
'price' => 1999.95,
'original_price' => 2499.95,
'weight' => 1.3,
'width' => 27,
'height' => 21,
'length' => 60,
'slug' => 'maxi-baxi-2000',
'excerpt' => 'Maxi Baxi 2000 is the THING you always have dreamt of',
'description' => 'Maxi Baxi 2000 makes your dreams come true. See: https://youtu.be/5RKM_VLEbOc',
'state' => 'active',
'meta_keywords' => 'maxi, baxi, dreams',
'meta_description' => 'The THING you always have dreamt of'
]);
Searching Products
The ProductSearch
class provides a way to search for products and master products based on various criteria. The ProductSearch
class enables filtering by name, slug, taxons, channels, price ranges, and other attributes.
Finding Products by Name
Exact Match
This will return products and master products that contain "Shiny Glue" in their name.
$finder = new ProductSearch();
$result = $finder->nameContains('Shiny Glue')->getResults();
Starts With
Finds products and master products whose names start with "Mature", such as "Matured Cheese" or "Mature People".
$finder = new ProductSearch();
$result = $finder->nameStartsWith('Mature')->getResults();
Ends With
Finds products and master products where the name ends with "Transformator", such as "Bobinated Transformator".
$finder = new ProductSearch();
$result = $finder->nameEndsWith('Transformator')->getResults();
Multiple Matches
Returns multiple products and master products containing "Mandarin" in their names.
$finder = new ProductSearch();
$products = $finder->nameContains('Mandarin')->getResults();
Finding Products by Slug
Exact Slug Match
Returns the product with the exact matching slug.
$product = ProductSearch::findBySlug('nintendo-todd-20cm-plush');
Slug with Exception Handling
Throws a ModelNotFoundException
if the product is not found.
use Illuminate\Database\Eloquent\ModelNotFoundException;
try {
$product = ProductSearch::findBySlugOrFail('non-existent-slug');
} catch (ModelNotFoundException $e) {
// Handle case where product is not found
}
Filtering Products
By Taxon
use Vanilo\Category\Models\Taxon;
$taxon = Taxon::find(1);
$products = (new ProductSearch())->withinTaxon($taxon)->getResults();
By Channel
use Vanilo\Channel\Models\Channel;
$channel = Channel::find(1);
$products = (new ProductSearch())->withinChannel($channel)->getResults();
By Price Range
$products = (new ProductSearch())->priceBetween(100, 500)->getResults();
Filtering by Property Values
By Single Property Value
Filters products that have a specific property value.
use App\Models\PropertyValue;
$propertyValue = PropertyValue::find(1);
$products = (new ProductSearch())->havingPropertyValue($propertyValue)->getResults();
By Multiple Property Values
Filters products that match multiple property values.
$propertyValues = PropertyValue::whereIn('id', [1, 2, 3])->get();
$products = (new ProductSearch())->havingPropertyValues($propertyValues->toArray())->getResults();
By Property Name and Values
Filters products by a property name and its corresponding values.
$products = (new ProductSearch())->havingPropertyValuesByName('color', ['red', 'blue'])->getResults();
Using OR Conditions for Property Values
Applies an OR condition when filtering by multiple property values.
$products = (new ProductSearch())->orHavingPropertyValues($propertyValues->toArray())->getResults();
Filtering by Custom Attributes
These custom attributes are standard product fields that must be added through separate migrations. They are distinct from the 'properties' feature and do not interact with it.
Filtering by Color
$products = (new ProductSearch())->where('color', 'red')->getResults();
Filtering by Material
$products = (new ProductSearch())->where('material', 'cotton')->getResults();
Fields
Name | Type | Notes |
---|---|---|
id | autoinc | |
name | string | Required |
sku | string | Required |
slug | string | Nullable, default value is auto generated by Eloquent-Sluggable using product name |
stock | decimal(15,4) | Default value is 0 |
price | decimal(15,4) | Nullable |
original_price | decimal(15,4) | Nullable |
weight | decimal(15,4) | Nullable |
width | decimal(15,4) | Nullable |
height | decimal(15,4) | Nullable |
length | decimal(15,4) | Nullable |
excerpt (aka "short description") | string | Nullable |
description | string | Nullable |
state | ProductState | See product state section for detailed info |
ext_title | string(511) | Nullable, see product title section for detailed info |
meta_keywords | text | Nullable |
meta_description | text | Nullable |
Product Title
Product title is either the ext_title
field's value or the name
if
ext_title is empty.
$product = Product::create([
'name' => 'I am a product',
'sku' => 'N1'
]);
echo $product->title();
// "I am a product"
$product->ext_title = 'I am a product with attitudes';
echo $product->title();
// "I am a product with attitudes"
// It can be accessed as property as well:
echo $product->title;
// "I am a product with attitudes"
Product Stock
$product = Product::create([
'name' => 'Yet Another Product',
'sku' => 'YAP',
]);
echo $product->stock;
// 0
echo ($product->isOnStock() ? 'On Stock' : 'Not on Stock');
// "Not on Stock"
$product->stock = 34;
echo ($product->isOnStock() ? 'On Stock' : 'Not on Stock');
// "On Stock"
Product State
Product state is an enum.
use Vanilo\Product\Models\Product;
use Vanilo\Product\Models\ProductState;
// Supported product states out of the box:
print_r(ProductState::values());
//[
// "draft",
// "inactive",
// "active",
// "unavailable",
// "retired",
//]
$product = new Product();
// Product's state field is an enum:
echo get_class($product->state);
// "Vanilo\Product\Models\ProductState"
// Default value is draft:
echo $product->state->value();
// "draft"
// State can be set via scalar:
$product->state = 'inactive';
// State can be set via enum object:
$product->state = ProductState::INACTIVE();
// Products also have an 'isActive()' method:
echo $product->isActive();
// false
// Alternatively, this can be accessed as property too:
echo $product->is_active;
// false
// The isActive()/is_active flag is actually obtained from the state:
$product->state = ProductState::ACTIVE;
echo $product->isActive();
// true
For extending the product model and the product state enum, refer to the models and enums sections, respectively.
Product Images
Refer to the Modules vs. Framework page for understanding the difference between the two approaches.
Product Module Only - Without Framework
In case you're using the standalone product module only, then there's no product image support by default.
The contracts package defines the Buyable
interface
which extends the HasImages
interface that has 6 image related methods:
-
hasImage(): bool
-
imageCount(): int
(since v2.1) -
getThumbnailUrl(): ?string
-
getThumbnailUrls(): Collection
(since v2.1) -
getImageUrl(string $variant = ''): ?string
-
getImageUrls(string $variant = ''): Collection
(since v2.1)
The support package offers 2 traits for implementing the
image related functionality of the Buyable
interface:
-
BuyableNoImage
: "Null image" trait for products that don't actually have images -
HasImagesFromMediaLibrary
: adapter for using images with Spatie's Laravel Media Library
BuyableImageSpatieV7
andBuyableImageSpatieV8
traits are deprecated as of Vanilo v2.1, please use theHasImagesFromMediaLibrary
trait instead
In case you want to compose your own product model with Spatie image support:
namespace App;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Vanilo\Contracts\Buyable;
use Vanilo\Product\Models\Product as BaseProduct;
use Vanilo\Support\Traits\BuyableModel;
use Vanilo\Support\Traits\HasImagesFromMediaLibrary;
class Product extends BaseProduct implements Buyable, HasMedia
{
use BuyableModel; // Implements Buyable methods for common Eloquent models
use HasImagesFromMediaLibrary; // Implements Buyable's image methods using Spatie Media Library
use InteractsWithMedia; // Spatie package's default trait
}
It is also possible to add your very own implementation of these methods. The traits from the support package provide a convenient and common default implementation.
With The Framework
If you're using the Vanilo Framework (and not just the product module),
it already ships with an extended product model (Vanilo\Framework\Models\Product
) with image
support via Spatie Media Library.
Refer to the Spatie Media Library Documentation, to discover all the possibilities.
Add Multiple Product Images
// Example: in a controller action
public function store(Request $request)
{
$product = Product::create();
if (!empty($request->files->filter('images'))) {
$product->addMultipleMediaFromRequest(['images'])->each(function ($fileAdder) {
$fileAdder->toMediaCollection();
});
}
}
Define Image Variants
For more details about Vanilo Image handling, refer to the Handling Images section of this Documentation.