1

I need a second order view with some information about the order and additional upload functionality.

enter image description here

I tried to replicate how they did the "view order" page but although my links point to the right adress /sales/order/upload/order_id/128/ it leads to an error 404 page.

vendor/module/frontend/sales_order_upload.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">
    <update handle="customer_account"/>
    <update handle="sales_order_item_renderers"/>
    <update handle="sales_order_item_price"/>
    <update handle="sales_order_info_links"/>
    <body>
        <referenceContainer name="page.main.title">
            <block class="Magento\Sales\Block\Order\Info" name="order.status" template="order/order_status.phtml"/>
            <block class="Magento\Sales\Block\Order\Info" name="order.date" template="order/order_date.phtml"/>
            <container name="order.actions.container" htmlTag="div" htmlClass="actions-toolbar order-actions-toolbar">
                <block class="Magento\Sales\Block\Order\Info\Buttons" as="buttons" name="sales.order.info.buttons" cacheable="false"/>
            </container>
        </referenceContainer>
        <referenceContainer name="sales.order.info.buttons">
            <block class="Magento\Sales\Block\Order\Info\Buttons\Rss" as="buttons.rss" name="sales.order.info.buttons.rss" cacheable="false"/>
        </referenceContainer>
        <referenceContainer name="content">
            <block class="Vendor\Module\Block\Order\Upload" name="sales.order.upload" cacheable="false" after="sales.order.info.links">
                <block class="Magento\Sales\Block\Order\Items" name="order_items" template="order/items.phtml">
                    <block class="Magento\Framework\View\Element\RendererList" name="sales.order.items.renderers" as="renderer.list"/>
                    <block class="Magento\Sales\Block\Order\Totals" name="order_totals" template="order/totals.phtml">
                        <arguments>
                            <argument name="label_properties" xsi:type="string">colspan="4" class="mark"</argument>
                            <argument name="value_properties" xsi:type="string">class="amount"</argument>
                        </arguments>
                        <block class="Magento\Tax\Block\Sales\Order\Tax" name="tax" template="order/tax.phtml"/>
                    </block>
                </block>
            </block>
            <block class="Magento\Sales\Block\Order\Info" as="info" name="sales.order.info" after="sales.order.upload"/>
        </referenceContainer>
        <block class="Magento\Framework\View\Element\Template" name="additional.product.info" template="Magento_Theme::template.phtml"/>
    </body>
</page>

vendor/module/Controller/Order/Upload.php

<?php

namespace Vendor\Module\Controller\Order;

use Magento\Sales\Controller\OrderInterface;

class Upload extends \Vendor\Module\Controller\AbstractController\Upload implements \Magento\Sales\Controller\OrderInterface
{
}

vendor/module/Controller/AbstractController/Upload.php

<?php

namespace vendor\module\Controller\AbstractController;

use Magento\Framework\App\Action;
use Magento\Framework\View\Result\PageFactory;

abstract class Upload extends Action\Action

{

protected $orderLoader;

protected $resultPageFactory;


public function __construct(
    Action\Context $context,
    Magento\Sales\Controller\AbstractController\OrderLoaderInterface $orderLoader,
    PageFactory $resultPageFactory
) {
    $this->orderLoader = $orderLoader;
    $this->resultPageFactory = $resultPageFactory;
    parent::__construct($context);
}

/**
 * Uploader page
 *
 * @return \Magento\Framework\Controller\ResultInterface
 */
public function execute()
{
    $result = $this->orderLoader->load($this->_request);
    if ($result instanceof \Magento\Framework\Controller\ResultInterface) {
        return $result;
    }

    $resultPage = $this->resultPageFactory->create();

    $navigationBlock = $resultPage->getLayout()->getBlock('customer_account_navigation');
    if ($navigationBlock) {
        $navigationBlock->setActive('sales/order/history');
    }
    return $resultPage;
}
}

vendor/module/Block/Order/Upload.php

<?php

namespace Vendor\Module\Block\Order;

use Magento\Customer\Model\Context;

/**
 * Sales order upload block
 */
class Upload extends \Magento\Framework\View\Element\Template
{

protected $_template = 'order/upload.phtml';

protected $_coreRegistry = null;

protected $_customerSession;

protected $_paymentHelper;

public function __construct(
    \Magento\Framework\View\Element\Template\Context $context,
    \Magento\Framework\Registry $registry,
    \Magento\Framework\App\Http\Context $httpContext,
    \Magento\Payment\Helper\Data $paymentHelper,
    array $data = []
) {
    $this->_paymentHelper = $paymentHelper;
    $this->_coreRegistry = $registry;
    $this->httpContext = $httpContext;
    parent::__construct($context, $data);
    $this->_isScopePrivate = true;
}


    protected function _prepareLayout()
    {
        $this->pageConfig->getTitle()->set(__('Order # %1', $this->getOrder()->getRealOrderId()));
        $infoBlock = $this->_paymentHelper->getInfoBlock($this->getOrder()->getPayment(), $this->getLayout());
        $this->setChild('payment_info', $infoBlock);
    }

    /**
     * @return string
     */
    public function getPaymentInfoHtml()
    {
        return $this->getChildHtml('payment_info');
    }

    /**
     * Retrieve current order model instance
     *
     * @return \Magento\Sales\Model\Order
     */
    public function getOrder()
    {
        return $this->_coreRegistry->registry('current_order');
    }

    /**
     * Return back url for logged in and guest users
     *
     * @return string
     */
    public function getBackUrl()
    {
        if ($this->httpContext->getValue(Context::CONTEXT_AUTH)) {
            return $this->getUrl('*/*/history');
        }
        return $this->getUrl('*/*/form');
    }

    /**
     * Return back title for logged in and guest users
     *
     * @return \Magento\Framework\Phrase
     */
    public function getBackTitle()
    {
        if ($this->httpContext->getValue(Context::CONTEXT_AUTH)) {
            return __('Back to My Orders');
        }
        return __('View Another Order');
    }

    /**
     * @param object $order
     * @return string
     */
    public function getInvoiceUrl($order)
    {
        return $this->getUrl('*/*/invoice', ['order_id' => $order->getId()]);
    }

    /**
     * @param object $order
     * @return string
     */
    public function getShipmentUrl($order)
    {
        return $this->getUrl('*/*/shipment', ['order_id' => $order->getId()]);
    }

    /**
     * @param object $order
     * @return string
     */
    public function getCreditmemoUrl($order)
    {
        return $this->getUrl('*/*/creditmemo', ['order_id' => $order->getId()]);
    }
}

vendor/module/view/frontend/order/upload.phtml

<div class="order-details-items ordered">
    <?php $_order = $block->getOrder() ?>

    <div class="order-title">
        <strong><?php /* @escapeNotVerified */ echo __('Items Ordered') ?></strong>
        <?php if ($_order->getTracksCollection()->count()) : ?>
            <?php echo $block->getChildHtml('tracking-info-link') ?>
        <?php endif; ?>
    </div>

    <?php echo $block->getChildHtml('order_items') ?>

    <?php if ($this->helper('Magento\GiftMessage\Helper\Message')->isMessagesAllowed('order', $_order) && $_order->getGiftMessageId()): ?>
    <div class="block block-order-details-gift-message">
        <div class="block-title"><strong><?php /* @escapeNotVerified */ echo __('Gift Message for This Order') ?></strong></div>
        <?php $_giftMessage = $this->helper('Magento\GiftMessage\Helper\Message')->getGiftMessageForEntity($_order); ?>
        <div class="block-content">
            <dl class="item-options">
                <dt class="item-sender"><strong class="label"><?php /* @escapeNotVerified */ echo __('From') ?></strong><?php echo $block->escapeHtml($_giftMessage->getSender()) ?></dt>
                <dt class="item-recipient"><strong class="label"><?php /* @escapeNotVerified */ echo __('To') ?></strong><?php echo $block->escapeHtml($_giftMessage->getRecipient()) ?></dt>
                <dd class="item-message"><?php /* @escapeNotVerified */ echo $this->helper('Magento\GiftMessage\Helper\Message')->getEscapedGiftMessage($_order) ?></dd>
            </dl>
        </div>
    </div>
    <?php endif; ?>

    <div class="actions-toolbar">
        <div class="secondary">
            <a class="action back" href="<?php /* @escapeNotVerified */ echo $block->getBackUrl() ?>">
                <span><?php /* @escapeNotVerified */ echo $block->getBackTitle() ?></span>
            </a>
        </div>
    </div>
</div>

Where did I go wrong, or how is magento 2 actually supposed to resolve such a url?

2

Change

=> vendor/module/Controller/AbstractController/Upload.php


namespace vendor\module\Controller\AbstractController;

use Magento\Framework\App\Action;
use Magento\Framework\View\Result\PageFactory;

abstract class Upload extends Action\Action

{

    protected $orderLoader;

    protected $resultPageFactory;


    public function __construct(
        Action\Context $context,
        \Magento\Sales\Controller\AbstractController\OrderLoaderInterface $orderLoader,
        PageFactory $resultPageFactory
    ) {
        $this->orderLoader = $orderLoader;
        $this->resultPageFactory = $resultPageFactory;
        parent::__construct($context);
    }

    /**
     * Uploader page
     *
     * @return \Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->orderLoader->load($this->_request);
        if ($result instanceof \Magento\Framework\Controller\ResultInterface) {
            return $result;
        }

        $resultPage = $this->resultPageFactory->create();

        $navigationBlock = $resultPage->getLayout()->getBlock('customer_account_navigation');
        if ($navigationBlock) {
            $navigationBlock->setActive('sales/order/history');
        }
        return $resultPage;
    }
}

=> vendor/module/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="sales">
            <module name="vendor_module" before="Magento_Sales" />
        </route>
    </router>
</config>
1
  • Thank you for the answer! It worked, I'll have to research a bit more how routes.xml works.
    – TrytoFly
    Oct 13 '17 at 11:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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