General
- Requests
- Pipelines
- Response Builders
- What are the available response builders?
- How do I pass data to a response?
- How do I redirect a response?
- How do I set the response status code?
- How do I set response headers?
- How do I attach middleware to a response builder?
- How do I change the response view?
- Services
- What is the tax accountant service?
- What is the combination serializer service?
- What is the login blocker service?
- What is the volume service?
- What is the weight service
- Commands
- Tutorials
Requests
What are the available requests?
Storefront
Listed below are all the storefront validation requests:
Aero\Store\Http\Requests\SearchRequestAero\Store\Http\Requests\CartDiscountCodeApplyAero\Store\Http\Requests\CreateAccountRequestAero\Store\Http\Requests\UpdateAccountDetailsRequestAero\Store\Http\Requests\UpdateAccountPasswordRequestAero\Store\Http\Requests\CreateAddressRequestAero\Store\Http\Requests\UpdateAddressRequest
Admin
Listed below are all the admin validation requests:
General
Aero\Admin\Http\Requests\CombinationFormRequestAero\Admin\Http\Requests\SeoFormRequestAero\Admin\Http\Requests\FileUploadRequestAero\Admin\Http\Requests\ImageUploadRequestAero\Admin\Http\Requests\CreateCommentRequestAero\Admin\Http\Requests\FilterSaveRequest
Catalog Management
Aero\Admin\Http\Requests\Catalog\CreateAttributeGroupRequestAero\Admin\Http\Requests\Catalog\UpdateAttributeGroupRequestAero\Admin\Http\Requests\Catalog\CreateCategoryRequestAero\Admin\Http\Requests\Catalog\UpdateCategoryRequestAero\Admin\Http\Requests\Catalog\CreateCollectionRequestAero\Admin\Http\Requests\Catalog\UpdateCollectionRequestAero\Admin\Http\Requests\Catalog\CreateManufacturerRequestAero\Admin\Http\Requests\Catalog\UpdateManufacturerRequestAero\Admin\Http\Requests\Catalog\CreateProductRequestAero\Admin\Http\Requests\Catalog\UpdateProductRequestAero\Admin\Http\Requests\Catalog\CreateTagGroupRequestAero\Admin\Http\Requests\Catalog\UpdateTagGroupRequest
Content Management
Aero\Admin\Http\Requests\Combinations\StoreRequestAero\Admin\Http\Requests\Combinations\UpdateRequestAero\Admin\Http\Requests\Content\Redirects\StoreAero\Admin\Http\Requests\Content\Redirects\UpdateAero\Admin\Http\Requests\Content\CreateBlockRequestAero\Admin\Http\Requests\Content\UpdateBlockRequestAero\Admin\Http\Requests\Content\CreatePageRequestAero\Admin\Http\Requests\Content\UpdatePageRequest
Customer Management
Aero\Admin\Http\Requests\Customers\CreateRequestAero\Admin\Http\Requests\Customers\UpdateRequestAero\Admin\Http\Requests\Customers\CreateCustomerGroupRequestAero\Admin\Http\Requests\Customers\UpdateCustomerGroupRequestAero\Admin\Http\Requests\Customers\UpdateAddressRequestAero\Admin\Http\Requests\Customers\LockCustomerRequest
Discount Management
Aero\Admin\Http\Requests\Discounts\CreateDiscountRequestAero\Admin\Http\Requests\Discounts\UpdateDiscountRequestAero\Admin\Http\Requests\Discounts\CreateVoucherRequestAero\Admin\Http\Requests\Discounts\UpdateVoucherRequestAero\Admin\Http\Requests\Discounts\CreatePriceListRequest
Order Management
Aero\Admin\Http\Requests\Orders\CreateOrderRequestAero\Admin\Http\Requests\Orders\EditOrderRequestAero\Admin\Http\Requests\Orders\CreateFulfillmentRequestAero\Admin\Http\Requests\Orders\UpdateFulfillmentRequestAero\Admin\Http\Requests\Orders\CreateReturnRequestAero\Admin\Http\Requests\Orders\PaymentCaptureRequestAero\Admin\Http\Requests\Orders\PaymentRefundRequestAero\Admin\Http\Requests\Orders\PaymentReleaseRequestAero\Admin\Http\Requests\Orders\ProcessFulfillmentsRequestAero\Admin\Http\Requests\Orders\UpdateBillingAddressRequestAero\Admin\Http\Requests\Orders\UpdateCustomerRequestAero\Admin\Http\Requests\Orders\UpdateDiscountRequestAero\Admin\Http\Requests\Orders\UpdateFlagsRequestAero\Admin\Http\Requests\Orders\UpdateFulfillmentRequestAero\Admin\Http\Requests\Orders\UpdateShippingAddressRequestAero\Admin\Http\Requests\Orders\UpdateShippingMethodRequestAero\Admin\Http\Requests\Orders\UpdateSubscriptionRequestAero\Admin\Http\Requests\Orders\ChangeOrderStatusRequest
Reports
Aero\Admin\Http\Requests\Reports\ExportReportRequest
Two Factor Authentication
Aero\Admin\Http\Requests\TwoFactorAuthentication\TwoFactorAuthenticationRequest
Configuration
Aero\Admin\Http\Requests\Settings\CreateAdminRequestAero\Admin\Http\Requests\Settings\UpdateAdminRequestAero\Admin\Http\Requests\Settings\CreateCountryGroupRequestAero\Admin\Http\Requests\Settings\UpdateCountryGroupRequestAero\Admin\Http\Requests\Settings\CreateCountryRequestAero\Admin\Http\Requests\Settings\UpdateCountryRequestAero\Admin\Http\Requests\Settings\CreateCurrencyRequestAero\Admin\Http\Requests\Settings\UpdateCurrencyRequestAero\Admin\Http\Requests\Settings\CreateCustomerTaxGroupRequestAero\Admin\Http\Requests\Settings\UpdateCustomerTaxGroupRequestAero\Admin\Http\Requests\Settings\CreateFlagRequestAero\Admin\Http\Requests\Settings\UpdateFlagRequestAero\Admin\Http\Requests\Settings\CreateFulfillmentMethodRequestAero\Admin\Http\Requests\Settings\UpdateFulfillmentMethodRequestAero\Admin\Http\Requests\Settings\CreateLocationRequestAero\Admin\Http\Requests\Settings\UpdateLocationRequestAero\Admin\Http\Requests\Settings\CreateMailRequestAero\Admin\Http\Requests\Settings\UpdateMailRequestAero\Admin\Http\Requests\Settings\CreateOrderReturnReasonGroupRequestAero\Admin\Http\Requests\Settings\UpdateOrderReturnReasonGroupRequestAero\Admin\Http\Requests\Settings\CreateOrderStatusGroupRequestAero\Admin\Http\Requests\Settings\UpdateOrderStatusGroupRequestAero\Admin\Http\Requests\Settings\CreatePaymentMethodRequestAero\Admin\Http\Requests\Settings\UpdatePaymentMethodRequestAero\Admin\Http\Requests\Settings\CreateProductTaxGroupRequestAero\Admin\Http\Requests\Settings\UpdateProductTaxGroupRequestAero\Admin\Http\Requests\Settings\CreateSettingDefinitionRequestAero\Admin\Http\Requests\Settings\UpdateSettingDefinitionRequestAero\Admin\Http\Requests\Settings\CreateShippingMethodRequestAero\Admin\Http\Requests\Settings\UpdateShippingMethodRequestAero\Admin\Http\Requests\Settings\CreateSubscriptionPlanRequestAero\Admin\Http\Requests\Settings\UpdateSubscriptionPlanRequestAero\Admin\Http\Requests\Settings\CreateTaxRateRequestAero\Admin\Http\Requests\Settings\UpdateTaxRateRequestAero\Admin\Http\Requests\Settings\CreateTaxRuleRequestAero\Admin\Http\Requests\Settings\UpdateTaxRuleRequestAero\Admin\Http\Requests\Settings\ManageSearchIndexRequestAero\Admin\Http\Requests\Settings\PreviewMailRequestAero\Admin\Http\Requests\Settings\StoreProductTypeRequest
Checkout
Listed below are all the checkout validation requests:
Aero\Checkout\Http\Requests\ValidateCartCustomerAero\Checkout\Http\Request\ValidateGuestConversionRequestAero\Checkout\Http\Request\ValidateOrderAddressAero\Checkout\Http\Request\ValidatePaymentMethodAero\Checkout\Http\Request\ValidateShippingMethod
Account Area
Listed below are all the account area validation requests:
Aero\AccountArea\Http\Requests\ValidateAccountDetailsAero\AccountArea\Http\Requests\ValidateAddressAero\AccountArea\Http\Requests\ValidateEmailAero\AccountArea\Http\Requests\ValidateLoginAero\AccountArea\Http\Requests\ValidatePasswordResetAero\AccountArea\Http\Requests\ValidatePasswordUpdateAero\AccountArea\Http\Requests\ValidateRegister
How can I extend an existing request?
The expects() method can be used to add custom validation rules (and messages) for your custom field (or to overwrite the existing rules/messages for an existing field):
// Adding a custom field
\Aero\Admin\Http\Requests\Catalog\CreateProductRequest::expects('acme', 'required|string|max:255', [
'acme.required' => 'The acme field is required.',
]);
// Making existing categories field required
\Aero\Admin\Http\Requests\Catalog\CreateProductRequest::expects('categories', 'required|array');
Parameters
| Parameter |
Type |
Description |
$field |
string |
The key of the field to validate. |
$rules |
string|array|\Closure |
The rules to use when validating. If callback is supplied, it will receive the request as the argument. |
$messages |
array|null |
The messages for the rules, key's are of the form {$field}.{$rule}. |
Pipelines
What are the available pipelines?
| Pipeline |
Description |
\Aero\Store\Pipelines\ContentForBody |
Builds content string to be injected into the body of all pages. |
\Aero\Store\Pipelines\ContentForHead |
Builds content string to be injected into the head of all pages. |
\Aero\Store\Pipelines\RobotsTxt |
Used to defined/generate a robots.txt file. |
\Aero\Store\Pipelines\CartItemBuilder |
Run whenever a cart item is added to the cart in order to build the item from the request data. |
\Aero\Cart\Pipelines\OrderItemBuilder |
Run whenever a cart item is transformed into an order item. |
\Aero\Subscription\Pipelines\SubscriptionOrderBuilder |
Run when a subscription is processed and requires a new order to be created. |
\Aero\Admin\Pipelines\ListingRulesContextBuilder |
Builds listing rule context for each rule type. |
\Aero\Admin\Pipelines\ListingRulesDataFormatter |
Formats listing rules for admin UI. |
\Aero\Admin\Pipelines\PreviewMailAction |
Builds a temporary mail action to be previewed. |
\Aero\Admin\Reports\Pipelines\BuyXDiscountTierReportQuery |
Builds the query for the buy x discount tier report. |
\Aero\Admin\Reports\Pipelines\DiscountCodesReportQuery |
Builds the query for the discount codes report. |
\Aero\Admin\Reports\Pipelines\OrderBreakdownReportQuery |
Builds the query for the order breakdown report. |
\Aero\Admin\Reports\Pipelines\OrderSurchargeReportQuery |
Builds the query for the order surcharge report. |
\Aero\Admin\Reports\Pipelines\ProductStockLevelReportQuery |
Builds the query for the product stock level report. |
\Aero\Admin\Reports\Pipelines\RefundReportQuery |
Builds the query for the refund report. |
\Aero\Admin\Reports\Pipelines\SalesReportQuery |
Builds the query for the sales report. |
\Aero\Admin\Reports\Pipelines\VoucherReportQuery |
Builds the query for the voucher report. |
Aero\Admin\Configuration\Groups\PaymentAndShippingConfigurationGroup |
Builds the payment and shipping configuration group. |
Aero\Admin\Configuration\Groups\OrderManagementConfigurationGroup |
Builds the order management configuration group. |
Aero\Admin\Configuration\Groups\LocalizationConfigurationGroup |
Builds the localization configuration group. |
Aero\Admin\Configuration\Groups\ProductManagementConfigurationGroup |
Builds the product management configuration group. |
Aero\Admin\Configuration\Groups\NotificationsConfigurationGroup |
Builds the notifications configuration group. |
Aero\Admin\Configuration\Groups\TaxConfigurationGroup |
Builds the tax configuration group. |
Aero\Admin\Configuration\Groups\SystemConfigurationGroup |
Builds the system configuration group. |
Aero\Admin\Configuration\Groups\UserManagementConfigurationGroup |
Builds the user management configuration group. |
Aero\Admin\Configuration\Groups\MaintenanceConfigurationGroup |
Builds the maintenance configuration group. |
Aero\DataPort\Commands\Pipelines\ImportBlockCSVPipeline |
Creates a block from CSV data. |
Aero\DataPort\Commands\Pipelines\ImportProductCSVPipeline |
Creates a product from CSV data. |
\Aero\Store\Pipelines\ListingsPageQuery |
Builds the query for the listings page. |
Aero\Search\Elastic\Pipelines\ProductAttributes |
Builds the attributes for the ES Product model |
Aero\Search\Elastic\Pipelines\ListingAttributes |
Builds the attributes for the ES Listing model |
Aero\Search\Elastic\Pipelines\ListingCategory |
Builds listing documents categories data. |
Aero\Search\Elastic\Pipelines\ListingCategoryFacet |
Builds listing documents category string facet data. |
Aero\Search\Elastic\Pipelines\ListingManufacturerFacet |
Builds listing documents manufacturer string facet data. |
Aero\Search\Elastic\Pipelines\ListingTagFacet |
Builds listing documents tag string facet data. |
Aero\Search\Elastic\Pipelines\Mapping |
Used to build the ES Mapping for search documents. |
How do I extend pipelines?
The payload data can be altered using the extend() method. This is typically done from within a Service Provider:
- If the code is unique to a particular store it could be placed in the
boot()method of theAppServiceProvider. - If it is to be included as part of a module, then it can be added to the setup method of the module's Service Provider.
For example, if a module needs to add an option to items to flag them as requiring gift wrap, the CartItemBuilder pipeline class should be extended in the module's ServiceProvider as shown below:
<?php
namespace Aerocargo\Acme;
use Aero\Cart\CartItemOption;
use Aero\Common\Providers\ModuleServiceProvider;
use Aero\Store\Pipelines\CartItemBuilder;
class ServiceProvider extends ModuleServiceProvider
{
public function setup()
{
CartItemBuilder::extend(function ($item) {
if (request()->has('gift_wrap')) {
$option = CartItemOption::create('Gift wrap');
$item->addOption($option);
}
});
}
}
Response Builders
What are the available response builders?
Storefront
Listed below are all the storefront response builders, the vast majority are view page responses or cart action responses:
Aero\Store\Http\Responses\AccountOverviewPageAero\Store\Http\Response\CartDiscountCodeApplyAero\Store\Http\Response\CartDiscountCodeRemoveAero\Store\Http\Response\CartEmptyAero\Store\Http\Response\CartItemAddAero\Store\Http\Response\CartItemUpdateAero\Store\Http\Response\CartPageAero\Store\Http\Response\Error404PageAero\Store\Http\Response\FormSubmitAero\Store\Http\Response\HomepageAero\Store\Http\Response\InformationPageAero\Store\Http\Response\ListingsJsonAero\Store\Http\Response\ListingsPageAero\Store\Http\Response\ProductPageAero\Store\Http\Response\SearchJsonAero\Store\Http\Response\SearchPage
Admin
Listed below are all the admin response builders, the vast majority are create/edit page responses or store/update responses:
General
Aero\Admin\Http\Responses\RedirectBuyableToEdit
Dashboard
Aero\Admin\Http\Responses\AdminDashboardPage
Catalog Management
Aero\Admin\Http\Responses\Catalog\AdminAttributeGroupCreatePageAero\Admin\Http\Responses\Catalog\AdminAttributeGroupEditPageAero\Admin\Http\Responses\Catalog\AdminAttributeGroupStoreAero\Admin\Http\Responses\Catalog\AdminAttributeGroupUpdateAero\Admin\Http\Responses\Catalog\AdminCategoryCreatePageAero\Admin\Http\Responses\Catalog\AdminCategoryEditPageAero\Admin\Http\Responses\Catalog\AdminCategoryStoreAero\Admin\Http\Responses\Catalog\AdminCategoryUpdateAero\Admin\Http\Responses\Catalog\AdminCollectionCreatePageAero\Admin\Http\Responses\Catalog\AdminCollectionEditPageAero\Admin\Http\Responses\Catalog\AdminCollectionStoreAero\Admin\Http\Responses\Catalog\AdminCollectionUpdateAero\Admin\Http\Responses\Catalog\AdminFetchVariantsForProductAero\Admin\Http\Responses\Catalog\AdminManufacturerCreatePageAero\Admin\Http\Responses\Catalog\AdminManufacturerEditPageAero\Admin\Http\Responses\Catalog\AdminManufacturerStoreAero\Admin\Http\Responses\Catalog\AdminManufacturerUpdateAero\Admin\Http\Responses\Catalog\AdminProductCreatePageAero\Admin\Http\Responses\Catalog\AdminProductEditPageAero\Admin\Http\Responses\Catalog\AdminProductStoreAero\Admin\Http\Responses\Catalog\AdminProductUpdateAero\Admin\Http\Responses\Catalog\AdminProductTypeCreatePageAero\Admin\Http\Responses\Catalog\AdminProductTypeEditPageAero\Admin\Http\Responses\Catalog\AdminProductTypeStoreAero\Admin\Http\Responses\Catalog\AdminProductTypeUpdateAero\Admin\Http\Responses\Catalog\AdminTagGroupsCreatePageAero\Admin\Http\Responses\Catalog\AdminTagGroupsEditPageAero\Admin\Http\Responses\Catalog\AdminTagGroupsStoreAero\Admin\Http\Responses\Catalog\AdminTagGroupsUpdate
Content Management
Aero\Admin\Http\Responses\Content\AdminCombinationCreatePageAero\Admin\Http\Responses\Content\AdminCombinationEditPageAero\Admin\Http\Responses\Content\AdminCombinationStoreAero\Admin\Http\Responses\Content\AdminCombinationUpdateAero\Admin\Http\Responses\Content\AdminPageCreatePageAero\Admin\Http\Responses\Content\AdminPageEditPageAero\Admin\Http\Responses\Content\AdminPageStoreAero\Admin\Http\Responses\Content\AdminPageUpdate
Customer Management
Aero\Admin\Http\Responses\Customers\AdminCustomerCreatePageAero\Admin\Http\Responses\Customers\AdminCustomerEditPageAero\Admin\Http\Responses\Customers\AdminCustomerStoreAero\Admin\Http\Responses\Customers\AdminCustomerUpdateAero\Admin\Http\Responses\Customers\AdminCustomerGroupCreatePageAero\Admin\Http\Responses\Customers\AdminCustomerGroupEditPageAero\Admin\Http\Responses\Customers\AdminCustomerGroupStoreAero\Admin\Http\Responses\Customers\AdminCustomerGroupUpdate
Discount Management
Aero\Admin\Http\Responses\Discounts\AdminDiscountCreatePageAero\Admin\Http\Responses\Discounts\AdminDiscountEditPageAero\Admin\Http\Responses\Discounts\AdminDiscountStoreAero\Admin\Http\Responses\Discounts\AdminDiscountUpdateAero\Admin\Http\Responses\Discounts\AdminVoucherCreatePageAero\Admin\Http\Responses\Discounts\AdminVoucherEditPageAero\Admin\Http\Responses\Discounts\AdminVoucherStoreAero\Admin\Http\Responses\Discounts\AdminVoucherUpdate
Order Management
Aero\Admin\Http\Responses\Orders\AdminOrderCreatePageAero\Admin\Http\Responses\Orders\AdminOrderCreateStoreAero\Admin\Http\Responses\Orders\AdminOrderViewPageAero\Admin\Http\Responses\Orders\AdminOrderEditPageAero\Admin\Http\Responses\Orders\AdminOrderUpdateAero\Admin\Http\Responses\Orders\AdminOrderUpdateBillingAddressAero\Admin\Http\Responses\Orders\AdminOrderUpdateCustomerAero\Admin\Http\Responses\Orders\AdminOrderUpdateDiscountAero\Admin\Http\Responses\Orders\AdminOrderUpdateShippingMethodAero\Admin\Http\Responses\Orders\AdminOrderUpdateShippingAddressAero\Admin\Http\Responses\Orders\AdminOrderUpdateFlagsAero\Admin\Http\Responses\Orders\AdminOrderFulfillmentCreatePageAero\Admin\Http\Responses\Orders\AdminOrderFulfillmentEditPageAero\Admin\Http\Responses\Orders\AdminOrderFulfillmentStoreAero\Admin\Http\Responses\Orders\AdminOrderFulfillmentUpdateAero\Admin\Http\Responses\Orders\AdminOrderFulfillmentCancelAero\Admin\Http\Responses\Orders\AdminOrderPaymentPageAero\Admin\Http\Responses\Orders\AdminOrderPaymentStoreAero\Admin\Http\Responses\Orders\AdminOrderReturnCreatePageAero\Admin\Http\Responses\Orders\AdminOrderReturnStoreAero\Admin\Http\Responses\Orders\AdminOrderShippingPageAero\Admin\Http\Responses\Orders\AdminOrderShippingStoreAero\Admin\Http\Responses\Orders\AdminOrderItemUpdateFlags
Two Factor Authentication
Aero\Admin\Http\Responses\TwoFactorAuthentication\FailedTwoFactorAuthenticationResponseAero\Admin\Http\Responses\TwoFactorAuthentication\PassedTwoFactorAuthenticationResponseAero\Admin\Http\Responses\TwoFactorAuthentication\RecoveryCodesGeneratedResponseAero\Admin\Http\Responses\TwoFactorAuthentication\TwoFactorConfirmedResponseAero\Admin\Http\Responses\TwoFactorAuthentication\TwoFactorDisabledResponseAero\Admin\Http\Responses\TwoFactorAuthentication\TwoFactorEnabledResponse
Configuration
Aero\Admin\Http\Responses\Configuration\AdminFulfillmentMethodCreatePageAero\Admin\Http\Responses\Configuration\AdminFulfillmentMethodEditPageAero\Admin\Http\Responses\Configuration\AdminFulfillmentMethodStoreAero\Admin\Http\Responses\Configuration\AdminFulfillmentMethodUpdateAero\Admin\Http\Responses\Configuration\AdminLocationCreatePageAero\Admin\Http\Responses\Configuration\AdminLocationEditPageAero\Admin\Http\Responses\Configuration\AdminLocationStoreAero\Admin\Http\Responses\Configuration\AdminLocationUpdateAero\Admin\Http\Responses\Configuration\AdminMailCreatePageAero\Admin\Http\Responses\Configuration\AdminMailEditPageAero\Admin\Http\Responses\Configuration\AdminMailStoreAero\Admin\Http\Responses\Configuration\AdminMailUpdateAero\Admin\Http\Responses\Configuration\AdminShippingMethodCreatePageAero\Admin\Http\Responses\Configuration\AdminShippingMethodEditPageAero\Admin\Http\Responses\Configuration\AdminShippingMethodStoreAero\Admin\Http\Responses\Configuration\AdminShippingMethodUpdateAero\Admin\Http\Responses\Configuration\AdminUserCreatePageAero\Admin\Http\Responses\Configuration\AdminUserEditPageAero\Admin\Http\Responses\Configuration\AdminUserStoreAero\Admin\Http\Responses\Configuration\AdminUserUpdate
Checkout
Listed below are all the checkout response builders:
Aero\Checkout\Http\Responses\CheckoutBillingAddressSetAero\Checkout\Http\Responses\CheckoutCustomerLoginAero\Checkout\Http\Responses\CheckoutCustomerPageAero\Checkout\Http\Responses\CheckoutCustomerSetAero\Checkout\Http\Responses\CheckoutDiscountCodeApplyAero\Checkout\Http\Responses\CheckoutDiscountCodeRemoveAero\Checkout\Http\Responses\CheckoutExpressCompleteAero\Checkout\Http\Responses\CheckoutExpressPageAero\Checkout\Http\Responses\CheckoutGuestConvertAero\Checkout\Http\Responses\CheckoutIframeFailAero\Checkout\Http\Responses\CheckoutIframeSuccessAero\Checkout\Http\Responses\CheckoutOrderConfirmationPageAero\Checkout\Http\Responses\CheckoutPaymentCompleteAero\Checkout\Http\Responses\CheckoutPaymentPageAero\Checkout\Http\Responses\CheckoutPaymentSetAero\Checkout\Http\Responses\CheckoutRedirectToStepAero\Checkout\Http\Responses\CheckoutShippingAddressSetAero\Checkout\Http\Responses\CheckoutShippingPageAero\Checkout\Http\Responses\CheckoutShippingSetAero\Checkout\Http\Responses\CheckoutSuccess
Account Area
Listed below are all the account area response builders:
Aero\AccountArea\Http\Responses\AccountAddressDeleteAero\AccountArea\Http\Responses\AccountAddressNewPageAero\AccountArea\Http\Responses\AccountAddressNewSetAero\AccountArea\Http\Responses\AccountAddressEditPageAero\AccountArea\Http\Responses\AccountAddressEditSetAero\AccountArea\Http\Responses\AddressesPageAero\AccountArea\Http\Responses\AddressMakeDefaultSetAero\AccountArea\Http\Responses\AccountDetailsPageAero\AccountArea\Http\Responses\AccountDetailsSetAero\AccountArea\Http\Responses\AccountInvoicePageAero\AccountArea\Http\Responses\AccountLoginPageAero\AccountArea\Http\Responses\AccountLoginSetAero\AccountArea\Http\Responses\AccountLogoutSetAero\AccountArea\Http\Responses\AccountOrdersPageAero\AccountArea\Http\Responses\AccountOrderViewPageAero\AccountArea\Http\Responses\AccountOverviewPageAero\AccountArea\Http\Responses\AccountPasswordForgotPageAero\AccountArea\Http\Responses\AccountPasswordForgotSetAero\AccountArea\Http\Responses\AccountPasswordResetPageAero\AccountArea\Http\Responses\AccountPasswordResetSetAero\AccountArea\Http\Responses\AccountRegisterPageAero\AccountArea\Http\Responses\AccountRegisterSetAero\AccountArea\Http\Responses\AccountSubscriptionCancelSetAero\AccountArea\Http\Responses\AccountSubscriptionSkipSetAero\AccountArea\Http\Responses\AccountSubscriptionsPageAero\AccountArea\Http\Responses\AccountSubscriptionsViewPageAero\AccountArea\Http\Responses\AccountSubscriptionTogglePauseSet
How do I pass data to a response?
The most common task performed when extending responses, is setting additional data. Typically, for HTML responses that render from a view, this involves sending data to the view to be used as a variable. If the response returns JSON, it may be adding additional key/value pairs.
For example, if you needed to obtain customer reviews for a given product and output them on the product page, you could do the following, which passes a product to a 3rd party reviews API and then adds the reviews it returns to the response data, which is then passed to the product.twig view file ready to be loop around and outputted:
\Aero\Store\Http\Responses\ProductPage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
$reviews = ReviewsAPI::forProduct($page->product);
$page->setData('reviews', $reviews);
return $next($page);
});
Another example is getting the latest 5 blog posts from a blog module and sending them to the homepage to be displayed:
\Aero\Store\Http\Responses\Homepage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
$posts = \Acme\BlogPosts::latest()->limit(5)->get();
$page->setData('posts', $posts);
return $next($page);
});
You can obtain the existing data set against the response builder using the getData() method.
You can remove existing data set against the response builder using the removeData() method.
How do I redirect a response?
Sometimes you may wish to redirect the user to another location, either to an external site or within the store. To do so, pass the URL, route(), or an Illuminate\Http\RedirectResponse instance to the setRedirect() method.
For example, if you stored the age of customers (computed from their provided date of birth), and needed to prevent access to those under the age of 18:
\Aero\Store\Http\Responses\ProductPage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
if ($page->request->customer()->age < 18) {
$page->setRedirect('/denied');
}
return $next($page);
});
As extension code is evaluated in the order it's added to the response builder, code that runs after this step may override the redirect.
To force a redirect and prevent execution of the code that follows in the pipeline, you should return an instance of the redirect() helper:
\Aero\Store\Http\Responses\ProductPage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
if (! $page->product->canBeViewedByIp($page->request->ip())) {
return redirect('/denied');
}
return $next($page);
});
How do I set the response status code?
There may be situations where the HTTP response status needs to be altered. By default, the returned status is 200, however, this can be changed by passing the new status code to the setStatus() method:
\Aero\Store\Http\Responses\ProductPage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
$page->setStatus(403);
return $next($page);
});
How do I set response headers?
When extending the response builder, you can set HTTP headers to be sent with the response:
\Aero\Store\Http\Responses\ProductPage::extend(function ($page) {
$page->setHeader('foo', 'bar');
});
How do I attach middleware to a response builder?
Since Aero does not expose the underlying routes and controllers, middleware can be attached directly to the response builder. This allows for code to be executed before the main pipeline is run.
For example, to restrict all products from being accessible to guest visitors, you could register the auth middleware to the ProductPage response:
\Aero\Store\Http\Responses\ProductPage::middleware('auth');
When assigning middleware, you can also pass the fully qualified class name:
\Aero\Store\Http\Responses\ProductPage::middleware(\App\Http\Middleware\CheckAge::class);
Alternatively, you can provide a Closure.
For example, middleware could be added to the homepage to set a tracking cookie from the referrer:
\Aero\Store\Http\Responses\Homepage::middleware(function (\Illuminate\Http\Request $request, \Closure $next) {
return tap($next($request), function ($response) use ($request) {
$response->cookie('referer', $request->header('Referer'));
});
});
Refer to the Laravel documentation for more information on middleware.
How do I change the response view?
For responses that return HTML, a Twig view file is used. Whilst these are originally defined, the view can be changed. For example, to change the product page view based on product data:
\Aero\Store\Http\Responses\ProductPage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
if ($view = $page->product->additional('view')) {
$page->setView($view);
}
return $next($page);
});
Setting the view to null will result in a JSON response.
You can get the current view for a response using getView().
Services
What is the tax accountant service?
The Tax Account is the service responsible for determining the tax multiplier that should be applied to a product price.
It uses the store's tax configuration together with the current customer's tax information and location to determine which tax rules and rates apply. The service can then use those multipliers to convert prices between tax-exclusive and tax-inclusive values.
Converting prices
Ex => Inc
The priceInc method can be used to convert an ex price to an inc price, we use it when handling prices for products:
app('aero.accountant')->priceInc($value, $this->product_tax_group_id);
Inc => Ex
The priceEx method can be used to convert an inc price to an ex price, we use it when handling prices for products:
app('aero.accountant')->priceEx($value, $this->product_tax_group_id);
Resolvers
Tax Group Resolver
The Tax Account uses a tax group resolver to resolve a customer's tax group id.
A resolver is set by the Aero\Store\Http\Middleware\SetTaxResolver middleware:
$this->accountant->setTaxGroupResolver(static function (?\Aero\Account\Models\Customer $customer) {
if ($customer && ($group = $customer->getAttribute('customer_tax_group_id'))) {
return $group;
}
if ($customer && $customer->customer_group_id && ($group = $customer->group->getAttribute('customer_tax_group_id'))) {
return $group;
}
return null;
});
If no customer tax group id is resolved, the store's default will be used.
Country Resolver
The Tax Account uses a country resolver to resolve the country it should use.
A resolver is set by the Aero\Store\Http\Middleware\SetTaxResolver middleware:
$this->accountant->setCountryResolver(static function (?\Aero\Account\Models\Customer $customer) {
if ($cartLocale = \Aero\Cart\Facades\Cart::instance(PaymentDriver::MOTO)->locale()) {
return $cartLocale->countryCode;
}
return null;
});
If no country code is resolved, the store's default will be used.
Zone Resolver
The Tax Account uses a country resolver to resolve the country it should use.
A resolver is set by the Aero\Store\Http\Middleware\SetTaxResolver middleware:
$this->accountant->setZoneResolver(static function (?\Aero\Account\Models\Customer $customer) {
if ($cartLocale = \Aero\Cart\Facades\Cart::instance(PaymentDriver::MOTO)->locale()) {
return $cartLocale->zoneId;
}
return null;
});
If no zone id is resolved, then no zone id will be used.
Postcode Resolver
The Tax Account uses a country resolver to resolve the country it should use.
A resolver is set by the Aero\Store\Http\Middleware\SetTaxResolver middleware:
$this->accountant->setPostcodeResolver(static function (?\Aero\Account\Models\Customer $customer) {
if ($cartLocale = \Aero\Cart\Facades\Cart::instance(PaymentDriver::MOTO)->locale()) {
return $cartLocale->postcode;
}
return null;
});
If no postcode is resolved, then no postcode will be used.
What is the combination serializer service?
The combination serializer service is used to serialize and deserialize models.
Serializing
This is used to take a collection of models and convert them into a string that can be used to find a corresponding combination.
Let's say you have a category called mens, a manufacturer called acme and a blue tag in the group color. Then if you visit /mens/acme/blue on the storefront it will load any products in the category mens that have the manufacturer acme and are tagged with blue.
Perhaps you might rather that it 404s unless a combination for those models exists (as otherwise there may very likely be no products that matches the criteria). This can be done by serializing the slugs and considering them invalid if they don't correspond to an existing combination model:
\Aero\Store\Routing\Slugs::setValidator(function (\Illuminate\Database\Eloquent\Collection $slugs, $resolver) {
if ($resolver !== 'listings') return true;
try {
$serialized = \Aero\Common\Services\CombinationSerializer::serialize(
$slugs->map(function (\Aero\Store\Models\Slug $slug) {
return $slug->model;
})
);
return \Aero\Catalog\Models\Combination::where('serialized', $serialized)->exists();
} catch (\Exception $e) {
return false;
}
});
Deserializing
This is used to take a combination model and find all of its' component models (collections, categories, manufacturers & tags).
For example, you might want to resolve the category ids for the listings page from the combination:
\Aero\Store\Http\Responses\ListingsPage::extend(function (\Aero\Store\Http\Responses\ListingsPage $page, \Closure $next) {
$categoryIds = \Aero\Common\Services\CombinationSerializer::deserialize($page->getData('combination'))
->filter(function (\Illuminate\Database\Eloquent\Model $model) {
return $model instanceof \Aero\Catalog\Models\Category;
})
->pluck('id');
// Do stuff...
return $next($page);
});
What is the login blocker service?
The login blocker service can be used to block customers from logging in based on criteria.
For example, you might want to blacklist certain IPs.
First, define a setting to store blacklisted IPs:
\Aero\Common\Facades\Settings::group('customers', static function (\Aero\Common\Settings\SettingGroup $group) {
$group->array('blocked_ip_addresses');
});
Then add a login blocker to check if the customer IP is blocked:
\Aero\Common\Facades\LoginBlocker::add(function (\Aero\Account\Models\Customer $customer) {
if (in_array(request()->ip(), setting('customers.blocked_ip_addresses')) {
return __('Blocked due to suspicious activity');
}
});
Returning a string means that they customer will be blocked from logging in and that string will be displayed.
What is the volume service?
The volume service is used to normalize volumes into the store's base unit (cm^3 by default) as well as convert between different units.
Units
By default the volume service has the following units:
mm^3cm^3m^3
Adding a Unit
Use addUnit() to add a unit, for example we can add millilitres & litres:
\Aero\Common\Facades\Volume::addUnit('ml', 'ml');
\Aero\Common\Facades\Volume::addUnit('l', 'L')
->setNormalizer(function ($value) {
return $value * 1000;
});
setNormalizer defines how to get from that unit to the base unit, which is cm^3.
Removing a Unit
\Aero\Common\Facades\Volume::removeUnit('m^3');
Converting between Units
You can use convert() to convert between any two units, or normalize() to convert into the store's base unit.
\Aero\Common\Facades\Volume::convert(1000, 'mm^3', 'cm^3');
\Aero\Common\Facades\Volume::normalize('mm^3', 1000);
Setting a base Unit
\Aero\Common\Facades\Volume::setBaseUnit('ml');
When you change base unit, database values will still remain in cm^3. But volumes will be displayed in the new unit on screens such as the fulfillment create page.
What is the weight service
The weight service is used to normalize weights into the store's base unit (g by default) as well as convert between different units.
Units
By default the weight service has the following units:
gozlbkg
Adding a Unit
Use addUnit() to add a unit, for example we can add milligrams:
\Aero\Common\Facades\Weight::addUnit('mg', 'mg')
->setNormalizer(function ($value) {
return $value / 1000;
});
setNormalizer defines how to get from that unit to the base unit, which is g.
Removing a Unit
\Aero\Common\Facades\Weight::removeUnit('kg');
Converting between Units
You can use convert() to convert between any two units, or normalize() to convert into the store's base unit.
\Aero\Common\Facades\Weight::convert(1000, 'oz', 'g');
\Aero\Common\Facades\Weight::normalize('oz', 1000);
Setting a base Unit
\Aero\Common\Facades\Weight::setBaseUnit('oz');
When you change base unit, database values will still remain in grams. But weights will be displayed in the new unit on screens such as the fulfillment create page.
Commands
What are the available commands?
php artisan make:module
This command scaffolds a module for you (you need to provide a valid name for the module such as aerocargo/my-module). This involves setting up composer and publishing some default module stubs.
php artisan aero:configure
This command walks you through configuring your store. This includes things such as setting the store's name, database connection, and Elasticsearch connection.
php artisan aero:install
This command runs you through the installation process for your store. This includes completing migrations, configuring Elasticsearch, linking storage, seeding data, and clearing the applications cache.
php artisan aero:update
This command updates all aerocommerce modules, can optionally run as a dry run (asked upon running command).
php artisan aero:link
This command calls the patch command, links theme/module assets, clears the Twig views cache, and clears the Laravel views cache.
php artisan module:install
This command will install a specific module after you have composer required the module. This command seeds any data for the module, optionally clears the application cache, and links the module assets. You should note that this command doesn’t have to be used and is automatically run when composer requiring a module.
php artisan theme:install
This command will install a specific theme.
php artisan aero:patch
This command patches your store's database. This command is run automatically when updating and ensures that your database is kept up to date with the latest updates.
php artisan aero:search:install
This command sets up the necessary environment for your search driver. By default when using Elasticsearch this command will create the required indexes.
php artisan aero:search:rebuild
This command resets up and reindexes your search by running the search install and reindex commands.
php artisan aero:search:reindex
This command will reindex your database data into your searches index. By default when using Elasticsearch this command will clear the index and then index your database data.
php artisan aero:seed:emails
This command will seed some default email templates to your mail notifications.
php artisan aero:settings:clear
This command will clear the settings cache file.
php artisan aero:sitemap:cms
This command will generate the pages-sitemap.xml sitemap file in your public storage directory. This sitemap covers any pages you create through the admin.
php artisan aero:sitemap:combinations
This command will generate the combinations-sitemap.xml file in your public storage directory. This sitemap covers any combinations you create through the admin.
php artisan aero:sitemap:generate
This command will generate a complete sitemap for your store. This generates a sitemap.xml file in your public storage directory that references individual sitemap files for products, combinations, and pages.
php artisan aero:sitemap:products
This command will generate the products-sitemap.xml sitemap file in your public storage directory. This sitemap covers any products you create through the admin.
php artisan aero:subscriptions:alert-upcoming
This command will look for upcoming subscriptions and emit the Aero\Subscription\Events\SubscriptionUpcoming event for them.
php artisan aero:subscriptions:check-cards
This command will look for expired cards on subscriptions and then cancel the subscription and emit the Aero\Subscription\Events\SubscriptionCardExpired event for them.
php artisan aero:subscriptions:process
This command will process any subscriptions that need processing.
Tutorials
How do I add a custom price to a product with a module?
In this mini tutorial, we’ll add checkboxes to a product page that allow customers to select additional charges. The product page will update the additional price dynamically as options are selected, and the total will continue to update when the product price changes, for example when a different variant is selected.
This tutorial assumes you already have a module set up, or are happy working directly from your app service provider using the boot method. See here for information on setting up a module.
1. Add the extra prices
We’ll start by defining the available extra prices in our module service provider. For this example, we’ll use an array as the source of truth rather than database records:
protected $prices = [
[
'id' => 1,
'name' => 'Pay £1 more',
'price' => [
'inc' => 100,
'ex' => 83.33,
],
],
[
'id' => 2,
'name' => 'Pay £5 more',
'price' => [
'inc' => 500,
'ex' => 416.66,
],
],
[
'id' => 3,
'name' => 'Pay £10 more',
'price' => [
'inc' => 1000,
'ex' => 833.33,
],
],
];
2. Add the prices data to the products page
Next, we’ll make the extra prices available to the product page and add the JavaScript that will handle the checkboxes.
First, create a javascript.twig view in your module's resources directory. We’ll populate this later.
We can then extend Aero\Store\Http\Responses\ProductPage to add the $prices data to the product page:
\Aero\Store\Http\Responses\ProductPage::extend(function (\Aero\Store\Http\Responses\ProductPage $page, \Closure $next) {
$page->setData('extra_prices', $this->prices);
\Aero\Store\Pipelines\ContentForBody::extend(function (string $content, \Closure $next) {
$content .= view('acme::javascript');
return $next($content);
});
return $next($page);
});
3. Add the extra price checkboxes
In product.twig, we can display the product's total price and the additional price selected by the customer:
Total Price
<p v-text="total_price.inc"></p>
Total Extra Price
<p v-text="additional_prices['extra-prices'].inc" v-if="additional_prices['extra-prices']"></p>
{% for extra in extra_prices %}
<div>
<input type="checkbox" id="extraPrice{{ extra.id }}" value="{{ extra.id }}" data-extra-price-inc="{{ extra.price.inc }}" data-extra-price-ex="{{ extra.price.ex }}">
<label for="extraPrice{{ extra.id }}"> {{ extra.name }}</label>
</div>
{% endfor %}
4. Update the additional price with JavaScript
Now we can add the code to javascript.twig
There are two things we need to handle:
- When a checkbox changes, calculate the total of all selected extras and pass it to Aero using the
product.set-additional-priceevent. - When the product is added to the cart, include the IDs of the selected extras in the request.
We’ll initialise the additional price when product.loaded fires as well. This means the calculation is also correct if any of the checkboxes are selected by default:
<script>
window.AeroEvents.on('product.loaded', function () {
var extraPriceElements = document.querySelectorAll('input[type="checkbox"][data-extra-price-inc]');
for (var i = 0; i < extraPriceElements.length; i++) {
extraPriceElements[i].addEventListener('input', updateAndSetAdditionalPrices);
}
function updateAndSetAdditionalPrices() {
var price = { key: 'extra-prices', inc: 0, ex: 0 };
var extraPriceElements = document.querySelectorAll('input[type=checkbox]:checked[data-extra-price-inc]');
for (var i = 0; i < extraPriceElements.length; i++) {
price.inc += parseInt(extraPriceElements[i].dataset.extraPriceInc);
price.ex += parseInt(extraPriceElements[i].dataset.extraPriceEx);
}
window.Aero.runEvent('product.set-additional-price', price);
}
updateAndSetAdditionalPrices();
});
window.AeroEvents.on('product.add-to-cart', function (data) {
var extras = [];
var extraPriceElements = document.querySelectorAll('input[type=checkbox]:checked[data-extra-price-inc]');
for (var i = 0; i < extraPriceElements.length; i++) {
extras.push(extraPriceElements[i].value);
}
data.extras = extras;
return data;
});
</script>
5. Add the selected extras to the cart item
We can extend Aero\Store\Pipelines\CartItemBuilder and read the extras array from the request. Each ID is matched against the $prices array, with invalid IDs filtered out before creating the cart item options.
Each valid extra becomes an Aero\Cart\CartItemOption with its corresponding inclusive price.
\Aero\Store\Pipelines\CartItemBuilder::extend(function (\Aero\Cart\CartItem $item) {
collect(request()->input('extras', []))
->map(function ($extra) {
return collect($this->prices)->firstWhere('id', $extra);
})
->filter()
->each(function ($extra) use ($item) {
$option = \Aero\Cart\CartItemOption::create($extra['name']);
$option->setPriceInc($extra['price']['inc']);
$item->addOption($option);
});
});
Complete Service Provider
<?php
namespace Aerocargo\Acme;
use Aero\Cart\CartItem;
use Aero\Cart\CartItemOption;
use Aero\Common\Providers\ModuleServiceProvider;
use Aero\Store\Http\Responses\ProductPage;
use Aero\Store\Pipelines\CartItemBuilder;
use Aero\Store\Pipelines\ContentForBody;
class ServiceProvider extends ModuleServiceProvider
{
protected $prices = [
[
'id' => 1,
'name' => 'Pay £1 more',
'price' => [
'inc' => 100,
'ex' => 83.33,
],
],
[
'id' => 2,
'name' => 'Pay £5 more',
'price' => [
'inc' => 500,
'ex' => 416.66,
],
],
[
'id' => 3,
'name' => 'Pay £10 more',
'price' => [
'inc' => 1000,
'ex' => 833.33,
],
],
];
public function setup()
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'acme');
ProductPage::extend(function (ProductPage $page) {
$page->setData('extra_prices', $this->prices);
ContentForBody::extend(function (&$content) {
$content .= view('acme::javascript');
});
});
CartItemBuilder::extend(function (CartItem $item) {
collect(request()->input('extras', []))
->map(function ($extra) {
return collect($this->prices)->firstWhere('id', $extra);
})
->filter()
->each(function ($extra) use ($item) {
$option = CartItemOption::create($extra['name']);
$option->setPriceInc($extra['price']['inc']);
$item->addOption($option);
});
});
}
}