DDEV

After installing DDEV in WSL2 Ubuntu terminal. Note: do not install in Windows.

How to Launch VS Code

Ref DDEV PR #5979

It's important that VS Code is launched within WSL2. There are 2 methods to do this: from the command line and from VS Code. For the first method, open a WSL2 terminal (e.g. the default distro Ubuntu), cd to the root of your project, then run code .. Refer to the Microsoft doc for more inform...

Tips on Configuring Categories

Backend > Catalog > Manage Categories

We can do the following:

  1. Create new root categories and subcategories. You can organize the categories by drag-and-drop.
  2. For multi-stores setup, different stores can have difference sets of root category. After a root category is set up, you can associate it to a store in System > Manage Stores.
  3. You can show the categories in the menu. Only active categories are shown. You can show the category page with products or without, the contents can be set to a static block. You can set this on the _...

Uncaught TypeError: imagecopymerge(): Argument #9 ($pct) must be of type int, string given in .../lib/Varien/Image/Adapter/Gd2.php:570

Uncaught TypeError: imagecopymerge(): Argument #9 ($pct) must be of type int, string given in /.../lib/Varien/Image/Adapter/Gd2.php:570
Stack trace:
#0 /.../lib/Varien/Image/Adapter/Gd2.php(570): imagecopymerge(Object(GdImage), Object(GdImage), 0, 0, 0, 0, 400, 400, '')
#1 /.../lib/Varien/Image.php(197): Varien_Image_Adapter_Gd2->watermark('/home/web/publi...', 0, 0, 30, false)
#2 /.../app/code/core/Mage/Catalog/Model/Product/Image.php(557): Varien_Image->watermark('/home/web/publi...')
#3 /.../app/code/core/Mage/Catalog/Helper/Image.php(362...

Allow Login Customers Only to Add Product to Cart

With system config:
Image+

If that's not what you want, we can do event-observer:

    /**
     * Event 'checkout_cart_product_add_before'
     * @see Mage_Checkout_Model_Cart ::addProduct()
     *
     * @param Varien_Event_Observer $observer
     * @return void
     */
    public function beforeAddToCart(Varien_Event_Observer $observer)
    {
        if (Mage::getSingleton('customer/session')->isLoggedIn()) {
            return;
        }

        /** @var Mage_Catalog_Model_Product $product *...

Prototype.js Removal

This is monumental.
https://github.com/OpenMage/magento-lts/discussions/3645#discussioncomment-7547229

How to redirect in controller by throwing an exception

This whole class Mage_Core_Controller_Varien_Exception has only one reference in the core, see search result.

In the catch, there is a way to redirect or forward or call another action. So how do we make this works? Here's an example:

class Sxxx_Mohe_Model_Observer_Catalog
{
    /**
     * Event 'catalog_controller_category_init_after'
     * @see Mage_Catalog_CategoryController:: _initCategory()
     *
     * Redirect ca...

Add dynamic block contents in category page

In backend > Catalog > Manage Categories, we can configure a category page and put it on the main menu. The page contents are rendered in

app\design\frontend\base\default\template\catalog\category\view.phtml

If we want to render an HTML table in which its data are taken from the database, we would follow these steps:

  1. Create a custom block mymodule/mytable with template mymodule/mytable.phtml.
  2. Whitelist our block for rendering in the frontend: backend > System > Permissions > Blocks
  3. Create a CMS static block: backend > CM...

Add A Grid Column by Layout Update and Observer

Add a Custom Column in sales_flat_order_grid by Layout Update

<layout version="0.1.0">
    <add_order_grid_column_handle>
        <reference name="sales_order.grid">
            <action method="addColumnAfter">
                <columnId>skus</columnId>
                <arguments module="extendedsales" translate="header">
                    <header>SKUs</header>
                    <index>skus</index>
                </arguments>
                <after>status</after>
            </action>
        </reference>
    </add_order_grid...

Installing & Updating OpenMage with Git and Composer

There are 3 machines:

  1. Local Computer Windows OS
  2. Development Server
  3. Production Server

There are 3 repositories

  1. upstream, a fork of OpenMage in GitHub, the default branch is main
  2. origin, the project repo in BitBucket, set default branch to master
  3. local, resides in local computer with remotes called upstream and origin

Create local repo

  1. [local] Parent of root folder (without creating the root folder), git clone the upstream repo. At completion, root folder is created with all the source code from OM. The bra...

How to add a new DB connection

In the module's config.xml:

    <global>
        <resources>
            <tpa_setup>
                <setup>
                    <module>Vendor_Tpa</module>
                </setup>
            </tpa_setup>
            <bot_db>
                <connection>
                    <host><![CDATA[subdomain.rds.aws.com]]></host>
                    <username><![CDATA[some_name]]></username>
                    <password><![CDATA[some_pw]]></password>
                    <dbname><![CDATA[some_db_name]]></dbname>
                    <model...

MySQL Adapter

For read and write adapters, fetchOne(), fetchAll(), fetchAssoc(), fetchRow(), fetchCol(), fetchPairs(), see lib\Zend\Db\Adapter\Abstract.php

Also, standalone class lib\Mage\DB\Mysqli.php has interesting methods.

Zend

For fetchAll(), fetchColumn(), fetchObject(): app/code/core/Zend/Db/Statement.php

By default, fetchAll() returns an array of rows, each of which is an associative array. The keys of the associative array are the columns or column aliases named in the select query.

You can specify a different st...

Usefull Extensions

        "aoepeople/aoe_blackholesession": "Skip creating a real session for bots",
        "aoepeople/aoe_jscsststamp": "Automatic Versioning of JS and CSS files",
        "aoepeople/aoe_scheduler": "Advanced cron scheduling management",
        "aschroder/smtp_pro": "Support for sending emails via SMTP",
        "avstudnitz/fast-simple-import": "Imports products and customers from arrays",
        "colinmollenhour/Perfect_Watermarks": "Replacement for OpenMage's GD2 image adapter with imagemagick",
        "fballiano/magento1-image-clea...

Layout XML Directive - `if helper` and `ifconfig`

The addition of head elements for Vue are dependent on the helper method which returns a bool.

See app\code\core\Mage\Page\Block\Html\Head.php

<layout>
     <default>
        <reference name="head">
            <action method="addItem">
                <type>js</type>
                <name>lib/vue2611dev.js</name>
                <params />
                <if helper="adminpanel/noVue" />
            </action>
            <action method="addItem">
                <type>skin_css</type>
                <name>css/vue.css</name>
    ...

Programmaticaly add attributes to attribute group

/**
 * Add attributes to attibute_group 'CAUTION!!! System Config'.
 */
if ($attrs) {
    $resource = Mage::getResourceSingleton('eav/entity_attribute');
    foreach ($customerGroupIds as $groupCode => $groupId) {
        /** @var Scx_ExtendedCustomer_Model_Attribute_Set $set */
        $set = Mage::getModel('extendedcustomer/attribute_set');
        $set->load($groupId, 'apply_to');
        if (!$set->getId()) {
            continue;
        }
        $agId = Mage::getResourceModel('eav/entity_attribute_group_collection')
           ...

Products are not listed in frontend category page

Backend > System > Index Management > reindex

  1. Product Flat Data (optional)
  2. Category Products

Render Session Messages

In phtml

<?php echo $this->getMessagesBlock()->getGroupedHtml() ?>
// same as
<?php echo $this->getMessagesBlock()->toHtml() ?>

In Controller

$this->_initLayoutMessages('customer/session');

Category Static Block

To render the messages in static block, use catalog or checkout session to add the message.

Mage::getSingleton('catalog/session')->addError($e->getMessage());
// or
Mage::getSingleton('checkout/session')->addError($e->getMessage());

#1067 - invalid default value for created_at or updated_at in table sales_flat_order_item

Alter the columns:

SET sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';
ALTER TABLE `sales_flat_order_item` CHANGE `created_at` `created_at` TIMESTAMP NULL DEFAULT NULL COMMENT 'Created At'; 
ALTER TABLE `sales_flat_order_item` CHANGE `updated_at` `updated_at` TIMESTAMP NULL DEFAULT NULL COMMENT 'Updated At'; 

Collection setOrder

    public function setOrderByVaccDates($boxId, $direction = self::SORT_ORDER_DESC)
    {
        $case = 'CASE WHEN box_id = ' . $boxId . ' THEN vacc_date ELSE vacc_second_date END';
        $this->setOrder($case, $direction);
        return $this;
    }
ORDER BY 
  CASE 
    WHEN box_id = 376 THEN vacc_date ELSE vacc_second_date 
  END 
  DESC

DB Table Upgrade Script

Add Foreign Key

/** @var Mage_Core_Model_Resource_Setup $installer */
$installer = $this;
$installer->startSetup();
/** @var Varien_Db_Adapter_Pdo_Mysql $connection */
$connection = $installer->getConnection();

$table = $installer->getTable('simple/box');
$column = 'clinic_id';

if (!$connection->tableColumnExists($table, $column)) {
    $connection->addColumn($table, $column, [
        'type'      => Varien_Db_Ddl_Table::TYPE_INTEGER,
        'unsigned'  => true,
        'nullable'  => true,
        'comment'   => 'Clinic Id',
  ...

Search in Pagination

When there are input elements for search criteria in frontend grid with pagination block 'page/html_pager', the search params will be lost when the user click on page n. This is because the URL links in the pager do not contain the search params. There are 3 solutions:

Do not Use POST in form

<form class="form-list" id="search_form">

Simple JS Solution

This can be fixed easily with js URLSearchParams.append() by appending the search params to t...

How to Add Guzzle Package Using Composer.

To install, just issue the following PowerShell command at the root of OpenMage:

PS D:\Work\project> composer require guzzlehttp/guzzle:^7.0

Following is deprecated in the latest OpenMage, which will autoload the vendor folder automatically.

First, take a look at app\Mage.php autoload at lines 54-56:

/* Support additional includes, such as composer's vendor/autoload.php files */
foreach (glob(BP . DS . 'app' . DS . 'etc' . DS . 'includes' . DS . '*.php') as $path) {
    include_once $path;
}

So, we can add a f...

Exception Try Catch Block in PHP7

    final public function call($method, $args = [])
    {
        try {
            return $this->_apiCall($method, $args);
        } catch (Custom_Exception $e) {
            throw $e;
        } catch (Throwable $e) {
            throw new Custom_Exception('Unexpected error: '.$e->getMessage(), $e->getCode(), $e);
        }
    }

Add Custom API

Define the API in the custom module app\code\local\{vendor}\{module}\etc\api.xml:

<config>
    <api>
        <resources>
            <member translate="title" module="benefit">
                <model>benefit/api_member</model>
                <title>Member API</title>
                <acl>benefit/member</acl>
                <methods>
                    <!-- Element name must be in lower case, see note 1. -->
                    <check_in translate="title" module="benefit">
                        <title>Check-In</title>
         ...

How to Use Composer Packages in Magento 1 / OpenMage

OpenMage

Install the packages in vendor directory in the root by execute shell command: composer update

For wins:

PHP is not recognized as an internal or external command in command prompt

  1. Search: Edit the system environment variables
  2. Environment Variables ...
  3. System variables > Path > Edit ...
  4. New
  5. Then add D:\Work\wamp64\bin\php\php8.2.5

For Magento 1.9 (Not required for OpenMage)

Create dir vendor in the root and then modify Mage.php:

// in app\Mage.php
// Insert this line or make use of line 57...