Upload
meet-magento-spain
View
1.644
Download
7
Tags:
Embed Size (px)
DESCRIPTION
This talk covers a special use case. On stores with a small number of products it can make sense to completely replace the usual Magento front end and build a single page shop. This page contains the product presentation and enables the customer to check out easily. No catalog browsing functionality is present, since the goal is to get the customer from product presentation to checkout as quickly and easily as possible. The front end communicates with Magento via the REST API to fetch product information, create the customers and processes the orders. Building the customer facing page with a framework like AngularJS makes the front end work fun and easy. On the backend, the Magento REST API needs to be extended in order to provide all required functionality. Moving more business logic to the client side enables the Magento store to scale with less resources. This talk will cover an overview over the architecture and the challenges to overcome when building a one page store.
Citation preview
Single PageShops
With MagentoAnd AngularJS
Who am I?Vinai
How did I get here?
Freelance again!
I want to write a book......about Magento
(one trick pony)
Iʹll Self Publish!...on Magento
Work, Lots!Fun StuffCodingMoney
Unfun StuffSettingsThemingEmail TemplatesTerms & ConditionsSupport
MORE FUN
WoW
MuchDifferent
So faster
News Learnin
VeryAngular
Such JS
So Modern
WoW
JavaScript MVC Toolkit
DI and Testability are at itsvery core
Clean separation of MVClayers
Many pre‑made Modules
No jQuery or Prototype!(okay, it has jQuery Light)
Web‑App
AngularJSFrontend
<= REST API => MagentoCustomersProductsOrdersPaymentsDownloads
Admin Interface
Planning
Reduce to the max!
Starting outMagento CE 1.8.1.0angular‑seed
Magento REST APIBasics
REST API!==
SOAP APIs
Mage_Api2
Resources
Products,ProductCategories,ProductImages,ProductWebsites
Stock Items
Customers,CustomerAddresses
Orders,
Order Items,Order
Addresses,Order
Comments
Resource AttributesYou know the drill...
Products have Names, ... Customers have Groups, ...
Resource Routes/api/rest/products/category/10/store/2
Route Action TypesCollection
/api/rest/products/category/10/store/2
Entity/api/rest/products/16
OperationsMapping of HTTP verbs
GET => retrievePOST => createPUT => updateDELETE => delete
Roles
Admin
Customer
Guest
What weʹve gotRoles Resources
Attributes
Routes
Action Types
OperatonTypes
That all?
ACL
Each role can be allowed or denied potential access to eachresource by operation type via api2.xml.
E.g. guests may retrieve products, but not create them.
Under System > Web Services > REST ‑ Roles each potential rolepermission has to be assigned, too.
Resource Attributes ACLSame as roles... defined in XML, but ACL also has to be
assigned in the DB through the backend.
System > Web Services > REST ‑ Attributes
Not so elegant transition from theory to real stuff =>
Customizethe REST API
Customer AuthenticationOAuth
Session Authentication!REST API requests always run in admin store scope.$_SERVER['MAGE_RUN_CODE'] is not evaluated.
Api2 Session Auth Adapter1. If frontend cookie exists2. Set current store to frontend3. Start frontend session4. Check if customer is logged in
Which store?1. Evaluate store cookie2. If not found, use the defaultwebsites default store view
3. Hope the customer belongs tothe website
CodeVinaiKopp_Api2SessionAuthAdapter
VinaiKopp_Api2SessionLogin
More REST RelatedExtensions
VinaiKopp_Api2CreateAccountVinaiKopp_Api2DirectoryVinaiKopp_Api2SessionCustomerAddressVinaiKopp_Api2ForgotPasswordVinaiKopp_Api2DownloadsGrokking_Api2Checkout
(coming to github as time allows ‑ pls ask if you need sooner)
The Frontend
7thingsI digʹbout
1. Modules
angular.module('magentoApp', []);
angular.module('magentoApp', ['ngRoute']);
Look Ma, Module Dependencies!
Modules provide things
angular.module('magentoApp', ['ngRoute']) .factory('Countries', function() { return { code: 'ES', name: 'Espania' }; });
Things modules provideServicesControllersDirectivesFilters
and more...
2. Dependency InjectionIf a module needs a thing...
...just add it to thearguments
.controller('RegistrationCtrl', function($scope, Countries) {
$scope.countries = Countries;
})
3. Mangling Protection
JavaScript CompressionI HAZ TEH MINIFICATSION! (meow)
Variable names made shorter...
KILLS the DI!
Mangling Protection
.controller('RegistrationCtrl', ['Countries', function($scope, Countries) {
$scope.countries = Countries;
}])
4. Promises
Asynchronous ThingsXHR Requests and setTimeout Callbacks
Callback Try & Catch
Countries.fetch(). then(verifyAddress). then(createAddress). catch(displayAlert);
Can be combined!
$q.all(Countries.fetch(), Regions.fetch()). then(verifyAddress). then(createAddress). catch(displayAlert);
5. REST Resources
Inject $resource...
.factory('ForgotPassword', ['$resource', function($resource) { return $resource('/api/rest/customer/forgotpassword/:email'); });
...and use var result = ForgotPassword.get({ email: email });
Custom actions!
.factory('ForgotPassword', ['$resource', function($resource) { var resource = $resource('/api/rest/customer/forgotpassword/:email', {}, { validate: {method: 'GET', isArray: true}, reset: {method: 'PUT', isArray: false} });});
Fluid code :) var result = ForgotPassword.verify({ email: email, token: token });
6. Model Data Binding
[ ]
<p>{{ example }}</p> <input type="text" ng-bind="example">
Show Example
7. Testability it('should call calcRowTotal() when addItem is called with a new item', function () { expect(cart.items.length).toBe(0); cart.addItem(mock_product); expect(mock_item.calcRowTotal).toHaveBeenCalled(); });
Would I do it again?
Yeaaah!
Complicationsaka ʺOpportunities for Growthʺ
Scope Nestingcan be tricky
Frontend ArchitectureBuild a mini‑framework
Session State ManagementSplash MessagesConsistent error handling
Bad Crunch‑TimeDescisions
Last Friday I was running out of time
so I decided to continue without TDD
A lesson learned...again
I need more time to test manually then to write the tests.
Dankeschön!
@VinaiKopp on
Api2 Extensions on GitHub