Magento 1 Tutorial

Ref: http://devdocs.magento.com/guides/m1x/magefordev/mage-for-dev-2.html

ROUTES:
http://magento19.test/complexworld/index/showallblogposts XX
http://magento19.test/weblog/index/showallblogposts

CONTROLLER IN /home/teddy/Documents/works/magento19/app/code/local/Magentotutorial/Complexworld/controllers/IndexController.php XX
/home/teddy/Documents/works/magento19/app/code/local/Magentotutorial/Weblog/controllers/IndexController.php

MODEL IN
/home/teddy/Documents/works/magento19/app/code/local/Magentotutorial/Weblog/Model/Blogpost.php

Symfony 4 Tutorial

From this:

CREATE SYMFONY 4 PROJECT
(ref: https://symfony.com/doc/current/setup.html –> DONT USE THE INSTRUCTION ‘symfony/website-skeleton’. USE ‘symfony/skeleton’ FROM https://knpuniversity.com/screencast/symfony/setup#play INSTEAD)
1. CREATE A NEW DIR ‘symfony4’ IN Documents/works/ DIR
2. GO INTO IT AND USE ‘composer’ TO CREATE THE PROJECT SKELETON:

TEST IT VIA INTERNAL PHP SERVER:

OPEN VIA BROWSER: http://127.0.0.1:8000/ –> WORKS

CREATE A VIRTUALHOST
1. CREATE A NEW conf FILE

HERE IS THE CONTENT:

2. Enable the site

3. Register the site in /etc/hosts

HERE IS THE CONTENT:

RESTART THE APACHE2 SERVER: sudo systemctl restart apache2
TEST IT VIA BROWSER: http://symfony4test.test/ –> WORKS

ROUTE AND CONTROLLER (ref: https://knpuniversity.com/screencast/symfony/route-controller#play)
Modify /config/routes.yaml FILE TO UNCOMMENT THE CONTENT AND CHANGE THE CONTROLLER AND THE ACTION:

CREATE THE CONTROLLER ‘ArticleController’  FILE AND CLASS. ALSO CREATE ‘homepage’ FUNCTION IN /src/Controller/ArticleController.php:

REFRESH THE BROWSER: http://symfony4test.test/
IT’D SHOW ‘Hello, This is my first page!’ TEXT!

USE ANNOTATION ROUTE (PREFERRED) INSTEAD OF MODIFYING /config/routes.yaml
USE COMPOSER TO INSTALL IT ‘composer require annotations’

BECAUSE WE DONT NEED routes.yaml, COMMENT THE CONTENT BACK (IN /config/routes.yaml):

MODIFY AGAIN /src/Controller/ArticleController.php AND ADD THE ANNOTATION

REFRESH THE BROWSER: http://symfony4test.test/
IT’D SHOW ‘Hello, This is my first page with annotations!’ TEXT!

FANCY WILDCARD ANNOTATION ROUTE
FOR EXAMPLE ADD THIS NEW ROUTE IN /src/Controller/ArticleController.php:

WE SHOULD OPEN IT ON BROWSER LIKE THIS: http://symfony4test.test/news/why-asteroids-taste-like-bacon
BUT I GOT ‘Not found’ ERROR.
OK. I NEED TO RUN ‘composer require apache-pack’

REFRESH BROWSER! –> STILL NOT WORKING
I NEED TO CREATE .htaccess FILE in /public/ DIR (ref: https://knpuniversity.com/screencast/symfony/route-controller#play
AND THE .htaccess CONTENT GOT FROM https://raw.githubusercontent.com/symfony/recipes-contrib/master/symfony/apache-pack/1.0/public/.htaccess):
/public/.htaccess

REFRESH BROWSER: http://symfony4test.test/news/why-asteroids-taste-like-bacon –> WORKS
IT’D PRINT ‘Future page to show one space article!’

USE ANNOTATION WITH PARAMETER
MODIFY /src/Controller/ArticleController.php:

REFRESH BROWSER: http://symfony4test.test/pages/test-page –> WORKS
IT’D PRINT ‘Here is the page “test-page” content!’

Alan Storm Magento 2 Tutorial

REF: http://alanstorm.com/category/magento-2/

SETTING VirtualHost
REF:https://medium.com/@JohnFoderaro/how-to-set-up-apache-in-macos-sierra-10-12- bca5a5dfffba
MODIFY /private/etc/apache2/extra/httpd-vhosts.conf:

<VirtualHost *:80>
ServerName magentoce215.lcoal
ServerAlias www.magentoce215.local
DocumentRoot “/Library/WebServer/Documents/Projects/magentoce215”
DirectoryIndex index.php
<Directory “/Library/WebServer/Documents/Projects/magentoce215”>
AllowOverride All
Allow from All
Require all granted
</Directory>

ErrorLog “/private/var/log/apache2/magentoce215_error.log”
CustomLog “/private/var/log/apache2/magentoce215_access.log” common
</VirtualHost>

MODIFY /etc/hosts:

127.0.0.1 magentoce215.local

RESTART APACHE: sudo apachectl restart

OPEN http://magentoce215.local/

INSTALL PESTLE (https://github.com/astorm/pestle)
Satrias-MacBook-Pro:~ teddy$ curl -LO http://pestle.pulsestorm.net/pestle.phar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3990k 100 3990k 0 0 578k 0 0:00:06 0:00:06 –:–:– 860k
Satrias-MacBook-Pro:~ teddy$ php pestle.phar list-commands

GO TO THE M2 ROOT PROJECT (/Library/WebServer/Documents/Projects/magentoce215/)
Satrias-MacBook-Pro:~ teddy$ cd /Library/WebServer/Documents/Projects/magentoce215/

https://alanstorm.com/magento_2_javascript_init_scripts/
GO TO ‘app/code’ DIR: –> NO NEED. JUST PESTLE.PHAR IN MAGENTO ROOT IS OKAY
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/

THEN INSTALL PESTLE:
Satrias-MacBook-Pro:code teddy$ curl -LO http://pestle.pulsestorm.net/pestle.phar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3990k 100 3990k 0 0 860k 0 0:00:04 0:00:04 –:–:– 978k

THEN RUN ‘php pestle.phar generate_module Pulsestorm JavascriptInitTutorial 0.0.1’
I HAVE TO USE ‘php’ HERE BECAUSE IF NOT I’D GET AN ERROR MESSAGE ‘-bash: pestle.phar: command not found’ REF:https://github.com/astorm/pestle/issues/120

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm JavascriptInitTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/registration.php

HERE ARE THE GENERATED FILES:
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/registration.php:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
‘Pulsestorm_JavascriptInitTutorial’,
__DIR__
);

/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/module.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:Module/etc/module.xsd”>
<module name=”Pulsestorm_JavascriptInitTutorial” setup_version=”0.0.1″/>
</config>

THEN
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_JavascriptInitTutorial frontend pulsestorm_javascriptinittutorial
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/Controller/Index/Index.php

HERE ARE THE GENERATED FILES:
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/frontend/routes.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:App/etc/routes.xsd”>
<router id=”standard”>
<route id=”pulsestorm_javascriptinittutorial” frontName=”pulsestorm_javascriptinittutorial”>
<module name=”Pulsestorm_JavascriptInitTutorial”/>
</route>
</router>
</config>

AND
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/Controller/Index/Index.php:
<?php
namespace Pulsestorm\JavascriptInitTutorial\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{

protected $resultPageFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}

public function execute()
{
return $this->resultPageFactory->create();
}
}

 

THEN
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_JavascriptInitTutorial frontend pulsestorm_javascriptinittutorial_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml
Creating: Pulsestorm\JavascriptInitTutorial\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/layout/pulsestorm_javascriptinittutorial_index_index.xml

HERE ARE THE GENERATED FILES:
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<h1>This is my template, there are many like it, but this one is mine.</h1>

AND
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/layout/pulsestorm_javascriptinittutorial_index_index.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<referenceBlock name=”content”><block template=”content.phtml” class=”Pulsestorm\JavascriptInitTutorial\Block\Main” name=”pulsestorm_javascriptinittutorial_block_main”/></referenceBlock></page>

AND
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/Block/Main.php:
<?php
namespace Pulsestorm\JavascriptInitTutorial\Block;
class Main extends \Magento\Framework\View\Element\Template
{
function _prepareLayout(){}
}

 

THEN I HAVE TO GO UP THE MAGENTO ROOT THEN LOGIN AS ‘sudo -s -u _www’:
Satrias-MacBook-Pro:code teddy$ php bin/magento module:enable Pulsestorm_JavascriptInitTutorial
Could not open input file: bin/magento
Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_JavascriptInitTutorial
Command line user does not have read and write permissions on var/generation directory. Please address this issue before using Magento command line.
Satrias-MacBook-Pro:magentoce215 teddy$ sudo -s -u _www
Password:
bash-3.2$ php bin/magento module:enable Pulsestorm_JavascriptInitTutorial
The following modules have been enabled:
– Pulsestorm_JavascriptInitTutorial

To make sure that the enabled modules are properly registered, run ‘setup:upgrade’.
Cache cleared successfully.
Generated classes cleared successfully. Please run the ‘setup:di:compile’ command to generate classes.
Info: Some modules might require static view files to be cleared. To do this, run ‘module:enable’ with the –clear-static-content option to clear them.

THEN THE LAST:
bash-3.2$ php bin/magento setup:upgrade

TEST THE ROUTE URL: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D PRINT:
‘This is my template, there are many like it, but this one is mine.’

Setting up a RequireJS Module
CREATE A NEW FILE: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:
define([],function(){
alert(“A simple RequireJS Module”);
return {};
});

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<h1>This is my template, there are many like it, but this one is mine.</h1>

<script type=”text/javascript”>
requirejs([‘Pulsestorm_JavascriptInitTutorial/example’], function(example){
alert(‘Loaded!’);
console.log(example);
});
</script>

RUN: php bin/magento c:f
THEN TEST AGAIN: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D WORK AS EXPECTED. THE TWO ALERT “A simple RequireJS Module” THEN ‘Loaded!’ WOULD BE POPED UP. ALSO THE CONSOLE WOULD PRINT ‘{}’

X-Magento-Init
PURPOSES:
provides a way to pass that program a server side generated JSON object.
provides a way to provide that program with the DOM nodes it should operate on.

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<!–h1>This is my template, there are many like it, but this one is mine.</h1–>

<!–script type=”text/javascript”>
requirejs([‘Pulsestorm_JavascriptInitTutorial/example’], function(example){
alert(‘Loaded!’);
console.log(example);
});
</script–>

<div id=”one” class=”foo”>
Hello World
</div>
<div id=”two” class=”foo”>
Goodbye World
</div>

<script type=”text/x-magento-init”>
{
“*”: {
“Pulsestorm_JavascriptInitTutorial/example”:{}
}
}
</script>

RUN: php bin/magento c:f
THEN TEST AGAIN: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D SHOW ALERT “A simple RequireJS Module”
BUT THEN I GOT AN ERROR:
REFER TO: http://magentoce215.local/pub/static/version1513154325/frontend/Magento/luma/en_US/mage/apply/main.js
Uncaught TypeError: Cannot read property ‘bind’ of undefined
at main.js:26
at Object.execCb (require.js:1650)
at Module.check (require.js:866)
at Module.<anonymous> (require.js:1113)
at require.js:132
at require.js:1156
at each (require.js:57)
at Module.emit (require.js:1155)
at Module.check (require.js:917)
at Module.enable (require.js:1143)
SOLUTION: ‘The reason for this error? Because there’s no mage/menu key in the returned object.’
REF: https://alanstorm.com/requirejs-modules-that-return-two-widgets/
SO JUST FOLLOW BELOW ‘Magento Javascript Components’!

Magento Javascript Components
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:
/*
define([],function(){
alert(“A simple RequireJS Module”);
return {};
});
*/
define([], function () {
var mageJsComponent = function()
{
alert(“A simple magento component.”);
};

return mageJsComponent;
});

RUN: CLEAR CACHE
THEN RELOAD: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D SHOW THE ALERT “A simple magento component.”
ALSO THE ABOVE CONSOLE ERROR WOULD gone

WE CAN PASS PARAMETER TO THE REQUIREJS MODULE/COMPONENT (pass in server side generated JSON –> A SAMPLE FOR ‘provides a way to pass that program a server side generated JSON object.’)
FOR EXAMPLE PASS A PAIR KEY-VALUE PARAM ‘config’:’value’:
MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:

<script type=”text/x-magento-init”>
{
“*”: {
“Pulsestorm_JavascriptInitTutorial/example”:{“config”:”value”}
}
}
</script>

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:

define([], function () {
var mageJsComponent = function(config)
{
//alert(“A simple magento component.”);
alert(“Look in your browser’s console”);
console.log(config);
};

return mageJsComponent;
});

RELOAD THE BROWSER!
CONSOLE PRINTED:
{config: “value”}
config:”value”
__proto__:Object

HERE IS A SAMPLE FOR ‘provides a way to provide that program with the DOM nodes it should operate on.’:
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:
define([], function () {
var mageJsComponent = function(config, node)
{
//alert(“A simple magento component.”);
//alert(“Look in your browser’s console”);
console.log(config);
console.log(node);
};

return mageJsComponent;
});

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<div id=”one” class=”foo”>
Hello World
</div>
<div id=”two” class=”foo”>
Goodbye World
</div>

<script type=”text/x-magento-init”>
{
“#one”:{
“Pulsestorm_JavascriptInitTutorial/example”:{“config”:”value”}
}
}
</script>

THEN CLEAR CACHE
AND RELOAD: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D PRINT THE OUTPUT ON CONSOLE:
{config: “value”}
example.js:13 <div id=​”one” class=​”foo” data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​
Hello World
​</div>​

OR IF
<script type=”text/x-magento-init”>
{
“.foo”:{
“Pulsestorm_JavascriptInitTutorial/example”:{“config”:”value”}
}
}
</script>

THE OUTPUT CONSOLE WOULD BE:
{config: “value”}
example.js:13 <div id=​”one” class=​”foo” data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​
Hello World
​</div>​
example.js:12 {config: “value”}
example.js:13 <div id=​”two” class=​”foo” data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​
Goodbye World
​</div>​

 

Data-mage-init Attribute

In addition to <script type=”text/x-magento-init”>, there’s another way to invoke similar functionality on a specific DOM node, and that’s with the data-mage-init attribute.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<div data-mage-init='{“Pulsestorm_JavascriptInitTutorial/example”: {“another”:”example”}}’>A single div</div>

THEN CLEAR THE CACHE
AND RELOAD.
HERE IS THE CONSOLE PRINTED:
{another: “example”}
example.js:13 <div data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​A single div​</div>​

KnockoutJS Primer for Magento Developers
https://alanstorm.com/knockoutjs_primer_for_magento_developers/
JUST AN INTRODUCTION

Magento 2: KnockoutJS Integration
https://alanstorm.com/magento_2_knockoutjs_integration/

Creating a Magento Module
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm KnockoutTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_KnockoutTutorial frontend pulsestorm_knockouttutorial
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/Controller/Index/Index.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_KnockoutTutorial frontend pulsestorm_knockouttutorial_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/templates/content.phtml
Creating: Pulsestorm\KnockoutTutorial\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/layout/pulsestorm_knockouttutorial_index_index.xml

Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_KnockoutTutorial
The following modules have been enabled:
– Pulsestorm_KnockoutTutorial

To make sure that the enabled modules are properly registered, run ‘setup:upgrade’.
Cache cleared successfully.
Generated classes cleared successfully. Please run the ‘setup:di:compile’ command to generate classes.
Info: Some modules might require static view files to be cleared. To do this, run ‘module:enable’ with the –clear-static-content option to clear them.
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento setup:upgrade

Module ‘Pulsestorm_KnockoutTutorial’:
Please re-run Magento compile command

TEST: http://magentoce215.local/pulsestorm_knockouttutorial

NOTE: I NEED TO DISABLE Inchoo_ModalOverlay MODULE BECAUSE IT’S ANNOYING TO SHOW THE POPUP EACH TIME I REFRESH THE BROWSER! PROBABLY I NEED TO WRITE A TUTORIAL HOW TO WRITE THIS KIND OF MODULE (SHOW THE POPUP ON EACH PAGE)

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/templates/content.phtml:
<!–h1>This is my template, there are many like it, but this one is mine.</h1–>
<div data-bind=”template:’Pulsestorm_KnockoutTutorial/hello'”></div>

THEN ADD A NEW FILE hello.html IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/web/template/hello.html:
<p data-bind=”style:{fontSize:’24px’}”>Hello World</p>

CLEAR CACHE AND RELOAD.
IT’D PRINT ‘Hello World’

The Curious Case of Magento 2 Mixins
https://alanstorm.com/the-curious-case-of-magento-2-mixins/

Magento 2 RequireJS Mixins
A Magento 2 RequireJS “mixin” allows you to programmatically listen for the initial instantiation of any RequireJS module and manipulate that module before returning it.

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm RequireJsRewrite 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/registration.php

Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_RequireJsRewrite && php bin/magento setup:upgrade

CREATE A NEW FILE ‘requirejs-config.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/view/base/requirejs-config.js:
var config = {
‘config’:{
‘mixins’:{
‘Magento_Customer/js/view/customer’:{
‘Pulsestorm_RequireJsRewrite/hook’:true
}
}
}
};

THEN CREATE A NEW FILE ‘hook.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/view/base/web/hook.js:
define([], function(){
‘use strict’;
console.log(“Called this hook.”);
return function(targetModule){
targetModule.crazyPropertyAddedHere = ‘yes’;
return targetModule;
};
});

CLEAR THE CACHE THE TEST IT ON the Magento homepage (or any page which uses the Magento_Customer/js/view/customer RequireJS module): http://magentoce215.local/
IT’D PRINT ON THE CONSOLE: “Called this hook.”
Also, if you examine the Magento_Customer/js/view/customer module via the console, you’ll see it has an extra crazyPropertyAddedHere property:
module = requirejs(“Magento_Customer/js/view/customer”);
ƒ () {
var obj = this;

if (!_.isObject(obj) || Object.getPrototypeOf(obj) !== UiClass.prototype) {
obj = Object.create(UiClass.prototype);

console.log(module.crazyPropertyAddedHere);
VM2475:1 yes

With the above code, we changed the object returned by the Magento_Customer/js/view/customer module. If used judiciously, this is an incredibly powerful feature.

Class Rewrites for Javascript

 

Knockout Observables for Javascript Programmers
https://alanstorm.com/knockout-observables-for-javascript-programmers/

Important: Subscribers are only called when a value changes. If you pass in the observable’s current value, Knockout will not call subscriber callbacks

 

Modifying a jQuery Widget in Magento 2
https://alanstorm.com/modifying-a-jquery-widget-in-magento-2/

Creating our Mixin
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm Logdropdown 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/registration.php

CREATE A NEW FILE ‘requirejs-config.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/view/base/requirejs-config.js:
var config = {
‘config’:{
‘mixins’:{
‘mage/dropdown’:{
‘Pulsestorm_Logdropdown/js/dropdown-mixin’:true
}
}
}
};

THEN CREATE A REQUIREJS MODULE ‘dropdown-mixin.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/view/base/web/js/dropdown-mixin.js:
define([‘jquery’], function($){
return function(originalWidget){
alert(‘Our mixin is hooked up.’);
console.log(‘Our mixin is hooked up.’);
console.log(originalWidget);

return originalWidget;
};
});

THEN ENABLE THE MODULE:
Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_Logdropdown && php bin/magento setup:upgrade

LOAD ON ANY PAGE that uses the dropdownWidget widget (home page, catalog listing page, etc), and you should see an alert and a console.log message that says Our mixin is hooked up.

ƒ ( options, element ) {
// allow instantiation without “new” keyword
if ( !this._createWidget ) {
return new constructor( options, element );
}

// allow instantiation without initializing …

Changing a Widget
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/view/base/web/js/dropdown-mixin.js:
define([‘jquery’], function($){
return function(originalWidget){
/*alert(‘Our mixin is hooked up.’);
console.log(‘Our mixin is hooked up.’);
console.log(originalWidget);

return originalWidget;*/
// if you want to get fancy and pull the widget namespace
// and name from the returned widget definition
// var widgetFullName = originalWidget.prototype.namespace +
// ‘.’ +
// originalWidget.prototype.widgetName;

 

$.widget(
‘mage.dropdownDialog’, //named widget we’re redefining

//$.mage.dropdownDialog
$[‘mage’][‘dropdownDialog’], //widget definition to use as
//a “parent” definition — in
//this case the original widget
//definition, accessed using
//bracket syntax instead of
//dot syntax

{ //the new methods
open:function(){
//our new code here
console.log(“I opened a dropdown!”);

//call parent open for original functionality
return this._super();

}
});

//return the redefined widget for data-mage-init
//jQuery.mage.dropdownDialog
return $[‘mage’][‘dropdownDialog’];
};
});

With the above in place, clear your browser cache and reload the page. Then, click on any dropdown widget on the page — the currency/store-views are good candidates

After clicking on these menus and confirming everything still works, take a look at your javascript console — you should see the I opened a dropdown! text successfully logged.

 

Introduction to Magento 2 — No More MVC
https://alanstorm.com/magento_2_mvvm_mvc/

CREATE A NEW MODULE ‘HelloWorldMVVM’:
CREATE A NEW FILE ‘registration.php’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/registration.php:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
‘Pulsestorm_HelloWorldMVVM’,
__DIR__
);

CREATE A NEW FILE ‘module.xml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/etc/module.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd”>
<module name=”Pulsestorm_HelloWorldMVVM” setup_version=”0.0.1″ />
</config>

ENABLE THE MODULE: Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_HelloWorldMVVM && php bin/magento setup:upgrade

CREATE A NEW FRONTEND ROUTE ‘routes.xml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/etc/frontend/routes.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd”>
<router id=”standard”>
<route id=”hello_mvvm” frontName=”hello_mvvm”>
<module name=”Pulsestorm_HelloWorldMVVM” />
</route>
</router>
</config>

CREATE A NEW CONTROLLER ‘Hello/World.php’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:
<?php
namespace Pulsestorm\HelloWorldMVVM\Controller\Hello;

class World extends \Magento\Framework\App\Action\Action {
public function execute(){
echo ‘You Did it!’;
var_dump(__METHOD__);
}
}

TEST THE ROUTE BY OPENING: http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT:
You Did it!
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:7:string ‘Pulsestorm\HelloWorldMVVM\Controller\Hello\World::execute’ (length=57)

 

Passing off to the View
MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:
<?php
namespace Pulsestorm\HelloWorldMVVM\Controller\Hello;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\App\Action\Context;

class World extends \Magento\Framework\App\Action\Action
{
protected $pageFactory;
public function __construct(Context $context, PageFactory $pageFactory)
{
$this->pageFactory = $pageFactory;
return parent::__construct($context);
}

public function execute()
{
var_dump(__METHOD__);
$page_object = $this->pageFactory->create();
return $page_object;
}
}

BUT I GOT THIS ERROR ON RELOADING: http://magentoce215.local/hello_mvvm/hello/world
Fatal error: Uncaught TypeError: Argument 2 passed to Pulsestorm\HelloWorldMVVM\Controller\Hello\World::__construct() must be an instance of Magento\Framework\View\Result\PageFactory, none given, called in /Library/WebServer/Documents/Projects/magentoce215/var/generation/Pulsestorm/HelloWorldMVVM/Controller/Hello/World/Interceptor.php on line 14 and defined in /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php on line 9
( ! ) TypeError: Argument 2 passed to Pulsestorm\HelloWorldMVVM\Controller\Hello\World::__construct() must be an instance of Magento\Framework\View\Result\PageFactory, none given, called in /Library/WebServer/Documents/Projects/magentoce215/var/generation/Pulsestorm/HelloWorldMVVM/Controller/Hello/World/Interceptor.php on line 14 in /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php on line 9
SOLUTION: I NEED TO REMOVE THE var/generation DIRECTORY!!! CLEAR THE CACHE IS NOT ENOUGH!!!
Satrias-MacBook-Pro:magentoce215 teddy$ sudo rm -rf var/*
Password:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento c:f

HERE IS THE OUTPUT: (NO CONTENT YET) http://magentoce215.local/hello_mvvm/hello/world
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:17:string ‘Pulsestorm\HelloWorldMVVM\Controller\Hello\World::execute’ (length=57)

Creating the View
ADD A NEW LAYOUT ‘hello_mvvm_hello_world.xml’ (THIS FILENAME IS FULL ACTION NAME. THE COMBINATION FROM frontName/ID: hello_mvvm AND CONTROLLER & CLASS NAME: hello_world) IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/layout/hello_mvvm_hello_world.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd”>
<referenceBlock name=”content”>
<block
template=”content.phtml”
class=”Pulsestorm\HelloWorldMVVM\Block\Main”
name=”pulsestorm_helloworld_mvvm”/>
</referenceBlock>
</page>

CREATE A BLOCK FILE ‘Main.php’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php:
<?php
namespace Pulsestorm\HelloWorldMVVM\Block;
use Magento\Framework\View\Element\Template;

class Main extends Template
{
protected function _prepareLayout()
{

}
}

THEN CREATE A TEMPLATE FILE ‘content.phtml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1>Hello World</h1>

CLEAR THE CACHE AND RELOAD! http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT ‘Hello World’ WITH THE MAGENTO LUMA TEMPLATE

View/View Model
MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php: –> USE SET/GET METHOD

protected function _prepareLayout()
{
$this->setMessage(‘Hello Again World’);
}

THEN CALL IT FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1><?php echo $this->escapeHtml($this->getMessage()); ?></h1>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT: “Hello Again World”

OR MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php. THEN ADD A NEW FUNCTION ‘getGoodbyeMessage’:

public function getGoodbyeMessage()
{
return ‘Goodbye World’;
}

CALL IT FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1><?php echo $this->escapeHtml($this->getGoodbyeMessage()); ?></h1>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT: Goodbye World

USE PARAMS. FOR EXAMPLE WITH URL: http://magentoce215.local/hello_mvvm/hello/world/name/satria
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php:

protected function _prepareLayout()
{
$this->setMessage(‘Hello Again World’);
$this->setName($this->getRequest()->getParam(‘name’));
}

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1>
<?php echo $this->escapeHtml($this->getMessage()); ?>
<?php echo $this->escapeHtml($this->getName()); ?>
</h1>

<h2><?php echo $this->escapeHtml($this->getGoodbyeMessage()); ?></h2>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/hello_mvvm/hello/world/name/satria
IT’D PRINT:
Hello Again World satria
Goodbye World

 

Magento 2: Adding Frontend Assets via Layout XML
https://alanstorm.com/magento_2_javascript_css_layout_woes/

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm JavascriptCssExample 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_JavascriptCssExample frontend pulsestorm_javascriptcssexample
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/Controller/Index/Index.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_JavascriptCssExample frontend pulsestorm_javascriptcssexample_index_index Main content.phtml
Layout (ignored for adminhtml) ? (1column)]
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/templates/content.phtml
Creating: Pulsestorm\JavascriptCssExample\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/layout/pulsestorm_javascriptcssexample_index_index.xml

 

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_JavascriptCssExample && php bin/magento setup:upgrade

TEST IT ON http://magentoce215.local/pulsestorm_javascriptcssexample

MODIFY TO ADD JS AND CSS ON /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/layout/pulsestorm_javascriptcssexample_index_index.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<head>
<css src=”Pulsestorm_JavascriptCssExample::test.css”/>
<link src=”Pulsestorm_JavascriptCssExample::test.js”/>
</head>
<referenceBlock name=”content”><block template=”content.phtml” class=”Pulsestorm\JavascriptCssExample\Block\Main” name=”pulsestorm_javascriptcssexample_block_main”/></referenceBlock></page>

ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/web/test.js:
alert(“Hello”);

THEN ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/web/test.js:
body{
background-color:#f00;
}

CLEAR CACHE AND RELOAD: http://magentoce215.local/pulsestorm_javascriptcssexample
IT’S SHOW ‘Hello’ AND THE BG COLOR WOULD BE CHANGED TO RED

Adding Files Via PHP
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/layout/pulsestorm_javascriptcssexample_index_index.xml:
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<head>
<css src=”Pulsestorm_JavascriptCssExample::test.css”/>
<link src=”Pulsestorm_JavascriptCssExample::test.js”/>
</head>
<referenceBlock name=”content”>
<block template=”content.phtml”
class=”Pulsestorm\JavascriptCssExample\Block\Main”
name=”pulsestorm_javascriptcssexample_block_main”/>
</referenceBlock>
<referenceBlock name=”head.additional”>
<block template=”head.phtml”
class=”Pulsestorm\JavascriptCssExample\Block\Head”
name=”pulsestorm_javascriptcssexample_block_head” />
</referenceBlock>
</page>

ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/Block/Head.php:
<?php
namespace Pulsestorm\JavascriptCssExample\Block;
class Head extends \Magento\Framework\View\Element\Template
{

}

THEN ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/templates/head.phtml:
<!– Hello There –>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/pulsestorm_javascriptcssexample
THEN IT’D PRINT ‘<!– Hello There –>’ IN ‘head.additional’ BLOCK

The Asset Repository
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/Block/Head.php:
<?php
namespace Pulsestorm\JavascriptCssExample\Block;
class Head extends \Magento\Framework\View\Element\Template
{
public $assetRepository;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
array $data = [],
\Magento\Framework\View\Asset\Repository $assetRepository
)
{
$this->assetRepository = $assetRepository;
return parent::__construct($context, $data);
}
}

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/templates/head.phtml:
@highlightsyntax@php
<?php
$asset_repository = $this->assetRepository;
$asset = $asset_repository->createAsset(‘Pulsestorm_JavascriptCssExample::test.js’);
$url = $asset->getUrl();
?>
<!– Hello There –>
<script src=”<?php echo $url; ?>”></script>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/pulsestorm_javascriptcssexample
THEN IT’D PRINT ‘<!– Hello There –>’ IN ‘head.additional’ BLOCK THEN CREATE A SCRIPT:
<script src=”http://magentoce215.local/pub/static/version1513654716/frontend/Magento/luma/en_US/Pulsestorm_JavascriptCssExample/test.js”></script>

 

Magento 2: CRUD Models for Database Access
https://alanstorm.com/magento_2_crud_models_for_database_access/

Creating a Base Module
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm ToDoCrud 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_ToDoCrud frontend pulsestorm_todocrud
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Controller/Index/Index.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_ToDoCrud frontend pulsestorm_todocrud_index_index Main content.phtml
Layout (ignored for adminhtml) ? (1column)]
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/frontend/templates/content.phtml
Creating: Pulsestorm\ToDoCrud\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/frontend/layout/pulsestorm_todocrud_index_index.xml

Generating Crud Files
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_crud_model Pulsestorm_ToDoCrud TodoItem
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Api/TodoItemRepositoryInterface.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/TodoItemRepository.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Api/Data/TodoItemInterface.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/ResourceModel/TodoItem/Collection.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/ResourceModel/TodoItem.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/TodoItem.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Setup/InstallSchema.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Setup/InstallData.php

Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_ToDoCrud && php bin/magento setup:upgrade

TEST IT: http://magentoce215.local/pulsestorm_todocrud

Magento 2 Factory Objects
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Block/Main.php:
<?php
namespace Pulsestorm\ToDoCrud\Block;

use Magento\Framework\View\Element\Template\Context;
use Pulsestorm\ToDoCrud\Model\TodoItemFactory;

class Main extends \Magento\Framework\View\Element\Template
{
protected $todoFactory;

public function __construct(Context $context, TodoItemFactory $todoFactory){
$this->todoFactory = $todoFactory;
parent::__construct($context);
}

function _prepareLayout(){
//var_dump(“I’m here”);
var_dump(get_class($this->todoFactory));
exit;
}
}

CLEAR THE CACHE (IF NEEDED CLEAR var/* DIR) THEN RELOAD: http://magentoce215.local/pulsestorm_todocrud
IT’D PRINT: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Block/Main.php:18:string ‘Pulsestorm\ToDoCrud\Model\TodoItemFactory’ (length=41)

MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Block/Main.php:

function _prepareLayout(){
//var_dump(“I’m here”);
//var_dump(get_class($this->todoFactory));
$todo = $this->todoFactory->create();
$todo->setData(‘item_text’,’Finish my Magento article’)
->save();
var_dump(‘Done’);
exit;
}

CLEAR CACHE & RELOAD: http://magentoce215.local/pulsestorm_todocrud

CHECK THE TABLE IN PHPMYADMIN:
select * from pulsestorm_todocrud_todoitem

_prepareLayout() function could be:

function _prepareLayout(){
//var_dump(“I’m here”);
//var_dump(get_class($this->todoFactory));
$todo = $this->todoFactory->create();
$collection = $todo->getCollection();
//$todo->setData(‘item_text’,’Finish my Magento article’)
//->save();
//var_dump(‘Done’);
//$todo = $todo->load(1);
//var_dump($todo->getData());
foreach($collection as $item){
var_dump(“Item ID:”.$item->getId());
var_dump($item->getData());
}
exit;
}

 

Magento 2: Understanding Object Repositories
https://alanstorm.com/magento_2_understanding_object_repositories/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm RepositoryTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_command Pulsestorm_RepositoryTutorial Examples
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_RepositoryTutorial && php bin/magento setup:upgrade

TEST THE COMMAND FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/Command/Examples.php:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Hello World

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/Command/Examples.php:

use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\App\State;

class Examples extends Command
{
protected $objectManager;

public function __construct(ObjectManagerInterface $objectManager, State $appState, $name = null){
$this->objectManager = $objectManager;
$appState->setAreaCode(‘frontend’);
parent::__construct($name);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
$page = $repo->getById(2);
$output->writeln(get_class($page));
}
}

TEST THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Magento\Catalog\Model\Product\Interceptor

WE CAN GET THE PRODUCT NAME:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
$page = $repo->getById(2);
//$output->writeln(get_class($page));
//$output->writeln($page->getTitle()); //EMPTY!!!
$output->writeln($page->getName());
}

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Strive Shoulder Pack


protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
$page = $repo->getById(2);
//$output->writeln(get_class($page));
//$output->writeln($page->getTitle()); //EMPTY!!!
//$output->writeln($page->getName());
/*$page->setTitle($page->getTitle().”, Edited by code”);
$repo->save($page);
$output->writeln($page->getTitle());*/
$page->setId(null);
$page->setTitle(“My duplicated page”);
$repo->save($page);
$output->writeln($page->getId());
$output->writeln($page->getTitle());
}

BUT I GOT AN ERROR:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples

 

[Magento\Framework\Exception\AlreadyExistsException]
URL key for specified store already exists.

 

ps:examples

SEARCH CRITERIA
MODIFY

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Joust Duffle Bag
Strive Shoulder Pack
Crown Summit Backpack
….

MODIFY TO GET ALL PRODUCT CONTAIN/END WITH NAME ‘backpack’:

protected function execute(InputInterface $input, OutputInterface $output)
{
//create a filter
$filter = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter->setData(‘field’, ‘name’);
$filter->setData(‘value’, ‘%backpack’);
$filter->setData(‘condition_type’, ‘like’);

//add the filter to a group
$filter_group = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group->setData(‘filters’, [$filter]);

//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);
//add the filter group to the search criteria object
$search_criteria->setFilterGroups([$filter_group]);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}
….

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Crown Summit Backpack
Fusion Backpack
Endeavor Daytrip Backpack
Driven Backpack

ADD ANOTHER FILTER (WOULD CREATE ‘OR’ JOIN):

protected function execute(InputInterface $input, OutputInterface $output)
{
//create a filter
$filter = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter->setData(‘field’, ‘name’);
$filter->setData(‘value’, ‘%backpack’);
$filter->setData(‘condition_type’, ‘like’);

//create another filter
$filter2 = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter2->setData(‘field’, ‘name’);
$filter2->setData(‘value’, ‘%sprite%’);
$filter2->setData(‘condition_type’, ‘like’);

//add the filter to a group
$filter_group = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group->setData(‘filters’, [$filter, $filter2]);

//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);
//add the filter group to the search criteria object
$search_criteria->setFilterGroups([$filter_group]);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Crown Summit Backpack
Fusion Backpack
Endeavor Daytrip Backpack
Driven Backpack
Sprite Foam Yoga Brick
Sprite Foam Roller
Sprite Stasis Ball 55 cm
Sprite Stasis Ball 55 cm
Sprite Stasis Ball 55 cm
Sprite Stasis Ball 65 cm
Sprite Stasis Ball 65 cm
Sprite Stasis Ball 65 cm
Sprite Stasis Ball 75 cm
Sprite Stasis Ball 75 cm
Sprite Stasis Ball 75 cm
Sprite Yoga Strap 6 foot
Sprite Yoga Strap 8 foot
Sprite Yoga Strap 10 foot
Sprite Yoga Companion Kit
Set of Sprite Yoga Straps

ADD ANOTHER FILTER GROUP (WOULD CREATE ‘AND’ JOIN):

protected function execute(InputInterface $input, OutputInterface $output)
{
//create a filter
$filter = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter->setData(‘field’, ‘name’);
$filter->setData(‘value’, ‘%sport%’);
$filter->setData(‘condition_type’, ‘like’);

//create another filter
$filter2 = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter2->setData(‘field’, ‘name’);
$filter2->setData(‘value’, ‘%black%’);
$filter2->setData(‘condition_type’, ‘like’);

//add the filter to a group
$filter_group = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group->setData(‘filters’, [$filter]);

//add the filter2 to another group
$filter_group2 = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group2->setData(‘filters’, [$filter2]);

//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);
//add the filter group to the search criteria object
$search_criteria->setFilterGroups([$filter_group, $filter_group2]);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Supernova Sport Pant-32-Black
Supernova Sport Pant-33-Black
Supernova Sport Pant-34-Black
Supernova Sport Pant-36-Black
Rapha Sports Short-32-Black
Rapha Sports Short-33-Black
Rapha Sports Short-34-Black
Rapha Sports Short-36-Black

 

Helper Class with Dependency Injection

 

Magento 2: Understanding Access Control List Rules
https://alanstorm.com/magento_2_understanding_access_control_list_rules/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm AclExample 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/registration.php

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_AclExample && php bin/magento setup:upgrade

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_acl Pulsestorm_AclExample Pulsestorm_AclExample::top,Pulsestorm_AclExample::config
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/etc/acl.xml

CREATED /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/etc/acl.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:Acl/etc/acl.xsd”>
<acl>
<resources>
<resource id=”Magento_Backend::admin”>
<resource id=”Pulsestorm_AclExample::top” title=”Pulse Storm ACL Example Module”>
<resource id=”Pulsestorm_AclExample::config” title=”The First Rule”/>
<resource id=”Pulsestorm_AclExample::more_rules” title=”The Second Rule”/>
</resource>
</resource>
</resources>
</acl>
</config>

take a look at the Roles menu at System -> User Roles -> Add/Edit Role -> Role Resources. You should see your rules added to the system

 

Magento 2: Admin Menu Items
https://alanstorm.com/magento_2_admin_menu_items/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm MenuTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/registration.php

Satrias-MacBook-Pro:code teddy$ cd ../..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_MenuTutorial && php bin/magento setup:upgrade

ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/adminhtml/menu.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Backend:etc/menu.xsd”>
<menu>
<add id=”Pulsestorm_MenuTutorial::top_level_example”
title=”Top Level Example”
module=”Pulsestorm_MenuTutorial”
sortOrder=”9999″
resource=”Magento_Backend::content”
/>
</menu>
</config>

With the above in place, clear your Magento cache and load a backend page. You should see a new, top level Menu Item at the bottom of the admin navigation

ADD ADMIN SUB MENU
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/adminhtml/menu.xml:

<!– START: new node –>
<add id=”Pulsestorm_MenuTutorial::second_level_example”
title=”Second Level Example”
module=”Pulsestorm_MenuTutorial”
sortOrder=”9999″
resource=”Magento_Backend::content”

parent=”Pulsestorm_MenuTutorial::top_level_example”
action=”cms/page/index”
/>
<!– END: new node –>

ADD ADMIN SUB SUB MENU

<!– ADD L3 –>
<add id=”Pulsestorm_MenuTutorial::third_level_example”
title=”Third Level Example”
module=”Pulsestorm_MenuTutorial”
sortOrder=”9999″
resource=”Magento_Backend::content”

parent=”Pulsestorm_MenuTutorial::second_level_example”
action=”cms/page/index”
/>

 

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_acl
Which Module? (Pulsestorm_HelloWorld)] Pulsestorm_MenuTutorial
Rule IDs? (Pulsestorm_MenuTutorial::top,Pulsestorm_MenuTutorial::config,)] Pulsestorm_MenuTutorial::menu_items,Pulsestorm_MenuTutorial::example_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/acl.xml

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/acl.xml:

<resource id=”Pulsestorm_MenuTutorial::menu_items” title=”Tutorial Menu Items”>
<resource id=”Pulsestorm_MenuTutorial::example_1″ title=”First Example”/>
</resource>

 

GENERATE MENU:
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_menu
Module Name? (Pulsestorm_HelloGenerate)] Pulsestorm_MenuTutorial
Is this a new top level menu? (Y/N) (N)] N
Select Parent Menu:
[1] System (Magento_Backend::system)
[2] Customers (Magento_Customer::customer)
[3] Reports (Magento_Reports::report)
[4] Find Partners & Extensions (Magento_Marketplace::partners)
[5] Sales (Magento_Sales::sales)
[6] Dashboard (Magento_Backend::dashboard)
[7] System (Magento_Backend::system)
[8] Marketing (Magento_Backend::marketing)
[9] Content (Magento_Backend::content)
[10] Stores (Magento_Backend::stores)
[11] Products (Magento_Catalog::catalog)
[12] (Magento_Backend::system_currency)
[13] Top Level Example (Pulsestorm_MenuTutorial::top_level_example)
()] 1
Use [Magento_Backend::system] as parent? (Y/N) (N)] N
Select Parent Menu:
[1] Report (Magento_Backend::system_report)
[2] Permissions (Magento_User::system_acl)
[3] Extensions (Magento_Integration::system_extensions)
[4] Tools (Magento_Backend::system_tools)
[5] Data Transfer (Magento_Backend::system_convert)
[6] Other Settings (Magento_Backend::system_other_settings)
()] 6
Menu Link ID (Pulsestorm_MenuTutorial::unique_identifier)] Pulsestorm_MenuTutorial::a_menu_item
ACL Resource (Pulsestorm_MenuTutorial::a_menu_item)] Pulsestorm_MenuTutorial::example_1
Link Title (My Link Title)] Look at me, I’m a link
Three Segment Action (frontname/index/index)] pulsestorm_menututorial/index/index
Sort Order? (10)] 9999
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/adminhtml/menu.xml
Done.

 

Magento 2: Admin MVC/MVVM Endpoints
https://alanstorm.com/magento_2_admin_mvcmvvm_endpoints/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm HelloAdminBackend 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_acl Pulsestorm_HelloAdminBackend Pulsestorm_HelloAdminBackend::top,Pulsestorm_HelloAdminBackend::menu_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/acl.xml

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_menu Pulsestorm_HelloAdminBackend Magento_Backend::system_other_settings Pulsestorm_HelloAdminBackend::a_menu_item Pulsestorm_HelloAdminBackend::menu_1 “Hello Admin Backend Pestle” pulsestorm_hello_admin_backend/index/index 1
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/adminhtml/menu.xml
Done.

Satrias-MacBook-Pro:code teddy$ cd ../..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_HelloAdminBackend && php bin/magento setup:upgrade

you’ll have a Pulsestorm_HelloAdminBackend module with an ACL hierarchy defined, and a single Menu Item under System -> Other Settings -> Hello Admin Backend Pestle.

CREATE ADMIN ROUTE
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route
Which Module? (Pulsestorm_HelloWorld)] Pulsestorm_HelloAdminBackend
Which Area (frontend, adminhtml)? (frontend)] adminhtml
Frontname/Route ID? (pulsestorm_helloworld)] pulsestorm_hello_admin_backend
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/adminhtml/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/Controller/Adminhtml/Index/Index.php
Don’t forget your menu.xml and acl.xml
action=”pulsestorm_hello_admin_backend/index/index”
id=”Pulsestorm_HelloAdminBackend::pulsestorm_hello_admin_backend_menu

Clear your cache and generated class files, and then click on the Hello Admin Backend Pestle menu. If you’re logged in as the Magento super user, you should be brought to a new, blank admin page!

ALLOWED USER
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/Controller/Adminhtml/Index/Index.php:
..
protected function _isAllowed()
{
return $this->_authorization->isAllowed(‘Pulsestorm_HelloAdminBackend::menu_1’);
}

ADD ADMIN CONTENT
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_view
Which Module? (Pulsestorm_HelloGenerate)] Pulsestorm_HelloAdminBackend
Which Area? (frontend)] adminhtml
Which Handle? (pulsestorm_helloadminbackend_index_index)] pulsestorm_hello_admin_backend_index_index
Block Name? (Main)] Main
Template File? (content.phtml)] content.phtml
Layout (ignored for adminhtml) ? (1column)]
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/view/adminhtml/templates/content.phtml
Creating: Pulsestorm\HelloAdminBackend\Block\Adminhtml\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/view/adminhtml/layout/pulsestorm_hello_admin_backend_index_index.xml

After running pestle with the above arguments and clearing your cache, reload your page and you should see pestle’s default block content.

MENU HIGHLIGHT
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/Controller/Adminhtml/Index/Index.php:
….
public function execute()
{
//return $this->resultPageFactory->create();
$page = $this->resultPageFactory->create();
$page->setActiveMenu(‘Pulsestorm_HelloAdminBackend::a_menu_item’);
return $page;
}

SET DIFFERENT TITLE
MODIFY AGAIN

public function execute()
{
//return $this->resultPageFactory->create();
$page = $this->resultPageFactory->create();
$page->setActiveMenu(‘Pulsestorm_HelloAdminBackend::a_menu_item’);
$page->getConfig()->getTitle()->prepend(__(‘My New Title’));
return $page;
}

 

Magento 2 Object Manager
https://alanstorm.com/magento_2_object_manager/

DOWNLOAD https://github.com/astorm/magento2-tutorial-objectmanager1
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectManager1

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-1
You did it!

USE OBJECT MANAGER
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectManager1/Command/Testbed.php:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“You did it!”);
$manager = $this->getObjectManager();
$object = $manager->create(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$output->writeln($object->getHelloMessage());
}

TEST THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-1
Hello Magento!

SINGLETON
MODIFY AGAIN:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“You did it!”);
$manager = $this->getObjectManager();
/*$object = $manager->create(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$output->writeln($object->getHelloMessage());*/

//USE ‘GET’ INSTEAD OF ‘CREATE’ FOR SINGLETON
$object = $manager->get(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$object->message = ‘Hello PHP!’;
$output->writeln(
$object->getHelloMessage()
);

$object = $manager->get(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$output->writeln(
$object->getHelloMessage()
);
}

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-1
Hello PHP!
Hello PHP!

 

Magento 2’s Automatic Dependency Injection
https://alanstorm.com/magento2_dependency_injection_2015/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectmanager2
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectManager2

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-2
Hello Again World!

AUTOMATIC DEPENDENCY INJECTION
MODIFY ‘__construct’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectManager2/Model/Example.php:

public function __construct(Message $message)
{
//$object = new Message; //
//$this->messageObject = $object;
$this->messageObject = $message;
}

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-2
Hello Again World!

SO NO NEED TO SUPPLY ‘message’ PARAMETER BECAUSE IT’D ALREDY TAKE CARE BY AUTOMATIC DEPENDENCY INJECTION OF M2
‘This is automatic dependency injection. Behind the scenes, the object manager will use PHP’s reflection features to look at a class’s __construct type hints/parameters, automatically instantiate the object for us, and then pass it into the constructor as an argument.’

 

Magento 2 Object Manager Preferences
https://alanstorm.com/magento_2_object_manager_preferences/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectpreference1
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectPreference

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-preference
Hello!

CLASS PREFERENCE
SEE: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectPreference/etc/di.xml

 

Magento 2 Object Manager Argument Replacement
https://alanstorm.com/magento_2_object_manager_argument_replacement/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectmanager-arguments
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectManagerArguments

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-arguments
Installed!

ARGUMENT REPLACEMENT
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectManagerArguments/etc/di.xml:

<type name=”Magento\Framework\Console\CommandList”>

</type>
<type name=”Pulsestorm\TutorialObjectManagerArguments\Model\Example”>
<arguments>
<argument name=”scaler1″ xsi:type=”string”>bar</argument>
</arguments>
</type>

RUN THE COMMAND: (CLEAR/FLUSH CACHE FIRST)
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-arguments

The Property $scaler1
is a string
with a value of: bar

REPLACING ARRAYS
MODIFY AGAIN:

<type name=”Pulsestorm\TutorialObjectManagerArguments\Model\Example”>
<arguments>
<argument name=”scaler1″ xsi:type=”string”>bar</argument>
<argument name=”thearray” xsi:type=”array”>
<item name=”0″ xsi:type=”string”>science</item>
<item name=”baz” xsi:type=”string”>baz</item>
<item name=”bar” xsi:type=”string”>bar</item>
</argument>
</arguments>
</type>

RUN THE COMMAND: (CLEAR/FLUSH CACHE FIRST)
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-arguments

The Property $thearray
is an array
with the elements:
0=>science
baz=>baz
bar=>bar

Magento 2 Object Manager Virtual Types
https://alanstorm.com/magento_2_object_manager_virtual_types/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectmanager-virtual-types
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialVirtualType

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-virtual-type
Installed Pulsestorm_TutorialVirtualType!

MODIFY ‘execute’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialVirtualType/Command/Testbed.php:

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->output = $output;
//$output->writeln(“Installed Pulsestorm_TutorialVirtualType!”);
$this->showNestedPropertiesForObject();
}

FLUSH THE CACHE AND RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-virtual-type
First, we’ll report on the Pulsestorm\TutorialVirtualType\Model\Example object
The Property $property_of_example_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument1

Next, we’re going to report on the Example object’s one property (an Argument1 class)
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument2

Finally, we’ll report on an Argument1 object, instantiated seperate from Example
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument2

Creating a Virtual Type
With virtual types, the only behavior you can change in your virtual sub-class is which dependencies are injected.
With virtual types, the only behavior you can change in your virtual sub-class is which dependencies are injected.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialVirtualType/etc/di.xml:

<virtualType name=”ourVirtualTypeName” type=”Pulsestorm\TutorialVirtualType\Model\Argument1″>
<arguments>
<argument name=”the_argument” xsi:type=”object”>Pulsestorm\TutorialVirtualType\Model\Argument3</argument>
</arguments>
</virtualType>

<type name=”Pulsestorm\TutorialVirtualType\Model\Example”>
<arguments>
<argument name=”the_object” xsi:type=”object”>ourVirtualTypeName</argument>
</arguments>
</type>

FLUSH THE CACHE AND RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-virtual-type
First, we’ll report on the Pulsestorm\TutorialVirtualType\Model\Example object
The Property $property_of_example_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument1

Next, we’re going to report on the Example object’s one property (an Argument1 class)
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument3 <– IT’S CHANGED BY VIRTUALTYPE

Finally, we’ll report on an Argument1 object, instantiated seperate from Example
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument2 <– NOT CHANGED

You’ll notice that the property_of_argument1_object property is now an Argument3 object — but only when that parameter’s owner class (Argument1) is instantiated by dependency injection in the Example class. When we instantiate Argument1 by itself — Magento does not inject a dependency.

 

Magento 2 Object Manager: Proxy Objects
https://alanstorm.com/magento_2_object_manager_proxy_objects/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-proxy-objects
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialProxy1
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialProxy2

RUN A COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
You’ve installed Pulsestorm_TutorialProxy2!
You’ve also installed Pulsestorm_TutorialProxy1!

MODIFY ‘execute’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialProxy2/Command/Testbed.php:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$this->installedCheck($output);
$service = $this->createService($output);
$this->sayHelloWithFastObject($service, $output);
$this->sayHelloWithSlowObject($service, $output);
}

RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
About to Create Service
Constructing FastLoading Object
Constructing SlowLoading Object
Created Service, approximate time to load: 3006.922 ms <– SLOW

About to say hello with fast object
Hello
Said hello with fast object, approximate time to load: 0.0188 ms

About to say hello with slow object
Hello
Said hello with slow object, approximate time to load: 0.0551 ms

TO REPLACE THE SLOW OBJECT IN TutorialProxy1 OBJECT, WE CAN’T USE PREFERENCE BUT PROXY. SO MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialProxy2/etc/di.xml:

<!– Notice: we’re using TutorialProxy2‘s di.xml to change the
behavior of TutorialProxy1. This the far more common usage
of object manager/dependency-injection than the examples in
our tutorial so far –>

<type name=”Pulsestorm\TutorialProxy1\Model\Example”>
<arguments>
<argument name=”slow” xsi:type=”object”>Pulsestorm\TutorialProxy1\Model\SlowLoading\Proxy</argument>
</arguments>
</type>

</config>

THEN FLUSH THE CACHE AND RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
About to Create Service
Constructing FastLoading Object
Created Service, approximate time to load: 9.789 ms <– MUCH FASTER FOR THE FIRST TIME

About to say hello with fast object
Hello
Said hello with fast object, approximate time to load: 0.0129 ms

About to say hello with slow object
Constructing SlowLoading Object
Hello
Said hello with slow object, approximate time to load: 3005.425 ms

THEN RE-RUN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
About to Create Service
Constructing FastLoading Object
Created Service, approximate time to load: 1.6 ms <– EVEN FASTER FOR THE 2nd TIME

About to say hello with fast object
Hello
Said hello with fast object, approximate time to load: 0.0131 ms

About to say hello with slow object
Constructing SlowLoading Object
Hello
Said hello with slow object, approximate time to load: 3000.463 ms

 

Magento 2 Object Manager: Instance Objects
https://alanstorm.com/magento_2_object_manager_instance_objects/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-instance-objects
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialInstanceObjects

RUN A COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-instance-objects
You’ve installed Pulsestorm_TutorialInstanceObjects

 

Magento 2 Object Manager Plugin System
https://alanstorm.com/magento_2_object_manager_plugin_system/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-plugin
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialPlugin

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin-installed
You’ve installed Pulsestorm_TutorialPlugin

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello hola!

CREATE A PLUGIN:
It’s inevitable that the larger community will start using the word “plugin” as a place-holder for “extension” or “module”, but in the language of the object manager, a “plugin” refers to a special class that’s listening for any public method call to another object.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/etc/di.xml:

<type name=”Pulsestorm\TutorialPlugin\Model\Example”>
<plugin name=”pulsestorm_tutorial_plugin_model_example_plugin”
type=”Pulsestorm\TutorialPlugin\Model\Example\Plugin”
sortOrder=”10″
disabled=”false”/>
</type>

CREATE A NEW EMPTY CLASS ‘Plugin’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/Model/Example/Plugin.php:
<?php
namespace Pulsestorm\TutorialPlugin\Model\Example;
class Plugin
{

}

FLUSH THE CACHE AND RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor <– INTERCEPTOR ADDED FOR THE PLUGIN!!

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello hola!

Plugins: After Methods
ADD ‘afterGetMessage’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/Model/Example/Plugin.php:

public function afterGetMessage($subject, $result)
{
echo “Calling ” , __METHOD__,”\n”;
return $result;
}

RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Calling Pulsestorm\TutorialPlugin\Model\Example\Plugin::afterGetMessage
Result: hello hola!

Plugins: Before Methods
ADD ‘beforeGetMessage’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/Model/Example/Plugin.php:

public function beforeGetMessage($subject, $thing=’World’, $should_lc=false)
{
echo “Calling ” . __METHOD__,”\n”;
}

RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

Calling Pulsestorm\TutorialPlugin\Model\Example\Plugin::beforeGetMessage
Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello hola!


public function beforeGetMessage($subject, $thing=’World’, $should_lc=false)
{
//echo “Calling ” . __METHOD__,”\n”;
return [‘Changing the argument’, $should_lc];
}

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello changing the argument!

Plugins: Around Methods
MODIFY

public function aroundGetMessage($subject, $procede, $thing=’World’, $should_lc=false)
{
echo ‘Calling’ . __METHOD__ . ‘ — before’,”\n”;
$result = $procede();
echo ‘Calling’ . __METHOD__ . ‘ — after’,”\n”;
return $result;
}

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — before
Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — after
Result: Hello World!

AVOID PLUGIN CONFLICT FOR SAME FUNCTION/METHOD NAME
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/etc/di.xml:

<!– START: two new plugins –>
<type name=”Pulsestorm\TutorialPlugin\Model\Example”>
<plugin name=”pulsestorm_tutorial_plugin_model_conflict_plugin1″
type=”Pulsestorm\TutorialPlugin\Model\Conflict\Plugin1″
sortOrder=”10″
disabled=”false”/>
</type>

<type name=”Pulsestorm\TutorialPlugin\Model\Example”>
<plugin name=”pulsestorm_tutorial_plugin_model_conflict_plugin2″
type=”Pulsestorm\TutorialPlugin\Model\Conflict\Plugin2″
sortOrder=”15″
disabled=”false”/>
</type>
<!– START: two new plugins –>

RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — before
Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Calling Pulsestorm\TutorialPlugin\Model\Conflict\Plugin1::afterGetMessage
Calling Pulsestorm\TutorialPlugin\Model\Conflict\Plugin2::afterGetMessage
CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — after
Result: From Plugin 2

Magento 2: Introducing UI Components
https://alanstorm.com/magento_2_introducing_ui_components/

Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar magento2:generate:ui:grid
Which Module? (Pulsestorm_Gridexample)] Pulsestorm_ToDoCrud
Create a unique ID for your Listing/Grid! (pulsestorm_gridexample_log)] pulsestorm_todo_listing
What Resource Collection Model should your listing use? (Magento\Cms\Model\ResourceModel\Page\Collection)] Pulsestorm\ToDoCrud\Model\ResourceModel\TodoItem\Collection
What’s the ID field for you model? (pulsestorm_gridexample_log_id)] pulsestorm_todocrud_todoitem_id
Creating New /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/adminhtml/ui_component/pulsestorm_todo_listing.xml
Creating: Pulsestorm\ToDoCrud\Ui\Component\Listing\DataProviders\Pulsestorm\Todo\Listing
Creating: Pulsestorm\ToDoCrud\Ui\Component\Listing\Column\Pulsestormtodolisting\PageActions
Don’t forget to add this to your layout XML with <uiComponent name=”pulsestorm_todo_listing”/>

ADD A NEW FILE: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/adminhtml/layout/pulsestorm_admin_todocrud_index_index.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<body>
<referenceBlock name=”content”>
<uiComponent name=”pulsestorm_todo_listing”/>
</referenceBlock>
</body>
</page>

 

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/adminhtml/ui_component/pulsestorm_todo_listing.xml:

<column name=”pulsestorm_todocrud_todoitem_id”>

</column>
<column name=”title”>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”filter” xsi:type=”string”>text</item>
<item name=”label” xsi:type=”string” translate=”true”>Item Title</item>
<item name=”sortOrder” xsi:type=”number”>20</item>
</item>
</argument>
</column>
<actionsColumn name=”actions” …

Magento 2: Simplest UI Component
https://alanstorm.com/magento_simplest_ui_component/

CREATE THE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_module Pulsestorm SimpleUiComponent 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/registration.php

CREATE ACL:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_acl Pulsestorm_SimpleUiComponent Pulsestorm_SimpleUiComponent::top,Pulsestorm_SimpleUiComponent::menu_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/acl.xml

CREATE MENU:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_menu Pulsestorm_SimpleUiComponent Magento_Backend::system_other_settings Pulsestorm_SimpleUiComponent::a_menu_item Pulsestorm_SimpleUiComponent::menu_1 “Hello Simple Ui Component” pulsestorm_simpleuicomponent/index/index 1
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/adminhtml/menu.xml
Done.

CREATE ROUTE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_route Pulsestorm_SimpleUiComponent adminhtml pulsestorm_simpleuicomponent
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/adminhtml/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Controller/Adminhtml/Index/Index.php
Don’t forget your menu.xml and acl.xml
action=”pulsestorm_simpleuicomponent/index/index”
id=”Pulsestorm_SimpleUiComponent::pulsestorm_simpleuicomponent_menu

CREATE VIEW:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_view Pulsestorm_SimpleUiComponent adminhtml pulsestorm_simpleuicomponent_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/templates/content.phtml
Creating: Pulsestorm\SimpleUiComponent\Block\Adminhtml\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/layout/pulsestorm_simpleuicomponent_index_index.xml

ENABLE THE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_SimpleUiComponent && php bin/magento setup:upgrade

After running the above commands, you should be able to navigate to Magento’s backend and click on the System -> Other Settings -> Hello Simple Ui Component menu to bring up our new backend section.

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/layout/pulsestorm_simpleuicomponent_index_index.xml:

<referenceBlock name=”content”>
<block template=”content.phtml” …/>

<!– START: our new ui component –>
<uiComponent name=”pulsestorm_simple”/>
<!– END: our new ui component –>
</referenceBlock>

CREATE A NEW FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/pulsestorm_simple.xml:
<?xml version=”1.0″?>
<pulsestorm_simple xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
</pulsestorm_simple>

THEN CREATE A NEW FILE ‘definition.xml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/base/ui_component/etc/definition.xml:
<?xml version=”1.0″?>
<components xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_definition.xsd”>
<pulsestorm_simple class=”Pulsestorm\SimpleUiComponent\Component\Simple”/>
</components>

HERE WE NEED TO ADD CLASS PREFERENCE. SO CREATE ‘di.xml’ FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/di.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:ObjectManager/etc/config.xsd”>
<preference for=”Magento\Framework\App\Arguments\ValidationState” type=”Pulsestorm\SimpleUiComponent\Model\ValidationState”/>
</config>

THEN CREATE A NEW PHP FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Model/ValidationState.php:
<?php
namespace Pulsestorm\SimpleUiComponent\Model;
class ValidationState extends \Magento\Framework\App\Arguments\ValidationState
{
public function isValidationRequired()
{
return false;
}
}

THEN CREATE ANOTHER NEW PHP FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Component/Simple.php:
<?php
namespace Pulsestorm\SimpleUiComponent\Component;
class Simple extends \Magento\Ui\Component\AbstractComponent
{
const NAME = ‘pulsestorm_simple’;
public function getComponentName()
{
return static::NAME;
}
}

THEN MODIFY ‘definition.xml’ LIKE THIS:
<?xml version=”1.0″?>
<components xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_definition.xsd”>
<pulsestorm_simple class=”Pulsestorm\SimpleUiComponent\Component\Simple”>
<argument name=”data” xsi:type=”array”>
<item name=”template” xsi:type=”string”>templates/our-template</item>
</argument>
</pulsestorm_simple>
</components>

THEN CREATE A NEW XHTML FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/templates/our-template.xhtml:
<?xml version=”1.0″ encoding=”UTF-8″?>
<div>
<h1>Hello World</h1>
</div>

 

THEN MODIFY ‘pulsestorm_simple.xml’ FILE:
<?xml version=”1.0″?>
<pulsestorm_simple xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>

<dataSource name=”pulsestorm_simple_data_source”>
<argument name=”dataProvider” xsi:type=”configurableObject”>
<!– the PHP class that implements a data provider –>
<argument name=”class” xsi:type=”string”>Pulsestorm\SimpleUiComponent\Model\DataProvider</argument>

<!– redundant with the dataSource name –>
<argument name=”name” xsi:type=”string”>pulsestorm_simple_data_source</argument>

<!– required: means ui components are meant to work with models –>
<argument name=”primaryFieldName” xsi:type=”string”>entity_id</argument>

<!– required: means ui components are meant to work with URL passing –>
<argument name=”requestFieldName” xsi:type=”string”>id</argument>
</argument>

</dataSource>

</pulsestorm_simple>

THEN ADD A NEW PHP FILE (DATA PROVIDER) IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Model/DataProvider.php:
<?php
namespace Pulsestorm\SimpleUiComponent\Model;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
}

OK. CLEAR THE CACHE THEN TEST IT ON THE ADMIN PAGE (SYSTEM -> HELLO SIMPLE UI COMPONENT).
IT SHOULD DIPLAY:
Magento Admin
This is my template, there are many like it, but this one is mine.
Hello World

 

MODIFYING XHTML TEMPLATE.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Component/Simple.php TO ADD NEW FUNCTION ‘getEvenMoreData’:

//added this method
public function getEvenMoreData()
{
return ‘Even More Data!’;
}

THEN CALL THE FUNCTION FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/templates/our-template.xhtml:

<p>
{{getComponentName()}}
</p>

<p>
{{getEvenMoreData()}}
</p>

OK. CLEAR THE CACHE THEN TEST IT ON THE ADMIN PAGE (SYSTEM -> HELLO SIMPLE UI COMPONENT).
IT SHOULD DIPLAY:
Magento Admin
This is my template, there are many like it, but this one is mine.
Hello World
pulsestorm_simple
Even More Data!

 

Magento 2: Simplest UI Knockout Component
https://alanstorm.com/magento_2_simplest_ui_knockout_component/

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/base/ui_component/etc/definition.xml:

<argument name=”data” xsi:type=”array”>

<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
….

CREATE A NEW JS FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/js/pulsestorm_simple_component.js:
/*define([], function(){
console.log(‘Called’);
});*/
define([‘uiElement’], function(Element){
console.log(‘Called’);
viewModelConstructor = Element.extend({
defaults: {
template: ‘Pulsestorm_SimpleUiComponent/pulsestorm_simple_template’
}
});

return viewModelConstructor;
});

//IT’D PRINT ‘Called’.

CREATE THE HTML TEMPLATE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/template/pulsestorm_simple_template.html:
<h1>Rendered with Knockout.js</h1>

MODIFY THE XHTML COMPONENT IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/templates/our-template.xhtml:

<div>

<div data-bind=”scope: ‘pulsestorm_simple.pulsestorm_simple'” class=”entry-edit form-inline”>
<!– ko template: getTemplate() –><!– /ko –>
</div>
</div>

OK. CLEAR THE CACHE AND RELOAD:
IT’D PRINT
Magento Admin

This is my template, there are many like it, but this one is mine.
Hello World
pulsestorm_simple

Even More Data!

{{message}}

Rendered with Knockout.js

NOTE: ‘pulsestorm_simple.pulsestorm_simple’ IS FROM THE UICOMPONENT NAME (/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/pulsestorm_simple.xml)

TO SHOW A MESSAGE IN THE HTML FILE (pulsestorm_simple_template.html), MODIFY THE COMPONENT (/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/js/pulsestorm_simple_component.js) LIKE THIS:
define([‘uiElement’, ‘ko’], function(Element, ko){
console.log(‘Called’);
viewModelConstructor = Element.extend({
defaults: {
template: ‘Pulsestorm_SimpleUiComponent/pulsestorm_simple_template’
},
message: ko.observable(“Hello Knockout.js!”)
});

return viewModelConstructor;
});

THEN IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/template/pulsestorm_simple_template.html:
<h1>Rendered with Knockout.js</h1>

<strong data-bind=”text:message”></strong>

CLEAR THE CACHE AND RELOAD.

HERE IS ANOTHER WAY TO RENDER THE TEMPLATE
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/base/ui_component/etc/definition.xml:

<item name=”config” xsi:type=”array”>
<!– <item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item> –>
<item name=”component” xsi:type=”string”>uiComponent</item>
</item>

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/pulsestorm_simple.xml AND ADD:

<pulsestorm_simple xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>

<dataSource name=”pulsestorm_simple_data_source”>

</dataSource>

<htmlContent name=”first_ever_child”>
<argument name=”block” xsi:type=”object”>Magento\Framework\View\Element\Text</argument>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
</htmlContent>

</pulsestorm_simple>

THEN CLEAR CACHE AND RELOAD. IT’D PRINT THE SAME! BUT IF I MODIFY THE ABOVE XML FILE FURTHER, LIKE THIS (ADD “second_ever_child”):

<htmlContent name=”first_ever_child”>

</htmlContent>

<htmlContent name=”second_ever_child”>
<argument name=”block” xsi:type=”object”>Magento\Framework\View\Element\Text</argument>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
</htmlContent>

THE TEMPLATE WOULD BE RENDERED TWICE!

 

Magento 2: Simplest XSD Valid UI Component
https://alanstorm.com/magento_2_simplest_xsd_valid_ui_component/

DISABLE THE SIMPLEUICOMPONENT FIRST:
php bin/magento module:disable Pulsestorm_SimpleUiComponent

CREATE A NE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_module Pulsestorm SimpleValidUiComponent 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/registration.php

CREATE ACL:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_acl Pulsestorm_SimpleValidUiComponent Pulsestorm_SimpleValidUiComponent::top,Pulsestorm_SimpleValidUiComponent::menu_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/acl.xml

CREATE A MENU:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_menu Pulsestorm_SimpleValidUiComponent Magento_Backend::system_other_settings Pulsestorm_SimpleValidUiComponent::a_menu_item Pulsestorm_SimpleValidUiComponent::menu_1 “Hello Simple Valid Ui Component” pulsestorm_simplevaliduicomponent/index/index 1
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/adminhtml/menu.xml
Done.

CREATE A ROUTE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_route Pulsestorm_SimpleValidUiComponent adminhtml pulsestorm_simplevaliduicomponent
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/adminhtml/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Controller/Adminhtml/Index/Index.php
Don’t forget your menu.xml and acl.xml
action=”pulsestorm_simplevaliduicomponent/index/index”
id=”Pulsestorm_SimpleValidUiComponent::pulsestorm_simplevaliduicomponent_menu

CREATE VIEW:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_view Pulsestorm_SimpleValidUiComponent adminhtml pulsestorm_simplevaliduicomponent_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/templates/content.phtml
Creating: Pulsestorm\SimpleValidUiComponent\Block\Adminhtml\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/layout/pulsestorm_simplevaliduicomponent_index_index.xml

ENABLE THE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_SimpleValidUiComponent && php bin/magento setup:upgrade

With the above in place, clear your cache, and you should be able to navigate to a System -> Other Settings -> Hello Simple Valid Ui Component menu in your Magento backend.

CLEAR THE CACHE AND RELOAD

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/layout/pulsestorm_simplevaliduicomponent_index_index.xml TO ADD ‘uiComponent’:

<referenceBlock name=”content”>
<block template=”content.phtml” class=”Pulsestorm\SimpleValidUiComponent\Block\Adminhtml\Main” name=”pulsestorm_simplevaliduicomponent_block_main”/>

<uiComponent name=”pulsestorm_simple_valid”/>

</referenceBlock>
….

then we’ll create an XML file for this named UI Component IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<?xml version=”1.0″?>
<pulsestorm_simple_valid xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
</pulsestorm_simple_valid>

 

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
</container>

MODIFY AGAIN TO ADD ‘dataSource’ NODE:
<container xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
<dataSource name=”pulsestorm_simple_valid_data_source”>
<argument name=”dataProvider” xsi:type=”configurableObject”>
<!– the PHP class that implements a data provider –>
<argument name=”class” xsi:type=”string”>Pulsestorm\SimpleValidUiComponent\Model\DataProvider</argument>

<!– redundant with the dataSource name –>
<argument name=”name” xsi:type=”string”>pulsestorm_simple_valid_data_source</argument>

<!– required: means ui components are meant to work with models –>
<argument name=”primaryFieldName” xsi:type=”string”>entity_id</argument>

<!– required: means ui components are meant to work with URL passing –>
<argument name=”requestFieldName” xsi:type=”string”>id</argument>
</argument>
</dataSource>
</container>

THEN add a new data provider class IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Model/DataProvider.php:
<?php
namespace Pulsestorm\SimpleValidUiComponent\Model;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
}

THEN CLEAR THE CACHE AND RELOAD

CHANGING TEMPLATE
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
<argument name=”data” xsi:type=”array”>
<item name=”template” xsi:type=”string”>templates/pulsestorm_simple_valid/default</item>
</argument>

<dataSource name=”pulsestorm_simple_valid_data_source”>

</dataSource>
</container>

THEN CREATE A XHTML FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/templates/pulsestorm_simple_valid/default.xhtml:
<div
data-bind=”scope: ‘{{getName()}}.{{getName()}}'”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:noNamespaceSchemaLocation=”../../../../../../Ui/etc/ui_template.xsd”>

<!– ko template: getTemplate() –><!– /ko –>
</div>

ADD an htmlContent component/node IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container …>

<htmlContent name=”our_first_content”>
<argument name=”block” xsi:type=”object”>Pulsestorm\SimpleValidUiComponent\Block\Example</argument>
</htmlContent>
</container>

THEN CREATE A PHP FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Block/Example.php:
<?php
namespace Pulsestorm\SimpleValidUiComponent\Block;

use Magento\Framework\View\Element\BlockInterface;

class Example extends \Magento\Framework\View\Element\AbstractBlock
{
public function toHtml()
{
return ‘<h1>Hello PHP Block Rendered in JS</h1>’;
}
}

OK. CLEAR THE CACHE AND RELOAD.
IT’D PRINT:
Magento Admin

This is my template, there are many like it, but this one is mine.
Hello PHP Block Rendered in JS

Hijacking htmlContent
THIS IS ANOTHER WAY TO RENDER TEMPLATE WITH A COMPONENT CLASS:
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container …>

<htmlContent class=”Pulsestorm\SimpleValidUiComponent\Component\Simple” name=”our_first_content”>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleValidUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
</htmlContent>
</container>

CREATE A COMPONENT FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Component/Simple.php:
<?php
namespace Pulsestorm\SimpleValidUiComponent\Component;
class Simple extends \Magento\Ui\Component\AbstractComponent
{
const NAME = ‘html_content_pulsestorm_simple’;
public function getComponentName()
{
return self::getName();
}
}

CREATE THE KNOCKOUT JS VIEW MODEL IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/web/js/pulsestorm_simple_component.js:
define([‘uiElement’,’ko’], function(Element, ko){
viewModelConstructor = Element.extend({
defaults: {
template: ‘Pulsestorm_SimpleValidUiComponent/pulsestorm_simple_template’
}
});

return viewModelConstructor;
});

THEN CREATE THE TEMPLATE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/web/template/pulsestorm_simple_template.html:
<h1>Our Remote Knockout Template!</h1>

THEN clear your cache and reload the page
IT’D PRINT:
Magento Admin

This is my template, there are many like it, but this one is mine.
Our Remote Knockout Template!

CONCLUSION SO FAR:

Magento uses Knockout.js to render front end interfaces.

By default, Knockout.js uses the entire HTML page as a view, and a javascript object for the view model.

To use Knockout.js, programmers create a javascript constructor function. Knockout.js uses this constructor function to instantiate a view model.

Magento added a custom Knockout.js binding named scope. Scope allows different areas of the page to use different view models.

These different view models are instantiated by the Magento_Ui/js/core/app RequireJS module. This module is embedded in the page via an x-magento-init script, and this module uses a large data structure rendered via the backend’s UI Component classes and XML. This data structure configures a number of RequireJS modules called “components”.

These components are “view model constructor factories”. The Magento_Ui/js/core/app application uses these RequireJS components to create view model constructors, and then uses the instantiated view model constructor function to instantiate view models. Finally, the Magento_Ui/js/core/app application registers each instantiated view model object, (by name), with the uiRegistry RequireJS module. The view model’s registered names come from the large data structure rendered via the backend’s UI Component classes and XML.

The view model constructor objects are based on a Magento built javascript object system. This object system uses RequireJS modules as classes, and uses underscore.js for inheritance and method/property sharing. There’s also some Magento secret sauce in there. The base class is the uiClass module. The uiElement class/module extends from the uiClass class/module. Most of Magento’s Knockout.js view model constructors are uiElement objects.

Above, we mentioned the uiRegistry, uiClass, and uiElement RequireJS modules. These are RequireJS “map aliases” that point to the real modules at Magento_Ui/js/lib/registry/registry, Magento_Ui/js/lib/core/class, and Magento_Ui/js/lib/core/element/element respectively.

Magento CE 2.2.2 (With Sample Data) Installation

I want to install Magento CE 2.2.2 (with sample data) in my machine MacOS High Sierra (10.13.2), PHP 7.0 and Apache2. For the installation on Ubuntu 16.04 with Nginx and PHP7.0-FPM, See after this.

  1. Download the installation file from magento website (https://magento.com/tech-resources/download). I downloaded the file with sample data in tar.bz2 format
  2. Extract the compressed file into your web root. I extract them in ‘magentoce222’ directory.
  3. Create a virtualhost
    Modify /usr/local/etc/httpd/extra/httpd-vhosts.conf. then add this:

    Save the file.
    Then modify /private/etc/hosts. Then insert this:

    Save the file.
    Then restart apache server

     
  4. Open the site on the browser: http://magentoce222.local/
    Follow the instruction (Agree the terms and condition, check the readiness, the database addition (create the database manually), web config, timezone (mine: western indonesia time (indonesia/jakarta)
    So here is the local config:

    SORRY, ONLY ADMIN CAN SHOW THIS!
    Then click ‘Install’ button.
    Success!
  5. When I opened the admin page, it need to be reindexed and the cache need to be cleared:
  6. On the frontpage, I got the grid for the products (hot sellers section) not good enough. not like on http://magentoce215.local/
  7. INSTALL MSP VIA COMPOSER:

    Enable it:

    run setup:upgrade

    Then enable it also in the admin page : Stores -> Configuration -> MAGESPECIALIST
    NOTE: I GOT THIS ERROR AFTER ENABLE IT:
    One or more integrations have been reset because of a change to their xml configs.
    SOLUTION: I NEED TO DISABLE AN EXTENSION:
    php bin/magento module:disable Shopial_Facebook
    REF: https://github.com/magento/magento2/issues/12095

The installation on Ubuntu 16.04 with Nginx and PHP7.0-FPM
ref: http://devdocs.magento.com/guides/v2.0/install-gde/prereq/nginx.html

  1. Download Magento 2.2.2 (with sample data)
  2. Create the config file

    Here is the content:
  3. Enable file config
  4. Register the host on my system

    Like this:
  5. CHECK THE NGINX SETTING AND RESTART IT:


     
  6. Set file permission and owner:

    Then

     
  7. Test: –> NOT WORKING! I GOT BLANK PAGE. MAY BE SOMETHING WRONG ON NGINX ‘magento222.test’ CONFIG ERROR. BUT WHERE?
    IT ALSO REALLY WORTH TO CHECK THE ERROR MESSAGE FROM /var/log/nginx/error.log
    OK. I FOUND THE SOLUTION (ref: https://github.com/magento/magento2/issues/2504). I CAN DO ONE OF THIS SOLUTION (THE LATTER IS PREFERRED):
    1. CHANGE ‘cgi.fix_pathinfo’ TO ‘1’ IN /etc/php/7.0/fpm/php.ini
    2. MODIFY THE CONFIG FILE IN /etc/nginx/sites-available/magento222.test THEN ADD ‘fastcgi_split_path_info ^(.+?\.php)(/.*)$;’ JUST BELOW/IN ‘location ~ ^/setup/index.php {‘. PLS SEE THE FIXED SETTING ABOVE –> PREFERRED. BECAUSE  THIS PROBLEM ONLY WHEN I TRIED TO SETUP FOR THE FIRST TIME.
    I ALSO GOT ‘connection timeout’ ERROR WHEN TRYING TO INSTALL IT. SO I ADDED A FEW MORE LINES ON ‘setup’ SECTION ON THE NGINX CONFIG LIKE THIS:

    ref: https://www.digitalocean.com/community/questions/nginx-php5-fpm-error-110-connection-timed-out
    MAY BE I NEED TO DO THE SAME ON THE ‘update’ SECTION???
    3. To enable Magento 2 profiler for nginx, pls add ‘fastcgi_param MAGE_PROFILER html;’ like this:

    NOTE: THE PROFILER WOULD SLOW THE PAGE LOAD!!!
    ref: https://magento.stackexchange.com/questions/192401/how-to-enable-profiler-on-nginx

    I HAVE TO USE APACHE TO INSTALL IT
    SORRY, ONLY ADMIN CAN SHOW THIS!

  8. Compile

     

    OR (BECAUSE I GOT ERROR: ‘Area code not set: Area code must be set before starting a session. … vendor/magento/framework/Session/SessionManager.php’)


    Make sure the php version for cli is php 7.0.x (php 7.0.x for magento 2.2.2), if not, pls change the php cli version:

    If you get an error like ‘Class Magento\Framework\App\ResourceConnection\Proxy does not exist’ on the cli and/or the browser, then you need to remove ‘generated’ directory first.

    then run the setup:upgrade and the other commands like usual
    I GOT ANOTHER ERROR:

    SO REMOVE SOME FILES MANUALLY:

    RUN THE DEPLOY COMMAND AGAIN!
  9. Test:  http://magento222.test/
    Admin page: http://magento222.test/admin_14p856

Magento 2 Alan Storm Tutorial

REF: http://alanstorm.com/category/magento-2/

SETTING VirtualHost
REF:https://medium.com/@JohnFoderaro/how-to-set-up-apache-in-macos-sierra-10-12- bca5a5dfffba
MODIFY /private/etc/apache2/extra/httpd-vhosts.conf:

<VirtualHost *:80>
ServerName magentoce215.lcoal
ServerAlias www.magentoce215.local
DocumentRoot “/Library/WebServer/Documents/Projects/magentoce215”
DirectoryIndex index.php
<Directory “/Library/WebServer/Documents/Projects/magentoce215”>
AllowOverride All
Allow from All
Require all granted
</Directory>

ErrorLog “/private/var/log/apache2/magentoce215_error.log”
CustomLog “/private/var/log/apache2/magentoce215_access.log” common
</VirtualHost>

MODIFY /etc/hosts:

127.0.0.1 magentoce215.local

RESTART APACHE: sudo apachectl restart

OPEN http://magentoce215.local/

INSTALL PESTLE (https://github.com/astorm/pestle)
Satrias-MacBook-Pro:~ teddy$ curl -LO http://pestle.pulsestorm.net/pestle.phar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3990k 100 3990k 0 0 578k 0 0:00:06 0:00:06 –:–:– 860k
Satrias-MacBook-Pro:~ teddy$ php pestle.phar list-commands

GO TO THE M2 ROOT PROJECT (/Library/WebServer/Documents/Projects/magentoce215/)
Satrias-MacBook-Pro:~ teddy$ cd /Library/WebServer/Documents/Projects/magentoce215/

https://alanstorm.com/magento_2_javascript_init_scripts/
GO TO ‘app/code’ DIR: –> NO NEED. JUST PESTLE.PHAR IN MAGENTO ROOT IS OKAY
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/

THEN INSTALL PESTLE:
Satrias-MacBook-Pro:code teddy$ curl -LO http://pestle.pulsestorm.net/pestle.phar
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 3990k 100 3990k 0 0 860k 0 0:00:04 0:00:04 –:–:– 978k

THEN RUN ‘php pestle.phar generate_module Pulsestorm JavascriptInitTutorial 0.0.1’
I HAVE TO USE ‘php’ HERE BECAUSE IF NOT I’D GET AN ERROR MESSAGE ‘-bash: pestle.phar: command not found’ REF:https://github.com/astorm/pestle/issues/120

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm JavascriptInitTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/registration.php

HERE ARE THE GENERATED FILES:
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/registration.php:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
‘Pulsestorm_JavascriptInitTutorial’,
__DIR__
);

/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/module.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:Module/etc/module.xsd”>
<module name=”Pulsestorm_JavascriptInitTutorial” setup_version=”0.0.1″/>
</config>

THEN
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_JavascriptInitTutorial frontend pulsestorm_javascriptinittutorial
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/Controller/Index/Index.php

HERE ARE THE GENERATED FILES:
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/etc/frontend/routes.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:App/etc/routes.xsd”>
<router id=”standard”>
<route id=”pulsestorm_javascriptinittutorial” frontName=”pulsestorm_javascriptinittutorial”>
<module name=”Pulsestorm_JavascriptInitTutorial”/>
</route>
</router>
</config>

AND
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/Controller/Index/Index.php:
<?php
namespace Pulsestorm\JavascriptInitTutorial\Controller\Index;
class Index extends \Magento\Framework\App\Action\Action
{

protected $resultPageFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $resultPageFactory)
{
$this->resultPageFactory = $resultPageFactory;
parent::__construct($context);
}

public function execute()
{
return $this->resultPageFactory->create();
}
}

 

THEN
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_JavascriptInitTutorial frontend pulsestorm_javascriptinittutorial_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml
Creating: Pulsestorm\JavascriptInitTutorial\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/layout/pulsestorm_javascriptinittutorial_index_index.xml

HERE ARE THE GENERATED FILES:
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<h1>This is my template, there are many like it, but this one is mine.</h1>

AND
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/layout/pulsestorm_javascriptinittutorial_index_index.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<referenceBlock name=”content”><block template=”content.phtml” class=”Pulsestorm\JavascriptInitTutorial\Block\Main” name=”pulsestorm_javascriptinittutorial_block_main”/></referenceBlock></page>

AND
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/Block/Main.php:
<?php
namespace Pulsestorm\JavascriptInitTutorial\Block;
class Main extends \Magento\Framework\View\Element\Template
{
function _prepareLayout(){}
}

 

THEN I HAVE TO GO UP THE MAGENTO ROOT THEN LOGIN AS ‘sudo -s -u _www’:
Satrias-MacBook-Pro:code teddy$ php bin/magento module:enable Pulsestorm_JavascriptInitTutorial
Could not open input file: bin/magento
Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_JavascriptInitTutorial
Command line user does not have read and write permissions on var/generation directory. Please address this issue before using Magento command line.
Satrias-MacBook-Pro:magentoce215 teddy$ sudo -s -u _www
Password:
bash-3.2$ php bin/magento module:enable Pulsestorm_JavascriptInitTutorial
The following modules have been enabled:
– Pulsestorm_JavascriptInitTutorial

To make sure that the enabled modules are properly registered, run ‘setup:upgrade’.
Cache cleared successfully.
Generated classes cleared successfully. Please run the ‘setup:di:compile’ command to generate classes.
Info: Some modules might require static view files to be cleared. To do this, run ‘module:enable’ with the –clear-static-content option to clear them.

THEN THE LAST:
bash-3.2$ php bin/magento setup:upgrade

TEST THE ROUTE URL: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D PRINT:
‘This is my template, there are many like it, but this one is mine.’

Setting up a RequireJS Module
CREATE A NEW FILE: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:
define([],function(){
alert(“A simple RequireJS Module”);
return {};
});

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<h1>This is my template, there are many like it, but this one is mine.</h1>

<script type=”text/javascript”>
requirejs([‘Pulsestorm_JavascriptInitTutorial/example’], function(example){
alert(‘Loaded!’);
console.log(example);
});
</script>

RUN: php bin/magento c:f
THEN TEST AGAIN: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D WORK AS EXPECTED. THE TWO ALERT “A simple RequireJS Module” THEN ‘Loaded!’ WOULD BE POPED UP. ALSO THE CONSOLE WOULD PRINT ‘{}’

X-Magento-Init
PURPOSES:
provides a way to pass that program a server side generated JSON object.
provides a way to provide that program with the DOM nodes it should operate on.

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<!–h1>This is my template, there are many like it, but this one is mine.</h1–>

<!–script type=”text/javascript”>
requirejs([‘Pulsestorm_JavascriptInitTutorial/example’], function(example){
alert(‘Loaded!’);
console.log(example);
});
</script–>

<div id=”one” class=”foo”>
Hello World
</div>
<div id=”two” class=”foo”>
Goodbye World
</div>

<script type=”text/x-magento-init”>
{
“*”: {
“Pulsestorm_JavascriptInitTutorial/example”:{}
}
}
</script>

RUN: php bin/magento c:f
THEN TEST AGAIN: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D SHOW ALERT “A simple RequireJS Module”
BUT THEN I GOT AN ERROR:
REFER TO: http://magentoce215.local/pub/static/version1513154325/frontend/Magento/luma/en_US/mage/apply/main.js
Uncaught TypeError: Cannot read property ‘bind’ of undefined
at main.js:26
at Object.execCb (require.js:1650)
at Module.check (require.js:866)
at Module.<anonymous> (require.js:1113)
at require.js:132
at require.js:1156
at each (require.js:57)
at Module.emit (require.js:1155)
at Module.check (require.js:917)
at Module.enable (require.js:1143)
SOLUTION: ‘The reason for this error? Because there’s no mage/menu key in the returned object.’
REF: https://alanstorm.com/requirejs-modules-that-return-two-widgets/
SO JUST FOLLOW BELOW ‘Magento Javascript Components’!

Magento Javascript Components
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:
/*
define([],function(){
alert(“A simple RequireJS Module”);
return {};
});
*/
define([], function () {
var mageJsComponent = function()
{
alert(“A simple magento component.”);
};

return mageJsComponent;
});

RUN: CLEAR CACHE
THEN RELOAD: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D SHOW THE ALERT “A simple magento component.”
ALSO THE ABOVE CONSOLE ERROR WOULD gone

WE CAN PASS PARAMETER TO THE REQUIREJS MODULE/COMPONENT (pass in server side generated JSON –> A SAMPLE FOR ‘provides a way to pass that program a server side generated JSON object.’)
FOR EXAMPLE PASS A PAIR KEY-VALUE PARAM ‘config’:’value’:
MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:

<script type=”text/x-magento-init”>
{
“*”: {
“Pulsestorm_JavascriptInitTutorial/example”:{“config”:”value”}
}
}
</script>

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:

define([], function () {
var mageJsComponent = function(config)
{
//alert(“A simple magento component.”);
alert(“Look in your browser’s console”);
console.log(config);
};

return mageJsComponent;
});

RELOAD THE BROWSER!
CONSOLE PRINTED:
{config: “value”}
config:”value”
__proto__:Object

HERE IS A SAMPLE FOR ‘provides a way to provide that program with the DOM nodes it should operate on.’:
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/web/example.js:
define([], function () {
var mageJsComponent = function(config, node)
{
//alert(“A simple magento component.”);
//alert(“Look in your browser’s console”);
console.log(config);
console.log(node);
};

return mageJsComponent;
});

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<div id=”one” class=”foo”>
Hello World
</div>
<div id=”two” class=”foo”>
Goodbye World
</div>

<script type=”text/x-magento-init”>
{
“#one”:{
“Pulsestorm_JavascriptInitTutorial/example”:{“config”:”value”}
}
}
</script>

THEN CLEAR CACHE
AND RELOAD: http://magentoce215.local/pulsestorm_javascriptinittutorial/
IT’D PRINT THE OUTPUT ON CONSOLE:
{config: “value”}
example.js:13 <div id=​”one” class=​”foo” data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​
Hello World
​</div>​

OR IF
<script type=”text/x-magento-init”>
{
“.foo”:{
“Pulsestorm_JavascriptInitTutorial/example”:{“config”:”value”}
}
}
</script>

THE OUTPUT CONSOLE WOULD BE:
{config: “value”}
example.js:13 <div id=​”one” class=​”foo” data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​
Hello World
​</div>​
example.js:12 {config: “value”}
example.js:13 <div id=​”two” class=​”foo” data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​
Goodbye World
​</div>​

 

Data-mage-init Attribute

In addition to <script type=”text/x-magento-init”>, there’s another way to invoke similar functionality on a specific DOM node, and that’s with the data-mage-init attribute.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptInitTutorial/view/frontend/templates/content.phtml:
<div data-mage-init='{“Pulsestorm_JavascriptInitTutorial/example”: {“another”:”example”}}’>A single div</div>

THEN CLEAR THE CACHE
AND RELOAD.
HERE IS THE CONSOLE PRINTED:
{another: “example”}
example.js:13 <div data-mspdevtools=​”e076e2cbb07c8dc89e933bef9d185479″>​A single div​</div>​

KnockoutJS Primer for Magento Developers
https://alanstorm.com/knockoutjs_primer_for_magento_developers/
JUST AN INTRODUCTION

Magento 2: KnockoutJS Integration
https://alanstorm.com/magento_2_knockoutjs_integration/

Creating a Magento Module
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm KnockoutTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_KnockoutTutorial frontend pulsestorm_knockouttutorial
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/Controller/Index/Index.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_KnockoutTutorial frontend pulsestorm_knockouttutorial_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/templates/content.phtml
Creating: Pulsestorm\KnockoutTutorial\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/layout/pulsestorm_knockouttutorial_index_index.xml

Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_KnockoutTutorial
The following modules have been enabled:
– Pulsestorm_KnockoutTutorial

To make sure that the enabled modules are properly registered, run ‘setup:upgrade’.
Cache cleared successfully.
Generated classes cleared successfully. Please run the ‘setup:di:compile’ command to generate classes.
Info: Some modules might require static view files to be cleared. To do this, run ‘module:enable’ with the –clear-static-content option to clear them.
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento setup:upgrade

Module ‘Pulsestorm_KnockoutTutorial’:
Please re-run Magento compile command

TEST: http://magentoce215.local/pulsestorm_knockouttutorial

NOTE: I NEED TO DISABLE Inchoo_ModalOverlay MODULE BECAUSE IT’S ANNOYING TO SHOW THE POPUP EACH TIME I REFRESH THE BROWSER! PROBABLY I NEED TO WRITE A TUTORIAL HOW TO WRITE THIS KIND OF MODULE (SHOW THE POPUP ON EACH PAGE)

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/templates/content.phtml:
<!–h1>This is my template, there are many like it, but this one is mine.</h1–>
<div data-bind=”template:’Pulsestorm_KnockoutTutorial/hello'”></div>

THEN ADD A NEW FILE hello.html IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/KnockoutTutorial/view/frontend/web/template/hello.html:
<p data-bind=”style:{fontSize:’24px’}”>Hello World</p>

CLEAR CACHE AND RELOAD.
IT’D PRINT ‘Hello World’

The Curious Case of Magento 2 Mixins
https://alanstorm.com/the-curious-case-of-magento-2-mixins/

Magento 2 RequireJS Mixins
A Magento 2 RequireJS “mixin” allows you to programmatically listen for the initial instantiation of any RequireJS module and manipulate that module before returning it.

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm RequireJsRewrite 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/registration.php

Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_RequireJsRewrite && php bin/magento setup:upgrade

CREATE A NEW FILE ‘requirejs-config.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/view/base/requirejs-config.js:
var config = {
‘config’:{
‘mixins’:{
‘Magento_Customer/js/view/customer’:{
‘Pulsestorm_RequireJsRewrite/hook’:true
}
}
}
};

THEN CREATE A NEW FILE ‘hook.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RequireJsRewrite/view/base/web/hook.js:
define([], function(){
‘use strict’;
console.log(“Called this hook.”);
return function(targetModule){
targetModule.crazyPropertyAddedHere = ‘yes’;
return targetModule;
};
});

CLEAR THE CACHE THE TEST IT ON the Magento homepage (or any page which uses the Magento_Customer/js/view/customer RequireJS module): http://magentoce215.local/
IT’D PRINT ON THE CONSOLE: “Called this hook.”
Also, if you examine the Magento_Customer/js/view/customer module via the console, you’ll see it has an extra crazyPropertyAddedHere property:
module = requirejs(“Magento_Customer/js/view/customer”);
ƒ () {
var obj = this;

if (!_.isObject(obj) || Object.getPrototypeOf(obj) !== UiClass.prototype) {
obj = Object.create(UiClass.prototype);

console.log(module.crazyPropertyAddedHere);
VM2475:1 yes

With the above code, we changed the object returned by the Magento_Customer/js/view/customer module. If used judiciously, this is an incredibly powerful feature.

Class Rewrites for Javascript

 

Knockout Observables for Javascript Programmers
https://alanstorm.com/knockout-observables-for-javascript-programmers/

Important: Subscribers are only called when a value changes. If you pass in the observable’s current value, Knockout will not call subscriber callbacks

 

Modifying a jQuery Widget in Magento 2
https://alanstorm.com/modifying-a-jquery-widget-in-magento-2/

Creating our Mixin
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm Logdropdown 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/registration.php

CREATE A NEW FILE ‘requirejs-config.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/view/base/requirejs-config.js:
var config = {
‘config’:{
‘mixins’:{
‘mage/dropdown’:{
‘Pulsestorm_Logdropdown/js/dropdown-mixin’:true
}
}
}
};

THEN CREATE A REQUIREJS MODULE ‘dropdown-mixin.js’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/view/base/web/js/dropdown-mixin.js:
define([‘jquery’], function($){
return function(originalWidget){
alert(‘Our mixin is hooked up.’);
console.log(‘Our mixin is hooked up.’);
console.log(originalWidget);

return originalWidget;
};
});

THEN ENABLE THE MODULE:
Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_Logdropdown && php bin/magento setup:upgrade

LOAD ON ANY PAGE that uses the dropdownWidget widget (home page, catalog listing page, etc), and you should see an alert and a console.log message that says Our mixin is hooked up.

ƒ ( options, element ) {
// allow instantiation without “new” keyword
if ( !this._createWidget ) {
return new constructor( options, element );
}

// allow instantiation without initializing …

Changing a Widget
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/Logdropdown/view/base/web/js/dropdown-mixin.js:
define([‘jquery’], function($){
return function(originalWidget){
/*alert(‘Our mixin is hooked up.’);
console.log(‘Our mixin is hooked up.’);
console.log(originalWidget);

return originalWidget;*/
// if you want to get fancy and pull the widget namespace
// and name from the returned widget definition
// var widgetFullName = originalWidget.prototype.namespace +
// ‘.’ +
// originalWidget.prototype.widgetName;

 

$.widget(
‘mage.dropdownDialog’, //named widget we’re redefining

//$.mage.dropdownDialog
$[‘mage’][‘dropdownDialog’], //widget definition to use as
//a “parent” definition — in
//this case the original widget
//definition, accessed using
//bracket syntax instead of
//dot syntax

{ //the new methods
open:function(){
//our new code here
console.log(“I opened a dropdown!”);

//call parent open for original functionality
return this._super();

}
});

//return the redefined widget for data-mage-init
//jQuery.mage.dropdownDialog
return $[‘mage’][‘dropdownDialog’];
};
});

With the above in place, clear your browser cache and reload the page. Then, click on any dropdown widget on the page — the currency/store-views are good candidates

After clicking on these menus and confirming everything still works, take a look at your javascript console — you should see the I opened a dropdown! text successfully logged.

 

Introduction to Magento 2 — No More MVC
https://alanstorm.com/magento_2_mvvm_mvc/

CREATE A NEW MODULE ‘HelloWorldMVVM’:
CREATE A NEW FILE ‘registration.php’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/registration.php:
<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
‘Pulsestorm_HelloWorldMVVM’,
__DIR__
);

CREATE A NEW FILE ‘module.xml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/etc/module.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd”>
<module name=”Pulsestorm_HelloWorldMVVM” setup_version=”0.0.1″ />
</config>

ENABLE THE MODULE: Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_HelloWorldMVVM && php bin/magento setup:upgrade

CREATE A NEW FRONTEND ROUTE ‘routes.xml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/etc/frontend/routes.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”../../../../../../lib/internal/Magento/Framework/App/etc/routes.xsd”>
<router id=”standard”>
<route id=”hello_mvvm” frontName=”hello_mvvm”>
<module name=”Pulsestorm_HelloWorldMVVM” />
</route>
</router>
</config>

CREATE A NEW CONTROLLER ‘Hello/World.php’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:
<?php
namespace Pulsestorm\HelloWorldMVVM\Controller\Hello;

class World extends \Magento\Framework\App\Action\Action {
public function execute(){
echo ‘You Did it!’;
var_dump(__METHOD__);
}
}

TEST THE ROUTE BY OPENING: http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT:
You Did it!
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:7:string ‘Pulsestorm\HelloWorldMVVM\Controller\Hello\World::execute’ (length=57)

 

Passing off to the View
MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:
<?php
namespace Pulsestorm\HelloWorldMVVM\Controller\Hello;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\App\Action\Context;

class World extends \Magento\Framework\App\Action\Action
{
protected $pageFactory;
public function __construct(Context $context, PageFactory $pageFactory)
{
$this->pageFactory = $pageFactory;
return parent::__construct($context);
}

public function execute()
{
var_dump(__METHOD__);
$page_object = $this->pageFactory->create();
return $page_object;
}
}

BUT I GOT THIS ERROR ON RELOADING: http://magentoce215.local/hello_mvvm/hello/world
Fatal error: Uncaught TypeError: Argument 2 passed to Pulsestorm\HelloWorldMVVM\Controller\Hello\World::__construct() must be an instance of Magento\Framework\View\Result\PageFactory, none given, called in /Library/WebServer/Documents/Projects/magentoce215/var/generation/Pulsestorm/HelloWorldMVVM/Controller/Hello/World/Interceptor.php on line 14 and defined in /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php on line 9
( ! ) TypeError: Argument 2 passed to Pulsestorm\HelloWorldMVVM\Controller\Hello\World::__construct() must be an instance of Magento\Framework\View\Result\PageFactory, none given, called in /Library/WebServer/Documents/Projects/magentoce215/var/generation/Pulsestorm/HelloWorldMVVM/Controller/Hello/World/Interceptor.php on line 14 in /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php on line 9
SOLUTION: I NEED TO REMOVE THE var/generation DIRECTORY!!! CLEAR THE CACHE IS NOT ENOUGH!!!
Satrias-MacBook-Pro:magentoce215 teddy$ sudo rm -rf var/*
Password:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento c:f

HERE IS THE OUTPUT: (NO CONTENT YET) http://magentoce215.local/hello_mvvm/hello/world
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Controller/Hello/World.php:17:string ‘Pulsestorm\HelloWorldMVVM\Controller\Hello\World::execute’ (length=57)

Creating the View
ADD A NEW LAYOUT ‘hello_mvvm_hello_world.xml’ (THIS FILENAME IS FULL ACTION NAME. THE COMBINATION FROM frontName/ID: hello_mvvm AND CONTROLLER & CLASS NAME: hello_world) IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/layout/hello_mvvm_hello_world.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd”>
<referenceBlock name=”content”>
<block
template=”content.phtml”
class=”Pulsestorm\HelloWorldMVVM\Block\Main”
name=”pulsestorm_helloworld_mvvm”/>
</referenceBlock>
</page>

CREATE A BLOCK FILE ‘Main.php’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php:
<?php
namespace Pulsestorm\HelloWorldMVVM\Block;
use Magento\Framework\View\Element\Template;

class Main extends Template
{
protected function _prepareLayout()
{

}
}

THEN CREATE A TEMPLATE FILE ‘content.phtml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1>Hello World</h1>

CLEAR THE CACHE AND RELOAD! http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT ‘Hello World’ WITH THE MAGENTO LUMA TEMPLATE

View/View Model
MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php: –> USE SET/GET METHOD

protected function _prepareLayout()
{
$this->setMessage(‘Hello Again World’);
}

THEN CALL IT FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1><?php echo $this->escapeHtml($this->getMessage()); ?></h1>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT: “Hello Again World”

OR MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php. THEN ADD A NEW FUNCTION ‘getGoodbyeMessage’:

public function getGoodbyeMessage()
{
return ‘Goodbye World’;
}

CALL IT FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1><?php echo $this->escapeHtml($this->getGoodbyeMessage()); ?></h1>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/hello_mvvm/hello/world
IT’D PRINT: Goodbye World

USE PARAMS. FOR EXAMPLE WITH URL: http://magentoce215.local/hello_mvvm/hello/world/name/satria
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/Block/Main.php:

protected function _prepareLayout()
{
$this->setMessage(‘Hello Again World’);
$this->setName($this->getRequest()->getParam(‘name’));
}

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloWorldMVVM/view/frontend/templates/content.phtml:
<h1>
<?php echo $this->escapeHtml($this->getMessage()); ?>
<?php echo $this->escapeHtml($this->getName()); ?>
</h1>

<h2><?php echo $this->escapeHtml($this->getGoodbyeMessage()); ?></h2>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/hello_mvvm/hello/world/name/satria
IT’D PRINT:
Hello Again World satria
Goodbye World

 

Magento 2: Adding Frontend Assets via Layout XML
https://alanstorm.com/magento_2_javascript_css_layout_woes/

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm JavascriptCssExample 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_JavascriptCssExample frontend pulsestorm_javascriptcssexample
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/Controller/Index/Index.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_JavascriptCssExample frontend pulsestorm_javascriptcssexample_index_index Main content.phtml
Layout (ignored for adminhtml) ? (1column)]
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/templates/content.phtml
Creating: Pulsestorm\JavascriptCssExample\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/layout/pulsestorm_javascriptcssexample_index_index.xml

 

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_JavascriptCssExample && php bin/magento setup:upgrade

TEST IT ON http://magentoce215.local/pulsestorm_javascriptcssexample

MODIFY TO ADD JS AND CSS ON /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/layout/pulsestorm_javascriptcssexample_index_index.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<head>
<css src=”Pulsestorm_JavascriptCssExample::test.css”/>
<link src=”Pulsestorm_JavascriptCssExample::test.js”/>
</head>
<referenceBlock name=”content”><block template=”content.phtml” class=”Pulsestorm\JavascriptCssExample\Block\Main” name=”pulsestorm_javascriptcssexample_block_main”/></referenceBlock></page>

ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/web/test.js:
alert(“Hello”);

THEN ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/web/test.js:
body{
background-color:#f00;
}

CLEAR CACHE AND RELOAD: http://magentoce215.local/pulsestorm_javascriptcssexample
IT’S SHOW ‘Hello’ AND THE BG COLOR WOULD BE CHANGED TO RED

Adding Files Via PHP
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/layout/pulsestorm_javascriptcssexample_index_index.xml:
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” layout=”1column” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<head>
<css src=”Pulsestorm_JavascriptCssExample::test.css”/>
<link src=”Pulsestorm_JavascriptCssExample::test.js”/>
</head>
<referenceBlock name=”content”>
<block template=”content.phtml”
class=”Pulsestorm\JavascriptCssExample\Block\Main”
name=”pulsestorm_javascriptcssexample_block_main”/>
</referenceBlock>
<referenceBlock name=”head.additional”>
<block template=”head.phtml”
class=”Pulsestorm\JavascriptCssExample\Block\Head”
name=”pulsestorm_javascriptcssexample_block_head” />
</referenceBlock>
</page>

ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/Block/Head.php:
<?php
namespace Pulsestorm\JavascriptCssExample\Block;
class Head extends \Magento\Framework\View\Element\Template
{

}

THEN ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/templates/head.phtml:
<!– Hello There –>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/pulsestorm_javascriptcssexample
THEN IT’D PRINT ‘<!– Hello There –>’ IN ‘head.additional’ BLOCK

The Asset Repository
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/Block/Head.php:
<?php
namespace Pulsestorm\JavascriptCssExample\Block;
class Head extends \Magento\Framework\View\Element\Template
{
public $assetRepository;
public function __construct(
\Magento\Framework\View\Element\Template\Context $context,
array $data = [],
\Magento\Framework\View\Asset\Repository $assetRepository
)
{
$this->assetRepository = $assetRepository;
return parent::__construct($context, $data);
}
}

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/JavascriptCssExample/view/frontend/templates/head.phtml:
@highlightsyntax@php
<?php
$asset_repository = $this->assetRepository;
$asset = $asset_repository->createAsset(‘Pulsestorm_JavascriptCssExample::test.js’);
$url = $asset->getUrl();
?>
<!– Hello There –>
<script src=”<?php echo $url; ?>”></script>

CLEAR THE CACHE AND RELOAD: http://magentoce215.local/pulsestorm_javascriptcssexample
THEN IT’D PRINT ‘<!– Hello There –>’ IN ‘head.additional’ BLOCK THEN CREATE A SCRIPT:
<script src=”http://magentoce215.local/pub/static/version1513654716/frontend/Magento/luma/en_US/Pulsestorm_JavascriptCssExample/test.js”></script>

 

Magento 2: CRUD Models for Database Access
https://alanstorm.com/magento_2_crud_models_for_database_access/

Creating a Base Module
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm ToDoCrud 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route Pulsestorm_ToDoCrud frontend pulsestorm_todocrud
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/etc/frontend/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Controller/Index/Index.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_view Pulsestorm_ToDoCrud frontend pulsestorm_todocrud_index_index Main content.phtml
Layout (ignored for adminhtml) ? (1column)]
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/frontend/templates/content.phtml
Creating: Pulsestorm\ToDoCrud\Block\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/frontend/layout/pulsestorm_todocrud_index_index.xml

Generating Crud Files
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_crud_model Pulsestorm_ToDoCrud TodoItem
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Api/TodoItemRepositoryInterface.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/TodoItemRepository.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Api/Data/TodoItemInterface.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/ResourceModel/TodoItem/Collection.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/ResourceModel/TodoItem.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Model/TodoItem.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Setup/InstallSchema.php
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Setup/InstallData.php

Satrias-MacBook-Pro:code teddy$ cd ..
Satrias-MacBook-Pro:app teddy$ cd ..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_ToDoCrud && php bin/magento setup:upgrade

TEST IT: http://magentoce215.local/pulsestorm_todocrud

Magento 2 Factory Objects
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Block/Main.php:
<?php
namespace Pulsestorm\ToDoCrud\Block;

use Magento\Framework\View\Element\Template\Context;
use Pulsestorm\ToDoCrud\Model\TodoItemFactory;

class Main extends \Magento\Framework\View\Element\Template
{
protected $todoFactory;

public function __construct(Context $context, TodoItemFactory $todoFactory){
$this->todoFactory = $todoFactory;
parent::__construct($context);
}

function _prepareLayout(){
//var_dump(“I’m here”);
var_dump(get_class($this->todoFactory));
exit;
}
}

CLEAR THE CACHE (IF NEEDED CLEAR var/* DIR) THEN RELOAD: http://magentoce215.local/pulsestorm_todocrud
IT’D PRINT: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Block/Main.php:18:string ‘Pulsestorm\ToDoCrud\Model\TodoItemFactory’ (length=41)

MODIFY AGAIN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/Block/Main.php:

function _prepareLayout(){
//var_dump(“I’m here”);
//var_dump(get_class($this->todoFactory));
$todo = $this->todoFactory->create();
$todo->setData(‘item_text’,’Finish my Magento article’)
->save();
var_dump(‘Done’);
exit;
}

CLEAR CACHE & RELOAD: http://magentoce215.local/pulsestorm_todocrud

CHECK THE TABLE IN PHPMYADMIN:
select * from pulsestorm_todocrud_todoitem

_prepareLayout() function could be:

function _prepareLayout(){
//var_dump(“I’m here”);
//var_dump(get_class($this->todoFactory));
$todo = $this->todoFactory->create();
$collection = $todo->getCollection();
//$todo->setData(‘item_text’,’Finish my Magento article’)
//->save();
//var_dump(‘Done’);
//$todo = $todo->load(1);
//var_dump($todo->getData());
foreach($collection as $item){
var_dump(“Item ID:”.$item->getId());
var_dump($item->getData());
}
exit;
}

 

Magento 2: Understanding Object Repositories
https://alanstorm.com/magento_2_understanding_object_repositories/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm RepositoryTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_command Pulsestorm_RepositoryTutorial Examples
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_RepositoryTutorial && php bin/magento setup:upgrade

TEST THE COMMAND FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/Command/Examples.php:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Hello World

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/RepositoryTutorial/Command/Examples.php:

use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\App\State;

class Examples extends Command
{
protected $objectManager;

public function __construct(ObjectManagerInterface $objectManager, State $appState, $name = null){
$this->objectManager = $objectManager;
$appState->setAreaCode(‘frontend’);
parent::__construct($name);
}

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
$page = $repo->getById(2);
$output->writeln(get_class($page));
}
}

TEST THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Magento\Catalog\Model\Product\Interceptor

WE CAN GET THE PRODUCT NAME:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
$page = $repo->getById(2);
//$output->writeln(get_class($page));
//$output->writeln($page->getTitle()); //EMPTY!!!
$output->writeln($page->getName());
}

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Strive Shoulder Pack


protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
$page = $repo->getById(2);
//$output->writeln(get_class($page));
//$output->writeln($page->getTitle()); //EMPTY!!!
//$output->writeln($page->getName());
/*$page->setTitle($page->getTitle().”, Edited by code”);
$repo->save($page);
$output->writeln($page->getTitle());*/
$page->setId(null);
$page->setTitle(“My duplicated page”);
$repo->save($page);
$output->writeln($page->getId());
$output->writeln($page->getTitle());
}

BUT I GOT AN ERROR:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples

 

[Magento\Framework\Exception\AlreadyExistsException]
URL key for specified store already exists.

 

ps:examples

SEARCH CRITERIA
MODIFY

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Joust Duffle Bag
Strive Shoulder Pack
Crown Summit Backpack
….

MODIFY TO GET ALL PRODUCT CONTAIN/END WITH NAME ‘backpack’:

protected function execute(InputInterface $input, OutputInterface $output)
{
//create a filter
$filter = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter->setData(‘field’, ‘name’);
$filter->setData(‘value’, ‘%backpack’);
$filter->setData(‘condition_type’, ‘like’);

//add the filter to a group
$filter_group = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group->setData(‘filters’, [$filter]);

//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);
//add the filter group to the search criteria object
$search_criteria->setFilterGroups([$filter_group]);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}
….

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Crown Summit Backpack
Fusion Backpack
Endeavor Daytrip Backpack
Driven Backpack

ADD ANOTHER FILTER (WOULD CREATE ‘OR’ JOIN):

protected function execute(InputInterface $input, OutputInterface $output)
{
//create a filter
$filter = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter->setData(‘field’, ‘name’);
$filter->setData(‘value’, ‘%backpack’);
$filter->setData(‘condition_type’, ‘like’);

//create another filter
$filter2 = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter2->setData(‘field’, ‘name’);
$filter2->setData(‘value’, ‘%sprite%’);
$filter2->setData(‘condition_type’, ‘like’);

//add the filter to a group
$filter_group = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group->setData(‘filters’, [$filter, $filter2]);

//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);
//add the filter group to the search criteria object
$search_criteria->setFilterGroups([$filter_group]);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Crown Summit Backpack
Fusion Backpack
Endeavor Daytrip Backpack
Driven Backpack
Sprite Foam Yoga Brick
Sprite Foam Roller
Sprite Stasis Ball 55 cm
Sprite Stasis Ball 55 cm
Sprite Stasis Ball 55 cm
Sprite Stasis Ball 65 cm
Sprite Stasis Ball 65 cm
Sprite Stasis Ball 65 cm
Sprite Stasis Ball 75 cm
Sprite Stasis Ball 75 cm
Sprite Stasis Ball 75 cm
Sprite Yoga Strap 6 foot
Sprite Yoga Strap 8 foot
Sprite Yoga Strap 10 foot
Sprite Yoga Companion Kit
Set of Sprite Yoga Straps

ADD ANOTHER FILTER GROUP (WOULD CREATE ‘AND’ JOIN):

protected function execute(InputInterface $input, OutputInterface $output)
{
//create a filter
$filter = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter->setData(‘field’, ‘name’);
$filter->setData(‘value’, ‘%sport%’);
$filter->setData(‘condition_type’, ‘like’);

//create another filter
$filter2 = $this->objectManager->create(‘Magento\Framework\Api\Filter’);
$filter2->setData(‘field’, ‘name’);
$filter2->setData(‘value’, ‘%black%’);
$filter2->setData(‘condition_type’, ‘like’);

//add the filter to a group
$filter_group = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group->setData(‘filters’, [$filter]);

//add the filter2 to another group
$filter_group2 = $this->objectManager->create(‘Magento\Framework\Api\Search\FilterGroup’);
$filter_group2->setData(‘filters’, [$filter2]);

//$output->writeln(“Hello World”);
$repo = $this->objectManager->get(‘Magento\Catalog\Model\ProductRepository’);
//$page = $repo->getById(2);
$search_criteria = $this->objectManager->create(‘Magento\Framework\Api\SearchCriteriaInterface’);
//add the filter group to the search criteria object
$search_criteria->setFilterGroups([$filter_group, $filter_group2]);

$result = $repo->getList($search_criteria);
$products = $result->getItems();

foreach($products as $item){
$output->writeln($item->getName());
}
}

TEST:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:examples
Supernova Sport Pant-32-Black
Supernova Sport Pant-33-Black
Supernova Sport Pant-34-Black
Supernova Sport Pant-36-Black
Rapha Sports Short-32-Black
Rapha Sports Short-33-Black
Rapha Sports Short-34-Black
Rapha Sports Short-36-Black

 

Helper Class with Dependency Injection

 

Magento 2: Understanding Access Control List Rules
https://alanstorm.com/magento_2_understanding_access_control_list_rules/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm AclExample 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/registration.php

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_AclExample && php bin/magento setup:upgrade

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_acl Pulsestorm_AclExample Pulsestorm_AclExample::top,Pulsestorm_AclExample::config
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/etc/acl.xml

CREATED /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/AclExample/etc/acl.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:Acl/etc/acl.xsd”>
<acl>
<resources>
<resource id=”Magento_Backend::admin”>
<resource id=”Pulsestorm_AclExample::top” title=”Pulse Storm ACL Example Module”>
<resource id=”Pulsestorm_AclExample::config” title=”The First Rule”/>
<resource id=”Pulsestorm_AclExample::more_rules” title=”The Second Rule”/>
</resource>
</resource>
</resources>
</acl>
</config>

take a look at the Roles menu at System -> User Roles -> Add/Edit Role -> Role Resources. You should see your rules added to the system

 

Magento 2: Admin Menu Items
https://alanstorm.com/magento_2_admin_menu_items/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm MenuTutorial 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/registration.php

Satrias-MacBook-Pro:code teddy$ cd ../..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_MenuTutorial && php bin/magento setup:upgrade

ADD /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/adminhtml/menu.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Backend:etc/menu.xsd”>
<menu>
<add id=”Pulsestorm_MenuTutorial::top_level_example”
title=”Top Level Example”
module=”Pulsestorm_MenuTutorial”
sortOrder=”9999″
resource=”Magento_Backend::content”
/>
</menu>
</config>

With the above in place, clear your Magento cache and load a backend page. You should see a new, top level Menu Item at the bottom of the admin navigation

ADD ADMIN SUB MENU
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/adminhtml/menu.xml:

<!– START: new node –>
<add id=”Pulsestorm_MenuTutorial::second_level_example”
title=”Second Level Example”
module=”Pulsestorm_MenuTutorial”
sortOrder=”9999″
resource=”Magento_Backend::content”

parent=”Pulsestorm_MenuTutorial::top_level_example”
action=”cms/page/index”
/>
<!– END: new node –>

ADD ADMIN SUB SUB MENU

<!– ADD L3 –>
<add id=”Pulsestorm_MenuTutorial::third_level_example”
title=”Third Level Example”
module=”Pulsestorm_MenuTutorial”
sortOrder=”9999″
resource=”Magento_Backend::content”

parent=”Pulsestorm_MenuTutorial::second_level_example”
action=”cms/page/index”
/>

 

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_acl
Which Module? (Pulsestorm_HelloWorld)] Pulsestorm_MenuTutorial
Rule IDs? (Pulsestorm_MenuTutorial::top,Pulsestorm_MenuTutorial::config,)] Pulsestorm_MenuTutorial::menu_items,Pulsestorm_MenuTutorial::example_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/acl.xml

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/acl.xml:

<resource id=”Pulsestorm_MenuTutorial::menu_items” title=”Tutorial Menu Items”>
<resource id=”Pulsestorm_MenuTutorial::example_1″ title=”First Example”/>
</resource>

 

GENERATE MENU:
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_menu
Module Name? (Pulsestorm_HelloGenerate)] Pulsestorm_MenuTutorial
Is this a new top level menu? (Y/N) (N)] N
Select Parent Menu:
[1] System (Magento_Backend::system)
[2] Customers (Magento_Customer::customer)
[3] Reports (Magento_Reports::report)
[4] Find Partners & Extensions (Magento_Marketplace::partners)
[5] Sales (Magento_Sales::sales)
[6] Dashboard (Magento_Backend::dashboard)
[7] System (Magento_Backend::system)
[8] Marketing (Magento_Backend::marketing)
[9] Content (Magento_Backend::content)
[10] Stores (Magento_Backend::stores)
[11] Products (Magento_Catalog::catalog)
[12] (Magento_Backend::system_currency)
[13] Top Level Example (Pulsestorm_MenuTutorial::top_level_example)
()] 1
Use [Magento_Backend::system] as parent? (Y/N) (N)] N
Select Parent Menu:
[1] Report (Magento_Backend::system_report)
[2] Permissions (Magento_User::system_acl)
[3] Extensions (Magento_Integration::system_extensions)
[4] Tools (Magento_Backend::system_tools)
[5] Data Transfer (Magento_Backend::system_convert)
[6] Other Settings (Magento_Backend::system_other_settings)
()] 6
Menu Link ID (Pulsestorm_MenuTutorial::unique_identifier)] Pulsestorm_MenuTutorial::a_menu_item
ACL Resource (Pulsestorm_MenuTutorial::a_menu_item)] Pulsestorm_MenuTutorial::example_1
Link Title (My Link Title)] Look at me, I’m a link
Three Segment Action (frontname/index/index)] pulsestorm_menututorial/index/index
Sort Order? (10)] 9999
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/MenuTutorial/etc/adminhtml/menu.xml
Done.

 

Magento 2: Admin MVC/MVVM Endpoints
https://alanstorm.com/magento_2_admin_mvcmvvm_endpoints/

Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_module Pulsestorm HelloAdminBackend 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/registration.php

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_acl Pulsestorm_HelloAdminBackend Pulsestorm_HelloAdminBackend::top,Pulsestorm_HelloAdminBackend::menu_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/acl.xml

Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_menu Pulsestorm_HelloAdminBackend Magento_Backend::system_other_settings Pulsestorm_HelloAdminBackend::a_menu_item Pulsestorm_HelloAdminBackend::menu_1 “Hello Admin Backend Pestle” pulsestorm_hello_admin_backend/index/index 1
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/adminhtml/menu.xml
Done.

Satrias-MacBook-Pro:code teddy$ cd ../..
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_HelloAdminBackend && php bin/magento setup:upgrade

you’ll have a Pulsestorm_HelloAdminBackend module with an ACL hierarchy defined, and a single Menu Item under System -> Other Settings -> Hello Admin Backend Pestle.

CREATE ADMIN ROUTE
Satrias-MacBook-Pro:magentoce215 teddy$ cd app/code/
Satrias-MacBook-Pro:code teddy$ php pestle.phar generate_route
Which Module? (Pulsestorm_HelloWorld)] Pulsestorm_HelloAdminBackend
Which Area (frontend, adminhtml)? (frontend)] adminhtml
Frontname/Route ID? (pulsestorm_helloworld)] pulsestorm_hello_admin_backend
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/etc/adminhtml/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/Controller/Adminhtml/Index/Index.php
Don’t forget your menu.xml and acl.xml
action=”pulsestorm_hello_admin_backend/index/index”
id=”Pulsestorm_HelloAdminBackend::pulsestorm_hello_admin_backend_menu

Clear your cache and generated class files, and then click on the Hello Admin Backend Pestle menu. If you’re logged in as the Magento super user, you should be brought to a new, blank admin page!

ALLOWED USER
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/Controller/Adminhtml/Index/Index.php:
..
protected function _isAllowed()
{
return $this->_authorization->isAllowed(‘Pulsestorm_HelloAdminBackend::menu_1’);
}

ADD ADMIN CONTENT
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_view
Which Module? (Pulsestorm_HelloGenerate)] Pulsestorm_HelloAdminBackend
Which Area? (frontend)] adminhtml
Which Handle? (pulsestorm_helloadminbackend_index_index)] pulsestorm_hello_admin_backend_index_index
Block Name? (Main)] Main
Template File? (content.phtml)] content.phtml
Layout (ignored for adminhtml) ? (1column)]
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/view/adminhtml/templates/content.phtml
Creating: Pulsestorm\HelloAdminBackend\Block\Adminhtml\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/view/adminhtml/layout/pulsestorm_hello_admin_backend_index_index.xml

After running pestle with the above arguments and clearing your cache, reload your page and you should see pestle’s default block content.

MENU HIGHLIGHT
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/HelloAdminBackend/Controller/Adminhtml/Index/Index.php:
….
public function execute()
{
//return $this->resultPageFactory->create();
$page = $this->resultPageFactory->create();
$page->setActiveMenu(‘Pulsestorm_HelloAdminBackend::a_menu_item’);
return $page;
}

SET DIFFERENT TITLE
MODIFY AGAIN

public function execute()
{
//return $this->resultPageFactory->create();
$page = $this->resultPageFactory->create();
$page->setActiveMenu(‘Pulsestorm_HelloAdminBackend::a_menu_item’);
$page->getConfig()->getTitle()->prepend(__(‘My New Title’));
return $page;
}

 

Magento 2 Object Manager
https://alanstorm.com/magento_2_object_manager/

DOWNLOAD https://github.com/astorm/magento2-tutorial-objectmanager1
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectManager1

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-1
You did it!

USE OBJECT MANAGER
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectManager1/Command/Testbed.php:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“You did it!”);
$manager = $this->getObjectManager();
$object = $manager->create(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$output->writeln($object->getHelloMessage());
}

TEST THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-1
Hello Magento!

SINGLETON
MODIFY AGAIN:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$output->writeln(“You did it!”);
$manager = $this->getObjectManager();
/*$object = $manager->create(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$output->writeln($object->getHelloMessage());*/

//USE ‘GET’ INSTEAD OF ‘CREATE’ FOR SINGLETON
$object = $manager->get(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$object->message = ‘Hello PHP!’;
$output->writeln(
$object->getHelloMessage()
);

$object = $manager->get(‘Pulsestorm\TutorialObjectManager1\Model\Example’);
$output->writeln(
$object->getHelloMessage()
);
}

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-1
Hello PHP!
Hello PHP!

 

Magento 2’s Automatic Dependency Injection
https://alanstorm.com/magento2_dependency_injection_2015/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectmanager2
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectManager2

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-2
Hello Again World!

AUTOMATIC DEPENDENCY INJECTION
MODIFY ‘__construct’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectManager2/Model/Example.php:

public function __construct(Message $message)
{
//$object = new Message; //
//$this->messageObject = $object;
$this->messageObject = $message;
}

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-2
Hello Again World!

SO NO NEED TO SUPPLY ‘message’ PARAMETER BECAUSE IT’D ALREDY TAKE CARE BY AUTOMATIC DEPENDENCY INJECTION OF M2
‘This is automatic dependency injection. Behind the scenes, the object manager will use PHP’s reflection features to look at a class’s __construct type hints/parameters, automatically instantiate the object for us, and then pass it into the constructor as an argument.’

 

Magento 2 Object Manager Preferences
https://alanstorm.com/magento_2_object_manager_preferences/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectpreference1
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectPreference

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-preference
Hello!

CLASS PREFERENCE
SEE: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectPreference/etc/di.xml

 

Magento 2 Object Manager Argument Replacement
https://alanstorm.com/magento_2_object_manager_argument_replacement/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectmanager-arguments
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialObjectManagerArguments

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-arguments
Installed!

ARGUMENT REPLACEMENT
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialObjectManagerArguments/etc/di.xml:

<type name=”Magento\Framework\Console\CommandList”>

</type>
<type name=”Pulsestorm\TutorialObjectManagerArguments\Model\Example”>
<arguments>
<argument name=”scaler1″ xsi:type=”string”>bar</argument>
</arguments>
</type>

RUN THE COMMAND: (CLEAR/FLUSH CACHE FIRST)
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-arguments

The Property $scaler1
is a string
with a value of: bar

REPLACING ARRAYS
MODIFY AGAIN:

<type name=”Pulsestorm\TutorialObjectManagerArguments\Model\Example”>
<arguments>
<argument name=”scaler1″ xsi:type=”string”>bar</argument>
<argument name=”thearray” xsi:type=”array”>
<item name=”0″ xsi:type=”string”>science</item>
<item name=”baz” xsi:type=”string”>baz</item>
<item name=”bar” xsi:type=”string”>bar</item>
</argument>
</arguments>
</type>

RUN THE COMMAND: (CLEAR/FLUSH CACHE FIRST)
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-object-manager-arguments

The Property $thearray
is an array
with the elements:
0=>science
baz=>baz
bar=>bar

Magento 2 Object Manager Virtual Types
https://alanstorm.com/magento_2_object_manager_virtual_types/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-objectmanager-virtual-types
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialVirtualType

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-virtual-type
Installed Pulsestorm_TutorialVirtualType!

MODIFY ‘execute’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialVirtualType/Command/Testbed.php:

protected function execute(InputInterface $input, OutputInterface $output)
{
$this->output = $output;
//$output->writeln(“Installed Pulsestorm_TutorialVirtualType!”);
$this->showNestedPropertiesForObject();
}

FLUSH THE CACHE AND RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-virtual-type
First, we’ll report on the Pulsestorm\TutorialVirtualType\Model\Example object
The Property $property_of_example_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument1

Next, we’re going to report on the Example object’s one property (an Argument1 class)
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument2

Finally, we’ll report on an Argument1 object, instantiated seperate from Example
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument2

Creating a Virtual Type
With virtual types, the only behavior you can change in your virtual sub-class is which dependencies are injected.
With virtual types, the only behavior you can change in your virtual sub-class is which dependencies are injected.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialVirtualType/etc/di.xml:

<virtualType name=”ourVirtualTypeName” type=”Pulsestorm\TutorialVirtualType\Model\Argument1″>
<arguments>
<argument name=”the_argument” xsi:type=”object”>Pulsestorm\TutorialVirtualType\Model\Argument3</argument>
</arguments>
</virtualType>

<type name=”Pulsestorm\TutorialVirtualType\Model\Example”>
<arguments>
<argument name=”the_object” xsi:type=”object”>ourVirtualTypeName</argument>
</arguments>
</type>

FLUSH THE CACHE AND RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-virtual-type
First, we’ll report on the Pulsestorm\TutorialVirtualType\Model\Example object
The Property $property_of_example_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument1

Next, we’re going to report on the Example object’s one property (an Argument1 class)
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument3 <– IT’S CHANGED BY VIRTUALTYPE

Finally, we’ll report on an Argument1 object, instantiated seperate from Example
The Property $property_of_argument1_object
is an object
created with the class:
Pulsestorm\TutorialVirtualType\Model\Argument2 <– NOT CHANGED

You’ll notice that the property_of_argument1_object property is now an Argument3 object — but only when that parameter’s owner class (Argument1) is instantiated by dependency injection in the Example class. When we instantiate Argument1 by itself — Magento does not inject a dependency.

 

Magento 2 Object Manager: Proxy Objects
https://alanstorm.com/magento_2_object_manager_proxy_objects/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-proxy-objects
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialProxy1
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialProxy2

RUN A COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
You’ve installed Pulsestorm_TutorialProxy2!
You’ve also installed Pulsestorm_TutorialProxy1!

MODIFY ‘execute’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialProxy2/Command/Testbed.php:

protected function execute(InputInterface $input, OutputInterface $output)
{
//$this->installedCheck($output);
$service = $this->createService($output);
$this->sayHelloWithFastObject($service, $output);
$this->sayHelloWithSlowObject($service, $output);
}

RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
About to Create Service
Constructing FastLoading Object
Constructing SlowLoading Object
Created Service, approximate time to load: 3006.922 ms <– SLOW

About to say hello with fast object
Hello
Said hello with fast object, approximate time to load: 0.0188 ms

About to say hello with slow object
Hello
Said hello with slow object, approximate time to load: 0.0551 ms

TO REPLACE THE SLOW OBJECT IN TutorialProxy1 OBJECT, WE CAN’T USE PREFERENCE BUT PROXY. SO MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialProxy2/etc/di.xml:

<!– Notice: we’re using TutorialProxy2‘s di.xml to change the
behavior of TutorialProxy1. This the far more common usage
of object manager/dependency-injection than the examples in
our tutorial so far –>

<type name=”Pulsestorm\TutorialProxy1\Model\Example”>
<arguments>
<argument name=”slow” xsi:type=”object”>Pulsestorm\TutorialProxy1\Model\SlowLoading\Proxy</argument>
</arguments>
</type>

</config>

THEN FLUSH THE CACHE AND RUN THE COMMAND AGAIN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
About to Create Service
Constructing FastLoading Object
Created Service, approximate time to load: 9.789 ms <– MUCH FASTER FOR THE FIRST TIME

About to say hello with fast object
Hello
Said hello with fast object, approximate time to load: 0.0129 ms

About to say hello with slow object
Constructing SlowLoading Object
Hello
Said hello with slow object, approximate time to load: 3005.425 ms

THEN RE-RUN:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-proxy
About to Create Service
Constructing FastLoading Object
Created Service, approximate time to load: 1.6 ms <– EVEN FASTER FOR THE 2nd TIME

About to say hello with fast object
Hello
Said hello with fast object, approximate time to load: 0.0131 ms

About to say hello with slow object
Constructing SlowLoading Object
Hello
Said hello with slow object, approximate time to load: 3000.463 ms

 

Magento 2 Object Manager: Instance Objects
https://alanstorm.com/magento_2_object_manager_instance_objects/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-instance-objects
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialInstanceObjects

RUN A COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-instance-objects
You’ve installed Pulsestorm_TutorialInstanceObjects

 

Magento 2 Object Manager Plugin System
https://alanstorm.com/magento_2_object_manager_plugin_system/

DOWNLOAD FROM https://github.com/astorm/magento2-tutorial-plugin
AND FOLLOW THE INSTRUCTION TO PUT IN IN /app/code/Pulsestorm/ DIR

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_TutorialPlugin

RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin-installed
You’ve installed Pulsestorm_TutorialPlugin

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello hola!

CREATE A PLUGIN:
It’s inevitable that the larger community will start using the word “plugin” as a place-holder for “extension” or “module”, but in the language of the object manager, a “plugin” refers to a special class that’s listening for any public method call to another object.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/etc/di.xml:

<type name=”Pulsestorm\TutorialPlugin\Model\Example”>
<plugin name=”pulsestorm_tutorial_plugin_model_example_plugin”
type=”Pulsestorm\TutorialPlugin\Model\Example\Plugin”
sortOrder=”10″
disabled=”false”/>
</type>

CREATE A NEW EMPTY CLASS ‘Plugin’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/Model/Example/Plugin.php:
<?php
namespace Pulsestorm\TutorialPlugin\Model\Example;
class Plugin
{

}

FLUSH THE CACHE AND RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor <– INTERCEPTOR ADDED FOR THE PLUGIN!!

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello hola!

Plugins: After Methods
ADD ‘afterGetMessage’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/Model/Example/Plugin.php:

public function afterGetMessage($subject, $result)
{
echo “Calling ” , __METHOD__,”\n”;
return $result;
}

RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Calling Pulsestorm\TutorialPlugin\Model\Example\Plugin::afterGetMessage
Result: hello hola!

Plugins: Before Methods
ADD ‘beforeGetMessage’ FUNCTION IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/Model/Example/Plugin.php:

public function beforeGetMessage($subject, $thing=’World’, $should_lc=false)
{
echo “Calling ” . __METHOD__,”\n”;
}

RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

Calling Pulsestorm\TutorialPlugin\Model\Example\Plugin::beforeGetMessage
Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello hola!


public function beforeGetMessage($subject, $thing=’World’, $should_lc=false)
{
//echo “Calling ” . __METHOD__,”\n”;
return [‘Changing the argument’, $should_lc];
}

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Result: hello changing the argument!

Plugins: Around Methods
MODIFY

public function aroundGetMessage($subject, $procede, $thing=’World’, $should_lc=false)
{
echo ‘Calling’ . __METHOD__ . ‘ — before’,”\n”;
$result = $procede();
echo ‘Calling’ . __METHOD__ . ‘ — after’,”\n”;
return $result;
}

Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — before
Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — after
Result: Hello World!

AVOID PLUGIN CONFLICT FOR SAME FUNCTION/METHOD NAME
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/TutorialPlugin/etc/di.xml:

<!– START: two new plugins –>
<type name=”Pulsestorm\TutorialPlugin\Model\Example”>
<plugin name=”pulsestorm_tutorial_plugin_model_conflict_plugin1″
type=”Pulsestorm\TutorialPlugin\Model\Conflict\Plugin1″
sortOrder=”10″
disabled=”false”/>
</type>

<type name=”Pulsestorm\TutorialPlugin\Model\Example”>
<plugin name=”pulsestorm_tutorial_plugin_model_conflict_plugin2″
type=”Pulsestorm\TutorialPlugin\Model\Conflict\Plugin2″
sortOrder=”15″
disabled=”false”/>
</type>
<!– START: two new plugins –>

RE-RUN THE COMMAND:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento ps:tutorial-plugin

We’re going to call the getMessage method on the class

Pulsestorm\TutorialPlugin\Model\Example\Interceptor

CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — before
Calling the real Pulsestorm\TutorialPlugin\Model\Example::getMessage
Calling Pulsestorm\TutorialPlugin\Model\Conflict\Plugin1::afterGetMessage
Calling Pulsestorm\TutorialPlugin\Model\Conflict\Plugin2::afterGetMessage
CallingPulsestorm\TutorialPlugin\Model\Example\Plugin::aroundGetMessage — after
Result: From Plugin 2

Magento 2: Introducing UI Components
https://alanstorm.com/magento_2_introducing_ui_components/

Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar magento2:generate:ui:grid
Which Module? (Pulsestorm_Gridexample)] Pulsestorm_ToDoCrud
Create a unique ID for your Listing/Grid! (pulsestorm_gridexample_log)] pulsestorm_todo_listing
What Resource Collection Model should your listing use? (Magento\Cms\Model\ResourceModel\Page\Collection)] Pulsestorm\ToDoCrud\Model\ResourceModel\TodoItem\Collection
What’s the ID field for you model? (pulsestorm_gridexample_log_id)] pulsestorm_todocrud_todoitem_id
Creating New /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/adminhtml/ui_component/pulsestorm_todo_listing.xml
Creating: Pulsestorm\ToDoCrud\Ui\Component\Listing\DataProviders\Pulsestorm\Todo\Listing
Creating: Pulsestorm\ToDoCrud\Ui\Component\Listing\Column\Pulsestormtodolisting\PageActions
Don’t forget to add this to your layout XML with <uiComponent name=”pulsestorm_todo_listing”/>

ADD A NEW FILE: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/adminhtml/layout/pulsestorm_admin_todocrud_index_index.xml:
<?xml version=”1.0″?>
<page xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:View/Layout/etc/page_configuration.xsd”>
<body>
<referenceBlock name=”content”>
<uiComponent name=”pulsestorm_todo_listing”/>
</referenceBlock>
</body>
</page>

 

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/ToDoCrud/view/adminhtml/ui_component/pulsestorm_todo_listing.xml:

<column name=”pulsestorm_todocrud_todoitem_id”>

</column>
<column name=”title”>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”filter” xsi:type=”string”>text</item>
<item name=”label” xsi:type=”string” translate=”true”>Item Title</item>
<item name=”sortOrder” xsi:type=”number”>20</item>
</item>
</argument>
</column>
<actionsColumn name=”actions” …

Magento 2: Simplest UI Component
https://alanstorm.com/magento_simplest_ui_component/

CREATE THE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_module Pulsestorm SimpleUiComponent 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/registration.php

CREATE ACL:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_acl Pulsestorm_SimpleUiComponent Pulsestorm_SimpleUiComponent::top,Pulsestorm_SimpleUiComponent::menu_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/acl.xml

CREATE MENU:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_menu Pulsestorm_SimpleUiComponent Magento_Backend::system_other_settings Pulsestorm_SimpleUiComponent::a_menu_item Pulsestorm_SimpleUiComponent::menu_1 “Hello Simple Ui Component” pulsestorm_simpleuicomponent/index/index 1
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/adminhtml/menu.xml
Done.

CREATE ROUTE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_route Pulsestorm_SimpleUiComponent adminhtml pulsestorm_simpleuicomponent
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/adminhtml/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Controller/Adminhtml/Index/Index.php
Don’t forget your menu.xml and acl.xml
action=”pulsestorm_simpleuicomponent/index/index”
id=”Pulsestorm_SimpleUiComponent::pulsestorm_simpleuicomponent_menu

CREATE VIEW:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_view Pulsestorm_SimpleUiComponent adminhtml pulsestorm_simpleuicomponent_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/templates/content.phtml
Creating: Pulsestorm\SimpleUiComponent\Block\Adminhtml\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/layout/pulsestorm_simpleuicomponent_index_index.xml

ENABLE THE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_SimpleUiComponent && php bin/magento setup:upgrade

After running the above commands, you should be able to navigate to Magento’s backend and click on the System -> Other Settings -> Hello Simple Ui Component menu to bring up our new backend section.

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/layout/pulsestorm_simpleuicomponent_index_index.xml:

<referenceBlock name=”content”>
<block template=”content.phtml” …/>

<!– START: our new ui component –>
<uiComponent name=”pulsestorm_simple”/>
<!– END: our new ui component –>
</referenceBlock>

CREATE A NEW FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/pulsestorm_simple.xml:
<?xml version=”1.0″?>
<pulsestorm_simple xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
</pulsestorm_simple>

THEN CREATE A NEW FILE ‘definition.xml’ IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/base/ui_component/etc/definition.xml:
<?xml version=”1.0″?>
<components xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_definition.xsd”>
<pulsestorm_simple class=”Pulsestorm\SimpleUiComponent\Component\Simple”/>
</components>

HERE WE NEED TO ADD CLASS PREFERENCE. SO CREATE ‘di.xml’ FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/etc/di.xml:
<?xml version=”1.0″?>
<config xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:framework:ObjectManager/etc/config.xsd”>
<preference for=”Magento\Framework\App\Arguments\ValidationState” type=”Pulsestorm\SimpleUiComponent\Model\ValidationState”/>
</config>

THEN CREATE A NEW PHP FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Model/ValidationState.php:
<?php
namespace Pulsestorm\SimpleUiComponent\Model;
class ValidationState extends \Magento\Framework\App\Arguments\ValidationState
{
public function isValidationRequired()
{
return false;
}
}

THEN CREATE ANOTHER NEW PHP FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Component/Simple.php:
<?php
namespace Pulsestorm\SimpleUiComponent\Component;
class Simple extends \Magento\Ui\Component\AbstractComponent
{
const NAME = ‘pulsestorm_simple’;
public function getComponentName()
{
return static::NAME;
}
}

THEN MODIFY ‘definition.xml’ LIKE THIS:
<?xml version=”1.0″?>
<components xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_definition.xsd”>
<pulsestorm_simple class=”Pulsestorm\SimpleUiComponent\Component\Simple”>
<argument name=”data” xsi:type=”array”>
<item name=”template” xsi:type=”string”>templates/our-template</item>
</argument>
</pulsestorm_simple>
</components>

THEN CREATE A NEW XHTML FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/templates/our-template.xhtml:
<?xml version=”1.0″ encoding=”UTF-8″?>
<div>
<h1>Hello World</h1>
</div>

 

THEN MODIFY ‘pulsestorm_simple.xml’ FILE:
<?xml version=”1.0″?>
<pulsestorm_simple xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>

<dataSource name=”pulsestorm_simple_data_source”>
<argument name=”dataProvider” xsi:type=”configurableObject”>
<!– the PHP class that implements a data provider –>
<argument name=”class” xsi:type=”string”>Pulsestorm\SimpleUiComponent\Model\DataProvider</argument>

<!– redundant with the dataSource name –>
<argument name=”name” xsi:type=”string”>pulsestorm_simple_data_source</argument>

<!– required: means ui components are meant to work with models –>
<argument name=”primaryFieldName” xsi:type=”string”>entity_id</argument>

<!– required: means ui components are meant to work with URL passing –>
<argument name=”requestFieldName” xsi:type=”string”>id</argument>
</argument>

</dataSource>

</pulsestorm_simple>

THEN ADD A NEW PHP FILE (DATA PROVIDER) IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Model/DataProvider.php:
<?php
namespace Pulsestorm\SimpleUiComponent\Model;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
}

OK. CLEAR THE CACHE THEN TEST IT ON THE ADMIN PAGE (SYSTEM -> HELLO SIMPLE UI COMPONENT).
IT SHOULD DIPLAY:
Magento Admin
This is my template, there are many like it, but this one is mine.
Hello World

 

MODIFYING XHTML TEMPLATE.
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/Component/Simple.php TO ADD NEW FUNCTION ‘getEvenMoreData’:

//added this method
public function getEvenMoreData()
{
return ‘Even More Data!’;
}

THEN CALL THE FUNCTION FROM /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/templates/our-template.xhtml:

<p>
{{getComponentName()}}
</p>

<p>
{{getEvenMoreData()}}
</p>

OK. CLEAR THE CACHE THEN TEST IT ON THE ADMIN PAGE (SYSTEM -> HELLO SIMPLE UI COMPONENT).
IT SHOULD DIPLAY:
Magento Admin
This is my template, there are many like it, but this one is mine.
Hello World
pulsestorm_simple
Even More Data!

 

Magento 2: Simplest UI Knockout Component
https://alanstorm.com/magento_2_simplest_ui_knockout_component/

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/base/ui_component/etc/definition.xml:

<argument name=”data” xsi:type=”array”>

<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
….

CREATE A NEW JS FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/js/pulsestorm_simple_component.js:
/*define([], function(){
console.log(‘Called’);
});*/
define([‘uiElement’], function(Element){
console.log(‘Called’);
viewModelConstructor = Element.extend({
defaults: {
template: ‘Pulsestorm_SimpleUiComponent/pulsestorm_simple_template’
}
});

return viewModelConstructor;
});

//IT’D PRINT ‘Called’.

CREATE THE HTML TEMPLATE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/template/pulsestorm_simple_template.html:
<h1>Rendered with Knockout.js</h1>

MODIFY THE XHTML COMPONENT IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/templates/our-template.xhtml:

<div>

<div data-bind=”scope: ‘pulsestorm_simple.pulsestorm_simple'” class=”entry-edit form-inline”>
<!– ko template: getTemplate() –><!– /ko –>
</div>
</div>

OK. CLEAR THE CACHE AND RELOAD:
IT’D PRINT
Magento Admin

This is my template, there are many like it, but this one is mine.
Hello World
pulsestorm_simple

Even More Data!

{{message}}

Rendered with Knockout.js

NOTE: ‘pulsestorm_simple.pulsestorm_simple’ IS FROM THE UICOMPONENT NAME (/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/pulsestorm_simple.xml)

TO SHOW A MESSAGE IN THE HTML FILE (pulsestorm_simple_template.html), MODIFY THE COMPONENT (/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/js/pulsestorm_simple_component.js) LIKE THIS:
define([‘uiElement’, ‘ko’], function(Element, ko){
console.log(‘Called’);
viewModelConstructor = Element.extend({
defaults: {
template: ‘Pulsestorm_SimpleUiComponent/pulsestorm_simple_template’
},
message: ko.observable(“Hello Knockout.js!”)
});

return viewModelConstructor;
});

THEN IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/web/template/pulsestorm_simple_template.html:
<h1>Rendered with Knockout.js</h1>

<strong data-bind=”text:message”></strong>

CLEAR THE CACHE AND RELOAD.

HERE IS ANOTHER WAY TO RENDER THE TEMPLATE
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/base/ui_component/etc/definition.xml:

<item name=”config” xsi:type=”array”>
<!– <item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item> –>
<item name=”component” xsi:type=”string”>uiComponent</item>
</item>

THEN MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleUiComponent/view/adminhtml/ui_component/pulsestorm_simple.xml AND ADD:

<pulsestorm_simple xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>

<dataSource name=”pulsestorm_simple_data_source”>

</dataSource>

<htmlContent name=”first_ever_child”>
<argument name=”block” xsi:type=”object”>Magento\Framework\View\Element\Text</argument>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
</htmlContent>

</pulsestorm_simple>

THEN CLEAR CACHE AND RELOAD. IT’D PRINT THE SAME! BUT IF I MODIFY THE ABOVE XML FILE FURTHER, LIKE THIS (ADD “second_ever_child”):

<htmlContent name=”first_ever_child”>

</htmlContent>

<htmlContent name=”second_ever_child”>
<argument name=”block” xsi:type=”object”>Magento\Framework\View\Element\Text</argument>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
</htmlContent>

THE TEMPLATE WOULD BE RENDERED TWICE!

 

Magento 2: Simplest XSD Valid UI Component
https://alanstorm.com/magento_2_simplest_xsd_valid_ui_component/

DISABLE THE SIMPLEUICOMPONENT FIRST:
php bin/magento module:disable Pulsestorm_SimpleUiComponent

CREATE A NE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_module Pulsestorm SimpleValidUiComponent 0.0.1
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/module.xml
Created: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/registration.php

CREATE ACL:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_acl Pulsestorm_SimpleValidUiComponent Pulsestorm_SimpleValidUiComponent::top,Pulsestorm_SimpleValidUiComponent::menu_1
Created /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/acl.xml

CREATE A MENU:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_menu Pulsestorm_SimpleValidUiComponent Magento_Backend::system_other_settings Pulsestorm_SimpleValidUiComponent::a_menu_item Pulsestorm_SimpleValidUiComponent::menu_1 “Hello Simple Valid Ui Component” pulsestorm_simplevaliduicomponent/index/index 1
Writing: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/adminhtml/menu.xml
Done.

CREATE A ROUTE:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_route Pulsestorm_SimpleValidUiComponent adminhtml pulsestorm_simplevaliduicomponent
Controller name? (Index)]
Action name? (Index)]
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/etc/adminhtml/routes.xml
/Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Controller/Adminhtml/Index/Index.php
Don’t forget your menu.xml and acl.xml
action=”pulsestorm_simplevaliduicomponent/index/index”
id=”Pulsestorm_SimpleValidUiComponent::pulsestorm_simplevaliduicomponent_menu

CREATE VIEW:
Satrias-MacBook-Pro:magentoce215 teddy$ php pestle.phar generate_view Pulsestorm_SimpleValidUiComponent adminhtml pulsestorm_simplevaliduicomponent_index_index Main content.phtml 1column
Creating /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/templates/content.phtml
Creating: Pulsestorm\SimpleValidUiComponent\Block\Adminhtml\Main
Creating: /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/layout/pulsestorm_simplevaliduicomponent_index_index.xml

ENABLE THE MODULE:
Satrias-MacBook-Pro:magentoce215 teddy$ php bin/magento module:enable Pulsestorm_SimpleValidUiComponent && php bin/magento setup:upgrade

With the above in place, clear your cache, and you should be able to navigate to a System -> Other Settings -> Hello Simple Valid Ui Component menu in your Magento backend.

CLEAR THE CACHE AND RELOAD

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/layout/pulsestorm_simplevaliduicomponent_index_index.xml TO ADD ‘uiComponent’:

<referenceBlock name=”content”>
<block template=”content.phtml” class=”Pulsestorm\SimpleValidUiComponent\Block\Adminhtml\Main” name=”pulsestorm_simplevaliduicomponent_block_main”/>

<uiComponent name=”pulsestorm_simple_valid”/>

</referenceBlock>
….

then we’ll create an XML file for this named UI Component IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<?xml version=”1.0″?>
<pulsestorm_simple_valid xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
</pulsestorm_simple_valid>

 

MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
</container>

MODIFY AGAIN TO ADD ‘dataSource’ NODE:
<container xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
<dataSource name=”pulsestorm_simple_valid_data_source”>
<argument name=”dataProvider” xsi:type=”configurableObject”>
<!– the PHP class that implements a data provider –>
<argument name=”class” xsi:type=”string”>Pulsestorm\SimpleValidUiComponent\Model\DataProvider</argument>

<!– redundant with the dataSource name –>
<argument name=”name” xsi:type=”string”>pulsestorm_simple_valid_data_source</argument>

<!– required: means ui components are meant to work with models –>
<argument name=”primaryFieldName” xsi:type=”string”>entity_id</argument>

<!– required: means ui components are meant to work with URL passing –>
<argument name=”requestFieldName” xsi:type=”string”>id</argument>
</argument>
</dataSource>
</container>

THEN add a new data provider class IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Model/DataProvider.php:
<?php
namespace Pulsestorm\SimpleValidUiComponent\Model;
class DataProvider extends \Magento\Ui\DataProvider\AbstractDataProvider
{
}

THEN CLEAR THE CACHE AND RELOAD

CHANGING TEMPLATE
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:noNamespaceSchemaLocation=”urn:magento:module:Magento_Ui:etc/ui_configuration.xsd”>
<argument name=”data” xsi:type=”array”>
<item name=”template” xsi:type=”string”>templates/pulsestorm_simple_valid/default</item>
</argument>

<dataSource name=”pulsestorm_simple_valid_data_source”>

</dataSource>
</container>

THEN CREATE A XHTML FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/templates/pulsestorm_simple_valid/default.xhtml:
<div
data-bind=”scope: ‘{{getName()}}.{{getName()}}'”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:noNamespaceSchemaLocation=”../../../../../../Ui/etc/ui_template.xsd”>

<!– ko template: getTemplate() –><!– /ko –>
</div>

ADD an htmlContent component/node IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container …>

<htmlContent name=”our_first_content”>
<argument name=”block” xsi:type=”object”>Pulsestorm\SimpleValidUiComponent\Block\Example</argument>
</htmlContent>
</container>

THEN CREATE A PHP FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Block/Example.php:
<?php
namespace Pulsestorm\SimpleValidUiComponent\Block;

use Magento\Framework\View\Element\BlockInterface;

class Example extends \Magento\Framework\View\Element\AbstractBlock
{
public function toHtml()
{
return ‘<h1>Hello PHP Block Rendered in JS</h1>’;
}
}

OK. CLEAR THE CACHE AND RELOAD.
IT’D PRINT:
Magento Admin

This is my template, there are many like it, but this one is mine.
Hello PHP Block Rendered in JS

Hijacking htmlContent
THIS IS ANOTHER WAY TO RENDER TEMPLATE WITH A COMPONENT CLASS:
MODIFY /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/ui_component/pulsestorm_simple_valid.xml:
<container …>

<htmlContent class=”Pulsestorm\SimpleValidUiComponent\Component\Simple” name=”our_first_content”>
<argument name=”data” xsi:type=”array”>
<item name=”config” xsi:type=”array”>
<item name=”component” xsi:type=”string”>Pulsestorm_SimpleValidUiComponent/js/pulsestorm_simple_component</item>
</item>
</argument>
</htmlContent>
</container>

CREATE A COMPONENT FILE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/Component/Simple.php:
<?php
namespace Pulsestorm\SimpleValidUiComponent\Component;
class Simple extends \Magento\Ui\Component\AbstractComponent
{
const NAME = ‘html_content_pulsestorm_simple’;
public function getComponentName()
{
return self::getName();
}
}

CREATE THE KNOCKOUT JS VIEW MODEL IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/web/js/pulsestorm_simple_component.js:
define([‘uiElement’,’ko’], function(Element, ko){
viewModelConstructor = Element.extend({
defaults: {
template: ‘Pulsestorm_SimpleValidUiComponent/pulsestorm_simple_template’
}
});

return viewModelConstructor;
});

THEN CREATE THE TEMPLATE IN /Library/WebServer/Documents/Projects/magentoce215/app/code/Pulsestorm/SimpleValidUiComponent/view/adminhtml/web/template/pulsestorm_simple_template.html:
<h1>Our Remote Knockout Template!</h1>

THEN clear your cache and reload the page
IT’D PRINT:
Magento Admin

This is my template, there are many like it, but this one is mine.
Our Remote Knockout Template!

CONCLUSION SO FAR:

Magento uses Knockout.js to render front end interfaces.

By default, Knockout.js uses the entire HTML page as a view, and a javascript object for the view model.

To use Knockout.js, programmers create a javascript constructor function. Knockout.js uses this constructor function to instantiate a view model.

Magento added a custom Knockout.js binding named scope. Scope allows different areas of the page to use different view models.

These different view models are instantiated by the Magento_Ui/js/core/app RequireJS module. This module is embedded in the page via an x-magento-init script, and this module uses a large data structure rendered via the backend’s UI Component classes and XML. This data structure configures a number of RequireJS modules called “components”.

These components are “view model constructor factories”. The Magento_Ui/js/core/app application uses these RequireJS components to create view model constructors, and then uses the instantiated view model constructor function to instantiate view models. Finally, the Magento_Ui/js/core/app application registers each instantiated view model object, (by name), with the uiRegistry RequireJS module. The view model’s registered names come from the large data structure rendered via the backend’s UI Component classes and XML.

The view model constructor objects are based on a Magento built javascript object system. This object system uses RequireJS modules as classes, and uses underscore.js for inheritance and method/property sharing. There’s also some Magento secret sauce in there. The base class is the uiClass module. The uiElement class/module extends from the uiClass class/module. Most of Magento’s Knockout.js view model constructors are uiElement objects.

Above, we mentioned the uiRegistry, uiClass, and uiElement RequireJS modules. These are RequireJS “map aliases” that point to the real modules at Magento_Ui/js/lib/registry/registry, Magento_Ui/js/lib/core/class, and Magento_Ui/js/lib/core/element/element respectively.

Upgraded PHP on Sierra

<OLD>
The PHP version on my Sierra was 5.6. I want to upgrade it to PHP 7.0 version. I followed a tutorial from https://coolestguidesontheplanet.com/upgrade-php-on-osx/.

PHP 7 would be installed in ‘/usr/local/php5/’ directory. Actually this is a symlink directory from ‘/usr/local/php5-7.0.18-20170506-095200/’ directory. Now I can use PHP 7.0 on my mac

But the php version on the terminal still show the old version. I need to change the $PATH like on this tutorial: https://stackoverflow.com/questions/25731145/mac-upgraded-php-to-5-6-but-cli-php-v-get-5-3-28:
Open Terminal, then run

Then add these 2 lines at the bottom of the file:

Save and reopen the terminal. Here is the new version:

</OLD>
NOW USE brew
REF: https://stackoverflow.com/questions/54207030/what-are-the-options-to-upgrade-php-on-macos-mojave-10-14-2
SEARCH PHP

INSTALL PHP 7.2

START SERVICE

ADD PATH

PHP.INI

MUST CLOSE THE TERMINAL THEN OPEN IT BACK TO CHECK THE PHP VERSION

PHP-FPM

CHANGE PHP SETTING

 

Mac OSX 10.12 (Sierra)

Two days ago I upgraded my macbook pro from 10.10 (yosemite) to 10.12 (sierra). The upgrade was pretty smooth but to upgrade it, I found many difficulties about my Apple ID.

Actually I have an Apple ID a long time ago but rarely use it. I remember to use it when I tried to install hackintosh. I tried to use it to download Sierra but I always got a complain on the AppStore like this ‘This Apple ID has not yet been used with the App Store. Please review your account information.’. I thought my Apple ID was deactivated somehow. not sure. Then I created a new Apple ID. But I got the same complain message. I tried many things like I said in https://discussions.apple.com/message/31865081#31865081 but none is working. Even I filled the payment form with my credit card. Finally it’s working. Somehow I tried to use my old Apple ID. It displayed the above message. Then I filled the payment form (the thing I didn’t do at the first time) with my credit card. This time my Apple ID is working and I can download and upgrade my OSX.

Installation of PHP 7.0 FPM and NGINX

Ref: https://www.ma-no.org/en/content/index_php7-install-php7-with-nginx-and-memcache-in-ubuntu-14-04_2137.php

  1. Install php7.0-fpm: sudo apt-get install php7.0-fpm

     
  2. CHANGE THE PHP VERSION FOR CLI TO 7.0

    CHECK THE PHP VERSION:

     
  3. TO ENABLE PHP 7.0 ON NGINX SERVER, PLS DO (MAKE SURE APACHE2 IS STOPPED IF IT’S RUNNING AND START NGINX):

    THE NGINX MAIN CONFIG IN /etc/nginx/nginx.conf
    THE DEFAULT VIRTUALHOST IN /etc/nginx/sites-available/default
    EDIT IT TO ENABLE PARSING PHP FILE:


    CHANGE THE CONTENT TO ENABLE PHP 7.0 FPM:

    THEN CHANGE PHP7.0-FPM SETTING:

    CHANGE THE CONTENT:

    THEN RESTART PHP7.0-FPM SERVICE:

    CHECK NGINX SYNTAX: sudo nginx -t
    RESTART NGINX: sudo systemctl restart nginx
    OPEN IT: http://localhost/phpinfo.php (NEED TO CLEAR THE BROWSER CACHE FIRST)

Magento 1.9.3.2

  1. Download the installer from https://magento.com/tech-resources/download. At the time writing, the latest magento 1.x version is 1.9.3.2. I downloaded the zip version (magento-downloader-1.9.1.0-2015-02-09-10-17-59.zip). I tried to download the .gz and tar.bz2 but it didn’t work. Then download the sample data from the same page.
  2. Create a new database first (may be with phpmyadmin). I gave the database name ‘magento19’.
  3. Extract the sample data from phpmyadmin, then import the sql file (magento_sample_data_for_1.9.2.4.sql) in the extracted data.
  4. Extract the installer file magento-downloader-1.9.1.0-2015-02-09-10-17-59.zip. It only contain single file: downloader.php. Then put this file into your magento root in your webserver. I put it in ‘magento19’ directory
  5. Create a virtualhost for this site:

    Here is the content:

     
  6. Enable the site:
  7. Put it in /etc/hosts/

    add this line:

     
  8. Restart apache webserver:
  9. Begin installation of magento 1.9.3.2 by opening : http://magento19.dev/developer.php. Then follow the instruction. It’d download the magento files needed.
    SORRY, ONLY ADMIN CAN SHOW THIS!
    Note: The PHP version must be between 5.2 and 6.0. I can’t use php 7.0 so I use php 5.6.
  10. Copy and paste the directories ‘media’ and ‘skin’ in the extracted sample data into the magento19 web directory. Just override the current media and skin directories.
  11. Now you can run the site: http://magento19.dev/
    and the admin site: http://magento19.dev/admin

NOTE: At first I made a mistake with installing magento 1.9 without the sample data. To install the sample data, I need to drop the database then create it again. Then follow #3 step. After that, I need to run the installer again http://magento19.dev/developer.php but this time without downloading the magento files because the files already downloaded. Follow the instruction again then if nothing wrong, it’d run well.

UPDATED
20191010
Download and Install extension GLS Shipping from https://marketplace.magento.com/gls-official-gls-dispatch.html
I tried to install it via connect manager then find and upload the package zip file (gls-Official_GLS_Dispatch-1.2.4.tgz). But I got this error message:

OR (CASE FOR Indianic_Couponimpexport EXTENSION)

BECAUSE THE PHP VERSION IN package.xml (EXTRACT FROM THE ZIP FILE) FILE LIKE THIS:

CHANGE IT TO

THEN RE-ZIP (Indianic_Couponimpexport-1.0.0.1-php7.tar.gz) AND RE TRY TO UPLOAD IT AGAIN
BUT GOT ANOTHER ERROR

NOTE: TO RE-ZIP THE PACKAGE, IT NEED TO INCLUDE ONLY THE EXTENSION FILES. DON’T INCLUDE THE PACKAGE DIR NAME!!! SO IT’D BE BETTER TO ZIP IN THE DIR NOT OUT THE DIR

I TRIED TO BACK TO ADMIN PAGE BUT I GOT MAINTENANCE PAGE. I CAN RESOLVE IT WITH n98magerun TO DISABLE MAINTENANCE MODE:

I NEED TO ENABLE LOG (System -> Configuration -> Developer -> Log)
THEN CLEAR/CLEAN THE CACHE

THE LOG WILL BE IN /home/teddy/Documents/works/magento19/var/log.
DONT FORGET TO SET THE FILE PERMISSION

I TRIED TO REUPLOAD THE PACKAGE BUT GOT THIS PERMISSION ERROR:

ALSO CHECK THE LOG IN /home/teddy/Documents/works/magento19/var/log/system.log

SOLUTION: SET THE FILE PERMISSION IN app/code/local/

RE RUN THE PACKAGE INSTALL AND SUCCESS!

FOR GLS SHIPPING, AFTER SET THE PHP VERSION AND NAME, I GOT THIS ERROR MESSAGE WHEN I TRIED TO INSTALL

THIS IS BECAUSE IN package.xml, THERE IS CHANNEL

SOLUTION: ADD THE CHANNEL (READ: https://stackoverflow.com/questions/29071430/connect-error-the-community-channel-is-not-installed-in-magento-site)

THEN RE INSTALL BUT GOT ANOTHER ERROR:

BUT IT INSTALLED SUCCESSFULLY. I NEED TO RUN n98 TO CLEAN THE CACHE.
TRIED TO UNINSTALL

ALSO DELETE THE FILES MANUALLY!
BUT I CONCERN ABOUT GLS MENU IN THE ADMIN PAGE SHOW 404 ERROR (http://magento19.test/index.php/admin/system_config/edit/section/gls/key/107260543ac135ee4fd87400f3e821c8/)