4

I don't get how this works. I'm trying to edit the header of my Magento 2 store (Magento_Theme/templates/html/header.phtml) and I'm trying to retrieve my customers lastname like this:

<span data-bind="text: new String('<?php echo $block->escapeHtml(__('Welcome %1', '%1'));?>').replace('%1', customer().lastname)"></span>

It works fine when it says 'fullname' instead of lastname: this shows my full name. It also works fine when I replace it with 'firstname': this shows my first name. Why doesn't it work with last name and what is the right way to get all the customer data here?

5 Answers 5

8

TLDR;

You need to create a plugin in a custom module to override the Magento\Customer\CustomerData\Customer class. In your module's di.xml file:

app/code/Vendor/LastName/Plugin/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">
    <type name="Magento\Customer\CustomerData\Customer">
        <plugin name="vendor_lastnameplugin"
                type="Vendor\LastName\Plugin\CustomerData\Customer"
                sortOrder="10"
                disabled="false"/>
    </type>
</config>

And then in your override file:

app/code/Vendor/LastName/Plugin/CustomerData/Customer.php

<?php
namespace ForeverNew\Criteo\Plugin\CustomerData;
use Magento\Customer\Helper\Session\CurrentCustomer;

class Customer
{
    protected $currentCustomer;

    public function __construct(
        CurrentCustomer $currentCustomer
    ) {
        $this->currentCustomer = $currentCustomer;
    }

    public function afterGetSectionData(\Magento\Customer\CustomerData\Customer $subject, $result)
    {
        $customer = $this->currentCustomer->getCustomer();
        $result['lastname'] = $customer->getLastname();
        return $result;
    }
}

This will create a customer().lastname for you to use in your template file.

More Background

There isn't a customer().lastname, and it's a bit convoluted as to how to add that in. The template (magento/module-theme/view/frontend/templates/html/header.phtml) is calling in the customer component with this script:

<script type="text/x-magento-init">
    {
        "*": {
            "Magento_Ui/js/core/app": {
                "components": {
                    "customer": {
                        "component": "Magento_Customer/js/view/customer"
                    }
                }
            }
        }
    }
</script>

But looking that file (after all the preamble) you will find only this line:

this.customer = customerData.get('customer');

But even following that call, you still don't get to the right file you need to edit. Turns out that the array that is defining the values for the customer() element is coming from a php file that is populating an array that is then getting used to define these values:

vendor/magento/module-customer/CustomerData/Customer.php

public function getSectionData()
{
    if (!$this->currentCustomer->getCustomerId()) {
        return [];
    }
    $customer = $this->currentCustomer->getCustomer();
    return [
        'fullname' => $this->customerViewHelper->getCustomerName($customer),
        'firstname' => $customer->getFirstname(),
    ];
}

Adding into the return array will add in any value that you can then access in the knockout template with dot notation, i.e. customer().anythingYouWant. So in this case you need to create a plugin to add to the return array with that value populated. It's just by luck that you already have access to $customer->getLastname() in that class, so you don't have to import any other class or data to get what you are looking for.

As a side note, this is a pain to test in the browser. Since the data that is set here is stored in the session, you have to clear that when testing out values. If customer().lastname is set, even if you change it in the php, the value that is set will persist. So you can log out or just clear mage-cache-storage in the browser and go on with your day.

2
  • I was trying to get Customer group Id by 'groupId' => $customer->getGroupId() but it doesn't work, any idea where to go from there? ( I know it works elsewhere by using $block->escapeHtml($block->getCustomer()->getGroupId() )
    – ne0nlight
    Jul 25, 2018 at 17:57
  • $subject->currentCustomer is a protected property. Try injecting Magento\Customer\Helper\Session\CurrentCustomer $currentCustomer in the constructor, then use $customer = $this->currentCustomer->getCustomer(); in the afterGetSectionData method. Sep 12, 2018 at 4:11
4

Completely no need to add tons of backend plugins here... Just initiate JS on your span with

<span data-mage-init='{"js/customerGreeting":{}}'>

and in your theme in web/js/customerGreeting.js

define([
    "jquery", "Magento_Customer/js/customer-data"
], function($, customerData) {
    "use strict";
    return function (config, element) {
        var firstname = customerData.get('customer')().firstname;
        if (typeof (firstname) === "undefined") {
            customerData
               .reload('customer')
               .then(function() { 
                  const firstname = customerData.get('customer')().firstname;
                  if (firstname) {
                    $(element).text('Hi, ' + firstname); 
                  }
               });
        }
    };
});

If you want just last name, you can extract it via regex or split(' ')

1
  • 2
    reload returns a Promise, so you can skip the setInterval logic and replace it with customerData.reload('customer').then(function() { customerData.get('customer')().firstname; }) The setInterval method will have code on the page running every half-second until firstname comes back. Or forever if the web request fails for any reason.
    – will_in_wi
    May 19, 2020 at 21:48
1

for me it didn't worked like that, instead to get the Customer Name, I used the following code:

echo $customerSession->getCustomerData()->getFirstname();

if anyone finds this useful.

1
  • I used Shoaib Rehman Answer with this one inside if condition. Jun 19, 2018 at 14:31
0

First You need to create a object instance:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();

& then try this:

    <?php
        $customerSession = $objectManager->get('Magento\Customer\Model\Session');
        if($customerSession->isLoggedIn()) { 
            echo   $customerSession->getCustomer()->getName()."<br/>";  // get  Full Name 
            echo   $customerSession->getCustomer()->getFirstname()."<br/>";  // get Customer First name
            echo   $customerSession->getCustomer()->getLastname()."<br/>";  // get  Last Name
        }    
    ?>
2
  • getLastName still doesn't show the last name. It appears to be empty. Also I'm still wondering why this doesn't seem to be working through databindings. Jan 31, 2017 at 12:52
  • 3
    never user object manager in templates.
    – Marius
    Jun 7, 2017 at 7:08
-1

In your PHP file do:

protected $_customerSession;
protected $_customer;

public function __construct(
    \Magento\Catalog\Block\Product\Context $context,
    \Magento\Customer\Model\SessionFactory $customerSession,
    \Magento\Customer\Model\Session $customer,
    array $data = []
) {
    $this->_customerSession = $customerSession->create();
    $this->_customer = $customer;
    parent::__construct($context, $data);
}

public function getCustomerLastName(){
    if($this->_customerSession->isLoggedIn()){
        return $this->_customer->getCustomerData()->getLastName();
    }
}

And then in your phtml file you can simply call the function by doing:

$blockObj = $block->getLayout()->createBlock('Company\Module\Block\Index\FileName');
$blockObj->getCustomerLastName();

This will check if the user if logged in. And if so then it will pull their last name.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.