Ooooo sending emails in Magento is painful! Grrrrrr.
Or is it?
Firstly a use case.
I generate report data from cron and I need a simple way of sending the reports on email to a recipient. I do not want to use just the regular php mail() command. It is not reliable and I want it to fit within the Magento way of sending emails.
A popular Mandrill module that I use will also continue to work by making sure we use the in built magento email sending functions.
Okay, so first we need to declare our email so we can load it later on.
When Magento is checking to see if a payment method is “available” it dispatches an event called payment_method_is_active passing in a StdClass that holds a local variable called isAvailable.
We only need to change this variable in our own custom logic to affect wether or not the method is available.
So I had a third party sending SOAP requests to Magento but something was broken.
I needed a way to test it.
They had already sent me the xml data they were pushing to the API, I just had to “pretend” to be their service and call the api with the data provided.
Recently I visited a website that detected I was using an ad blocker and hid the content from me.
Slightly annoying (if not expected) but as I discovered this is simply done with JavaScript and with some quick disabling of the JavaScript I was able to read the article.
Of course what I am talking about here is the order confirmation page.
That is the page you see once you have placed your order confirming your order number.
It is however a single use page.
Once you refresh it you are taken back to an empty cart and that is all fine in production but what if you are a developer in need of modifying the success page?
<?phpnamespace[Vendor]\[ModuleName]\Setup;useMagento\Eav\Setup\EavSetupFactory;useMagento\Framework\Setup\UpgradeDataInterface;useMagento\Framework\Setup\ModuleContextInterface;useMagento\Framework\Setup\ModuleDataSetupInterface;classUpgradeDataimplementsUpgradeDataInterface{protected$eavSetupFactory;publicfunction__construct(EavSetupFactory$eavSetupFactory){$this->eavSetupFactory=$eavSetupFactory;}publicfunctionupgrade(ModuleDataSetupInterface$setup,ModuleContextInterface$context){$eavSetup=$this->eavSetupFactory->create(['setup'=>$setup]);// @todo put attributes here
}}
Everything that follows will go in the // @todo put attributes here bit.
There are a number of entities EAV attributes can be added to; products, categories and customers.
You want to add some additional functionality to the customer section and you want it to reside under the customer frontname created by the magento-customer module.
How do you do this?
In app/code/[codePool]/[Vendor]/[ModuleName]/etc/frontend/routes.xml:
I have used the following technique to add a new button to an existing grid.
The same technique could be used to remove or reorder buttons too.
Grid containers extend Magento\Backend\Block\Widget\Container. During _prepareLayout, any buttons that have been added to the grid get pushed to a toolbar model ($this->toolbar->pushButtons($this, $this->buttonList);).
Because the pushButtons() method is public we can use it to “plugin” to and modify the buttons array.
Tip: If you just wanted to add the new tab for a particular product type you can put the following in a file specific to that type. catalog_product_configurable.xml for example.
<?phprequire__DIR__.'/app/bootstrap.php';classPlaygroundAppextends\Magento\Framework\App\Httpimplements\Magento\Framework\AppInterface{publicfunctionlaunch(){// test code here
// must return the response
return$this->_response;}publicfunctioncatchException(\Magento\Framework\App\Bootstrap$bootstrap,\Exception$exception){returnfalse;}}$bootstrap=\Magento\Framework\App\Bootstrap::create(BP,$_SERVER);/** @var \Magento\Framework\App\Http $app */$app=$bootstrap->createApplication('PlaygroundApp');$bootstrap->run($app);
Any class app that implements the AppInterface must implement both the launch() and catchException() functions.
The launch function must also return an object that implements the ResponseInterface (Line 13). Failing to do so will cause a fatal exception from the App/Bootstrap.php class within the run() function.
Specifically because it is the responsibility of the run() function to gather the response and then send that response to the browser.
Firstly, let us note that preferences are destructive.
That means to say that you tell the Magento system to use your class instead of the original one. It is akin to a rewrite in Magento 1 and doing such things can make it difficult to other module developers to make changes in the same area of code.
The src_type is the clever bit that tells Magento this is an external URL.
Currently this technique is only available in the head section of your layout file. This is something to bare in mind as this will cause the browser to render block whilst the file is downloaded.
This is not a railroading. I haven’t arrived at this conclusion on a whim either. It is the culmination of 12(ish) years of pain working with other email platforms and through one reason or another, them falling short of expectation in one or more areas (sometimes every area). Those areas we will discuss shortly but I would like to start with saying that every single person I have recommended or integrated to MailChimp to date, has either stuck with MailChimp or after a brief spell elsewhere have opted to come back.
My use case for this was that I needed a mechanism to change layout based on the customer group.
So with that in mind i decided adding a customer group layout handle was the way to go and that would allow me to use regular XML to change what I needed to.
So how?
To do this I used a plugin but I needed to know where to plug in to.
Creating a new product type in Magento 2 is actually relatively easy.
Yay!
As with most of these tutorials I make the assumption that you have a valid module registered with Magento. If this is not the case you should create one before you continue if you wish to try out the code.
You first you need to declare your new product type using the product_types.xml located in the etc folder of your module.
Any module installed using composer can be uninstalled using bin/magento module:uninstall [Vendor]_[ModuleName]
During the uninstall process Magento looks for an uninstall class located in the module being uninstalled. Specifically for Setup/Uninstall.php. It does this in the \Magento\Setup\Model\UninstallCollector.php class (collectUninstall()).
If it finds an Uninstall file and that file is a subclass of Magento\Framework\Setup\UninstallInterface it will run it very similar to how it runs install files.
It begins with running bin/magento sampledata:deploy from your magento root install directory.
Some magic then happens…
Hold on, I get an error deploying the sample data similar to:
PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 88614883 bytes)
No problem! This can sometimes happen. Magento uses a lot of memory when installing the sample data. You can remedy this by increasing the available memory temporarily whilst installing the sample data by running the above command with some additional PHP;
Today is create a new Magento 2 console command day!
Woop woop!
Out of the box Magento 2 comes with quite a number of console commands for things like clearing cache, setting developer modes etc. To see them all fire up a command prompt, go to your magento root directory and run:
bin/magento
Give it a few seconds then you will see a list of all available commands.
Before we begin If you are unfamiliar with unit testing and specifically PHPUnit (the testing framework used by Magento) I suggest you read the https://phpunit.de/
Here we go.
Scenario: We have decided to extend the core Breadcrumbs block class with some additional functionality.
A basic first test would be that our new class extends the original class.
The aim here is just to get a module registered with Magento 2. Nothing fancy.
Assuming you now have a installation of Magento 2 (if not see Creating a Magento 2 project with Composer), the first job is to let it know about your new module. You can do this with just two files.
Firstly create your module structure; app/code/[codePool]/[Vendor]/[ModuleName]
Hang on one second! What is [Vendor] and [ModuleName]? [Vendor] is your unique name. It defines your namespace. In my case, I use “Smartie”. [ModuleName] is erm, well, your module name :)
Note: The following is based on my current Magento 2 experience and is really my preferred way of working with the platform to date. You may or may not find it useful.
If you haven’t already, create a directory you want to install Magento 2.