Here is a way you could do this. The trick seems to be using the API instead of using the Object Manager. With the object manager you can call a 'create' method to pull in the product object and load the product with the product id, but so far most advise warns against this method. Using the API you can call the getById()
method on the object and get back a unique product object each time you call it. Theoretically with should preform better then using the object manager, and if the object manager goes away at some point, you aren't re-writing code (Alan Storm goes into the issues with the object manager here: Magento 2 Object Manager).
Doing it any other way you will run into Magento's automatic singleton design and will never be able to get the link url for each product, as the first product loaded by ID with set that value and it will persist in the page.
Here is the block (in a module you would put this in {{vender-namespace}}/{{module-name}}/Block/Product.php)
<?php
namespace {{vender-namespace}}/{{module-name}}\Block;
use Magento\Framework\View\Element\Template;
class Product extends Template {
public function __construct(
Template\Context $context,
\Magento\Catalog\Block\Product\View\abstractView $product,
\Magento\Catalog\Api\ProductRepositoryInterface $productModel,
array $data = []
) {
parent::__construct($context, $data);
$this->_product = $product;
$this->_productModel = $productModel;
}
protected function _prepareLayout() {
return parent::_prepareLayout();
}
protected function _getCurrentProduct() {
return $this->_product->getProduct();
}
protected function _getCurrentCategory() {
$currentCategories = $this->_getCurrentProduct()->getCategoryCollection();
foreach ($currentCategories as $currentCategory) {
return $currentCategory;
}
}
protected function _getProductById($id) {
$_product = $this->_productModel->getById($id);
return $_product;
}
public function getPreviousProductId() {
$_categoryArray = $this->_getCurrentCategory();
$_productCollectionIds = $this->_getCurrentCategory()->getProductCollection()->getAllIds();
if ($_categoryArray) {
$_currentProductId = $this->_getCurrentProduct()->getId();
$_currentProductCollectionId = array_search($_currentProductId, $_productCollectionIds);
$_previousProductId = $_productCollectionIds[$_currentProductCollectionId - 1];
if ($_previousProductId) {
return $_previousProductId;
}
return false;
}
return false;
}
public function getNextProductId() {
$_categoryArray = $this->_getCurrentCategory();
$_productCollectionIds = $this->_getCurrentCategory()->getProductCollection()->getAllIds();
if ($_categoryArray) {
$_currentProductId = $this->_getCurrentProduct()->getId();
$_currentProductCollectionId = array_search($_currentProductId, $_productCollectionIds);
$_nextProductId = $_productCollectionIds[$_currentProductCollectionId + 1];
$_product = $this->_productModel;
if ($_nextProductId) {
return $_nextProductId;
}
return false;
}
return false;
}
public function getPreviousProductUrl() {
$_previousProductUrl = $this->_getProductById($this->getPreviousProductId())->getProductUrl();
return $_previousProductUrl;
}
public function getNextProductUrl() {
$_nextProductUrl = $this->_getProductById($this->getNextProductId())->getProductUrl();
return $_nextProductUrl;
}
public function getPreviousProductName() {
$_previousProductName = $this->_getProductById($this->getPreviousProductId())->getName();
return $_previousProductName;
}
public function getNextProductName() {
$_nextProductName = $this->_getProductById($this->getNextProductId())->getName();
return $_nextProductName;
}
public function getPreviousProductImage() {
$_previousProductImage = $this->_getProductById($this->getPreviousProductId())->getImage();
return $_previousProductImage;
}
public function getNextProductImage() {
$_nextProductImage = $this->_getProductById($this->getNextProductId())->getImage();
return $_nextProductImage;
}
}
For displaying this on the front end you need to make a .xml file that will display the template on the product page top (in a module you would put this in {{vender-namespace}}/{{module-name}}/view/frontend/layout/catalog_product_view.xml)
<?xml version="1.0"?>
<page layout="1column" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceContainer name="content">
<block class="{{vender-namespace}}/{{module-name}}\Block\Product" name="custom.product.pagination" template="{{vender-namespace}}/{{module-name}}/::product/product-pagination.phtml" before="-" />
</referenceContainer>
</body>
</page>
And then in your phtml file (in a module you would put this in {{vender-namespace}}/{{module-name}}/view/frontend/template/product/product-pagination.phtml)
<?php
$previousProductUrl = $block->getPreviousProductUrl();
$nextProductUrl = $block->getNextProductUrl();
$previousProductName = $block->getPreviousProductName();
$nextProductName = $block->getNextProductName();
$previousProductImage = $block->getPreviousProductImage();
$nextProductImage = $block->getNextProductImage();
$previousImage = $this->getBaseUrl() . 'pub/media/catalog/product' . $previousProductImage;
$nextImage = $this->getBaseUrl() . 'pub/media/catalog/product' . $nextProductImage;
?>
<div class="product-pagination">
<div class="previous-product" style="float: left;">
<a href="<?php echo $previousProductUrl; ?>">
<img src="<?php echo $previousImage; ?>" alt="<?php echo $previousProductName; ?>" height="75" width="75" />
<p><?php echo $previousProductName; ?></p>
<button type="submit" title="Previous Product" class="action primary to-prev-product">
<span>← prev</span>
</button>
</a>
</div>
<div class="next-product" style="float: right;">
<a href="<?php echo $nextProductUrl; ?>">
<img src="<?php echo $nextImage; ?>" alt="<?php echo $nextProductName; ?>" height="75" width="75" />
<p><?php echo $nextProductName; ?></p>
<button type="submit" title="Next Product" class="action primary to-next-product">
<span>next →</span>
</button>
</a>
</div>
</div>
Of course there is a lot more you can do with this as far as theme integration and styling. But for a proof of concept, this will get you there.