Tuesday, December 8, 2015

Magento 2 Admin url 404 not found

If you create a virtual host in Windows XAMPP server (eg localhost:8081), which points to your magento 2 root, you need to do the following fix, in order to avoid 404 not found, when you access magento admin .

Go to app/code/Magento/Backend/App/Area/FrontNameResolver.php (in line 88)

Replace

$host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : '';


With

$host = isset($_SERVER['HTTP_HOST']) ? parse_url($_SERVER['HTTP_HOST'], PHP_URL_HOST) : '';

Monday, December 7, 2015

Magento 2 Custom Module Database Installation Script



When you setup the module at firstime, setup_module table doesn’t have a setup data for your custom module, then the magento system will checks for the setup_version of the module in its module.xml file

<module name="Quadone_Sample" schema_version="0.0.5" setup_version="1.0.0" />

Then it will execute Setup/InstallSchema.php to create installation script.
app/code/Quadone/Sample/Setup/InstallSchema.php

<?php

namespace Quadone\Sample\Setup;

use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;

class InstallSchema implements InstallSchemaInterface
{
    public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
                        $connection = $setup->getConnection();

        $setup->startSetup();

        /**
         * Create table ‘quadone_sample'
         */
        $table = $connection->newTable(
            $setup->getTable('quadone_sample')
        )->addColumn(
            'qsample_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
            'Quadone Id'
        )->addColumn(
            'name',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            8,
            ['nullable' => false, 'default' => 'default'],
            'Name'
        )->addColumn(
            'email',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            50,
            ['nullable' => false, 'default' => 'default'],
            'Email Id'
        );
        $connection->createTable($table);

        $setup->endSetup();
    }
}

Clear the cache and run bin/magento setup:upgrade

Upgrading Schema

Change the setup_version in module.xml
<module name="Quadone_Sample" schema_version="0.0.5" setup_version="2.0.0" />
System will executes the Setup/UpgradeSchema.php

<?php
namespace Quadone\Sample\Setup;

use Magento\Framework\Setup\UpgradeSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class UpgradeSchema implements UpgradeSchemaInterface
{
    public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context)
    {
            $connection = $setup->getConnection();
        $setup->startSetup();
        if (version_compare($context->getVersion(), '2.0.0', '<')) {
      //2nd parameter is the modified setup_version in module.xml
            $setup->getConnection()->addColumn(
                $setup->getTable(‘quadone_sample’),
                'age',
                [
                    'type' => \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
                    'unsigned' => true,
                    'nullable' => false,
                    'default' => '0',
                    'comment' => 'Age'
                ]
            );
   }
       $setup->endSetup();
    }
}


Friday, June 26, 2015

Magento Change Currency Symbol Position for Spanish users

Magento renders Currency Symbol (eg: $) after the price value in Spanish Store.

Eg: Spanish store renders 15 $, where as English store renders $ 15.

To change the position in Spanish store, Go to lib/Zend/Locale/Data
Edit es.xml

------------------------------------------------------------------------------------------------------------------------
Change the following From

<currencyFormats numberSystem="latn">
<currencyFormatLength>
              <currencyFormat type="standard">
                     <pattern>#,##0.00 ¤</pattern>
              </currencyFormat>
              <currencyFormat type="accounting">
                     <pattern>#,##0.00 ¤</pattern>
              </currencyFormat>
       </currencyFormatLength>
       <unitPattern count="one">{0} {1}</unitPattern>
       <unitPattern count="other">{0} {1}</unitPattern>
</currencyFormats>
To
<currencyFormats numberSystem="latn">
       <currencyFormatLength>
       <currencyFormat type="standard">
              <pattern>¤#,##0.00</pattern>
       </currencyFormat>
       <currencyFormat type="accounting">
              <pattern>¤#,##0.00</pattern>
       </currencyFormat>
       </currencyFormatLength>
       <unitPattern count="one">{0} {1}</unitPattern>
       <unitPattern count="other">{0} {1}</unitPattern>
</currencyFormats>
--------------------------------------------------------------------------------------------------------------------------
Clear Magento Cache


Monday, April 6, 2015

Magento Custom API Method to Login as a Customer

Magento API provides the following customer functions

Customer.list
Customer.create
Customer.info
Customer.update
Customer.delete

But if your iPhone/Android app has to provide the login feature for your customer, Core API doesn’t have such function to check login with the username and password provided to it.
Following steps may help you to create a custom Magenot API method to check login.
This method will takes username and password as input parameters and provides status (success, if customer exists, otherwise failed) and CustomerId (customer id, if status success, otherwise 0).

Step 1:
Create app/etc/modules/<NameSpace>_Customservice.xml with the following content
<?xml version="1.0"?>
<config>
  <modules>
    <[NameSpace]_Customservice>
      <active>true</active>
      <codePool>local</codePool>           
                        <depends>
                <Mage_Api />
            </depends>
      <version>0.1.0</version>
    </[NameSpace]_Customservice>
  </modules>
</config>
Step 2:
Create app/code/local/[NameSpace]/Customservice/etc/config.xml with the following content
<?xml version="1.0"?>
<config>
  <modules>
    <[NameSpace]_Customservice>
      <version>0.1.0</version>
    </[NameSpace]_Customservice>
  </modules>
  <global>
    <helpers>
      <customservice>
        <class>[NameSpace]_Customservice_Helper</class>
      </customservice>
    </helpers>
                <models>
                  <customservice>
                                <class>[NameSpace]_Customservice_Model</class>
                                <resourceModel>customservice_mysql4</resourceModel>
                  </customservice>
                </models>
  </global>
</config>
Create app/code/local/[NameSpace]/Customservice/etc/api.xml with the following content
<?xml version="1.0"?>
<config>
    <api>
        <resources>
            <customservice_fcustomer translate="title" module="customservice">
                <title>Custom Service API</title>
                <acl>fcustomservice_api</acl>
                <model>customservice/fcustomer_api</model>
                <methods>                   
                                                                                <checkLogin translate="title" module="customservice">
                        <title>login</title>
                        <method>checkLogin</method>
                        <acl>fcustomer/checklogin</acl>
                    </checkLogin>
                                </methods>
            </customservice_fcustomer>
        </resources>
      
         <resources_alias>
            <fcustomer>customservice_fcustomer</fcustomer>
        </resources_alias>
        
        <acl>
            <resources>
                <customservice_fcustomer translate="title" module="customservice">
                    <title>Custom Service</title>
                    <sort_order>2000</sort_order>                   
                                                                                <checklogin translate="title" module="customservice">
                        <title>login</title>
                    </checklogin>
                </customservice_fcustomer>
                                    </resources>
        </acl>
        <v2>
            <resources_function_prefix>
                <customservice_fcustomer>fcustomer</customservice_fcustomer>
             </resources_function_prefix>
        </v2>    
    </api>
</config>
Create app/code/local/[NameSpace]/Customservice/etc/wsdl.xml with the following content
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns:typens="urn:{{var wsdl.name}}" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
             xmlns="http://schemas.xmlsoap.org/wsdl/"
             name="{{var wsdl.name}}" targetNamespace="urn:{{var wsdl.name}}">
    <types>
        <schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:Magento">
            <import namespace="http://schemas.xmlsoap.org/soap/encoding/"
                    schemaLocation="http://schemas.xmlsoap.org/soap/encoding/"/>
            <complexType name="loginStatusEntity">
                <all>
                    <element name="status" type="xsd:string" minOccurs="1" />
                    <element name="customer_id" type="int" minOccurs="1" />
                </all>
            </complexType>
         </schema>
     </types>      
    <message name="fcustomerCheckLoginRequest">
        <part name="sessionId" type="xsd:string"/>
        <part name="email" type="xsd:string"/>
        <part name="password" type="xsd:string"/>
    </message>
    <message name="fcustomerCheckLoginResponse">
        <part name="result" type="typens:loginStatusEntity"/>
    </message>
    <portType name="{{var wsdl.handler}}PortType">
        <operation name="fcustomerCheckLogin">
            <documentation>Customer Login</documentation>
            <input message="typens:fcustomerCheckLoginRequest"/>
            <output message="typens:fcustomerCheckLoginResponse"/>
        </operation>
    </portType>
    <binding name="{{var wsdl.handler}}Binding" type="typens:{{var wsdl.handler}}PortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
        <operation name="fcustomerCheckLogin">
            <soap:operation soapAction="urn:{{var wsdl.handler}}Action"/>
            <input>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded"
                           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </input>
            <output>
                <soap:body namespace="urn:{{var wsdl.name}}" use="encoded"
                           encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
            </output>
        </operation>
    </binding>
</definitions>
Step 3:
Create app/code/local/[NameSpace]/Customservice/Model/Fcustomer/Api.php with the following script
<?php
class [NameSpace]_Customservice_Model_Fcustomer_Api extends Mage_Api_Model_Resource_Abstract
{       
                /** @var Mage_Customer_Model_Session */
                protected $_customerSession = null;
               
                  public function checkLogin($email, $password)
                                {
                                                $customer = Mage::getModel("customer/customer");
                                                $customer->setWebsiteId('1');
                                                $customer->loadByEmail($email);
                                               
                                               
                                                if($this->validateHash($password, $customer->getPasswordHash()))
                                                                return array("status"=>"success","customer_id"=>$customer->getId());
                                               
                                                return array("status"=>"failed","customer_id"=>0);
                    }
                    public function validateHash($password, $hash)
                    {
                                $hashArr = explode(':', $hash);
                   
                                switch (count($hashArr)) {
                                                case 1:
                                                                return md5($password) === $hash;
                                                case 2:
                                                                return md5($hashArr[1] . $password) === $hashArr[0];
                                }
                    }
}
Create app/code/local/[NameSpace]/Customservice/Model/Fcustomer/Api/V2.php with the following script
<?php
class [NameSpace]_Customservice_Model_Fcustomer_Api_V2 extends [NameSpace]_Customservice_Model_Fcustomer_Api
{
}

Your API method is ready.
How to Use this Custom Method

Examples
Request Example SOAP V1
$client = new SoapClient('http://magentohost/api/soap/?wsdl');
$session = $client->login('apiUser', 'apiKey');

$result = $client->call($session, 'fcustomer.checkLogin',array(‘email’=>’xxxx@xyz.com’,’password’=>’123456’));
var_dump ($result);

Request Example SOAP V2 (List of All Customers)
$proxy = new SoapClient('http://magentohost/api/v2_soap/?wsdl'); // TODO : change url
$sessionId = $proxy->login('apiUser', 'apiKey'); // TODO : change login and pwd if necessary

$result = $proxy-> fcustomerCheckLogin($sessionId,"xxxx@xyz.com","123456");

var_dump($result);