I have created module for exporting my product data to script outside of Magento2.
This is my Data.php
<?php
namespace Oktarin\Nabavanet\Helper;
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
protected $markup=1.03;
protected $markup_extra=1.02;
protected $price_limit=1500.00;
protected $pricefile;
protected $prices;
protected $pdv=0.25;
protected $base_url="https://domain.com/index.php/catalog/product/view/id/";
protected $base_image_url="https://domain.com/pub/media/catalog/product";
protected $shipping_cost=35.00;
protected $cats;
protected $appState;
/*
public function __construct(\Magento\Framework\App\Helper\Context $context,\Magento\Framework\App\State $state) {
$this->appState = $state;
parent::__construct($context);
}
public function execute() {
$originalArea = $this->state->getAreaCode();
$this->appState->setAreaCode('frontend');
//reset original code
$this->appState->setAreaCode($originalArea);
}
*/
public function getProductCollection()
{
$collection = $this->_productCollectionFactory->create();
return $collection;
} // end of function getProductCollection
public function makeXml(){
/*
*/
// $originalArea = $this->state->getAreaCode();
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$this->appState= $objectManager->create('Magento\Framework\App\State');
$this->appState->setAreaCode('frontend');
$productCollection = $objectManager->create('Magento\Catalog\Model\ResourceModel\Product\CollectionFactory');
$collection = $productCollection->create()
->addAttributeToSelect('*')
// ->addAttributeToFilter('sku', array('like' => '%702638%'))
->load();
$product=array();
foreach ($collection as $product_data){
if(!empty($product_data->getEntity_id())){
//Load the product categories
$categories1 = $product_data->getCategoryIds();
//Select the last category in the list
$categoryId = end($categories1);
$categoryObject=\Magento\Framework\App\ObjectManager::getInstance();
$category=$categoryObject->create('Oktarin\Nabavanet\Helper\CategoryTree');
$categoryTreepath=$category->getTreeByCategoryId($categoryId);
if(!empty($product_data->getspecial_price())){
$price=$product_data->getspecial_price();
$regular_price=$product_data->getprice();
}
else{
$price=$product_data->getprice();
$regular_price=false;
}
// Dostupnost proizvoda
switch($product_data->getproduct_availability()){
case "3929":
// Po narudžbi
$availability="Po narudžbi";
break;
case "3930":
// Na stanju
$availability="Raspoloživo";
break;
case "3931":
// Zalihe pri kraju
$availability="Raspoloživost potrebno provjeriti";
break;
}
$product[]=array(
"internal_product_id" => $product_data->getEntity_id(),
"sku" => $product_data->getsku(),
"ean" => $product_data->getean(),
"name" => $product_data->getName(),
"url" => $this->base_url.$product_data->getEntity_id()."/s/".$product_data->geturl_key()."/",
"availability" => $availability,
"category" => $categoryTreepath,
"image_url" => $this->base_image_url.$product_data->getimage(),
"additional_image_url" => $this->base_image_url.$product_data->getsmall_image(),
"description" => $product_data->getshort_description(),
"shipping_cost" => $this->shipping_cost,
"regular_price" => $regular_price,
"brand" => $product_data->getbrand(),
"part_number" => $product_data->getpart_number(),
"warranty" => $product_data->getgarancija_proizvoda(),
"price" => $price,
"specialPrice" => $product_data->getspecial_price(),
"tehnickaSpecifikacija" => $product_data->getdescription()
);
} // end of of entity_id isnt empty
} // end of foreach
//reset original code
$this->appState->setAreaCode($originalArea);
return $product;
} // end of function makeXml
} // end class
Method makeXml() I am calling from another script in file nabavanet-export.php that is designed to be run from cron/CLI/command line:
#!/usr/bin/php
<?php
(PHP_SAPI !== 'cli' || isset($_SERVER['HTTP_USER_AGENT'])) && die('cli only');
require_once __DIR__ . "/include.php";
$nabavanet=new Xml();
/* MAGENTO start */
// calling on Magento Helpers
use Magento\Framework\App\Bootstrap;
require '../app/bootstrap.php';
$params = $_SERVER;
$bootstrap = Bootstrap::create(BP, $params);
$obj = $bootstrap->getObjectManager();
$nabava = $obj->get('\Oktarin\Nabavanet\Helper\Data');
// end of Magento Helpers
/* END Magento */
try{
$filename="nabavaexport";
$xml=$nabavanet->createNabavanetXMLfile($nabava->createXml(),$filename);
if($xml==1){
echo "XML ".$filename.".xml generated!\n";
copy($filename.".xml", "../nabavanet/".$filename.".xml");
}
else{
echo "XML ".$filename.".xml not generated\n";
}
} catch (PDOException $e) {
// detaljan ispis grešaka slanjem
// PDOException objekta preko varijable $e
// PDO objekta preko varijable $db
// PDOStatement objekta preko varijable $stmt
showPDOErrors($e, $db_read, $stmt_read);
showPDOErrors($e, $db_write, $stmt_write);
}
?>
Script nabavanet-export.php was working fine when run through browser, however when I run it through command line I get this:
Fatal error: Uncaught Magento\Framework\Exception\LocalizedException: Area code is not set in /usr/www/users/shopyb/vendor/magento/framework/App/State.php:152
Stack trace:
#0 /usr/www/users/shopyb/vendor/magento/framework/Session/SessionManager.php(173): Magento\Framework\App\State->getAreaCode()
#1 /usr/www/users/shopyb/generated/code/Magento/Framework/Session/Generic/Interceptor.php(50): Magento\Framework\Session\SessionManager->start()
#2 /usr/www/users/shopyb/vendor/magento/framework/Session/SessionManager.php(130): Magento\Framework\Session\Generic\Interceptor->start()
#3 /usr/www/users/shopyb/generated/code/Magento/Framework/Session/Generic/Interceptor.php(14): Magento\Framework\Session\SessionManager->__construct(Object(Magento\Framework\App\Request\Http), Object(Magento\Framework\Session\SidResolver\Proxy), Object(Magento\Framework\Session\Config), Object(Magento\Framework\Session\SaveHandler), Object(Magento\Framework\Session\Validator), Object(Magento\Framework\Session\Storage), Object(Magento\Framework\Stdlib\C in /usr/www/users/shopyb/vendor/magento/framework/Session/SessionManager.php on line 175
As you can see I have tried implementing fix as said many times:
public function __construct(\Magento\Framework\App\State $state, $name=null) {
$this->appState = $state;
parent::__construct($name);
}
But this also generated error
So I have tried modifing it like this but without success:
public function __construct(\Magento\Framework\App\Helper\Context $context,\Magento\Framework\App\State $state) {
$this->appState = $state;
parent::__construct($context);
}
I hope someone can give me pointers how to make file nabavanet-export.php run as command line.
I need that outside script because it is depending on other methods required for generating xml.
UPDATE 1
Fix by Sukumar Gorai worked for me however new problem occured, I got this error:
Fatal error: Uncaught Magento\Framework\Exception\NoSuchEntityException: No such entity with id = in /usr/www/users//vendor/magento/framework/Exception/NoSuchEntityException.php:49
The script in Data.php should get product information, and it seems that it gets product without ID?
UPDATE 2
The problem with entity_id was due to false value returned while fetching categroy ids in another class. I have managed to get around it :).
Thank you all for great help!
2 Answers 2
You need to change your script nabavanet-export.php like below:
<?php
(PHP_SAPI !== 'cli' || isset($_SERVER['HTTP_USER_AGENT'])) && die('cli only');
require_once __DIR__ . "/include.php";
$nabavanet=new Xml();
/* MAGENTO start */
// calling on Magento Helpers
use Magento\Framework\App\Bootstrap;
require '../app/bootstrap.php';
$params = $_SERVER;
$bootstrap = Bootstrap::create(BP, $params);
$obj = $bootstrap->getObjectManager();
// Set area code
$state = $obj->get('Magento\Framework\App\State');
$state->setAreaCode('adminhtml');
$nabava = $obj->get('\Oktarin\Nabavanet\Helper\Data');
// end of Magento Helpers
/* END Magento */
try{
$filename="nabavaexport";
$xml=$nabavanet->createNabavanetXMLfile($nabava->createXml(),$filename);
if($xml==1){
echo "XML ".$filename.".xml generated!\n";
copy($filename.".xml", "../nabavanet/".$filename.".xml");
}
else{
echo "XML ".$filename.".xml not generated\n";
}
} catch (PDOException $e) {
// detaljan ispis grešaka slanjem
// PDOException objekta preko varijable $e
// PDO objekta preko varijable $db
// PDOStatement objekta preko varijable $stmt
showPDOErrors($e, $db_read, $stmt_read);
showPDOErrors($e, $db_write, $stmt_write);
}
?>
-
I have tried and got this error
Fatal error: Uncaught TypeError: Argument 1 passed to Magento\Framework\App\Helper\AbstractHelper::__construct() must be an instance of Magento\Framework\App\Helper\Context, instance of Magento\Framework\App\State\Interceptor given, called in /usr/www/users//vendor/magento/framework/ObjectManager/Factory/AbstractFactory.php on line 111 and defined in /usr/www/users//vendor/magento/framework/App/Helper/AbstractHelper.php:84Oktarin– Oktarin2019年06月24日 16:23:06 +00:00Commented Jun 24, 2019 at 16:23 -
This error is in helper class of your. Please check the helper class properly and run the di compile again and then test.Sukumar Gorai– Sukumar Gorai2019年06月24日 16:40:13 +00:00Commented Jun 24, 2019 at 16:40
-
it seems that it is working, after I ran setup:di:compile... however new problem occurs - please see "update" in original questionOktarin– Oktarin2019年06月24日 16:52:51 +00:00Commented Jun 24, 2019 at 16:52
-
Great. Does the error has been fixed of areacode?Sukumar Gorai– Sukumar Gorai2019年06月24日 16:53:39 +00:00Commented Jun 24, 2019 at 16:53
-
Yes - it seems that error has been fixedOktarin– Oktarin2019年06月24日 17:09:30 +00:00Commented Jun 24, 2019 at 17:09
Call AreaCode frontend inside module like this
/** @var \Magento\Framework\App\State **/
private $state;
public function __construct(\Magento\Framework\App\State $state) {
$this->state = $state;
parent::__construct();
}
public function execute() {
$this->state->setAreaCode(\Magento\Framework\App\Area::AREA_FRONTEND); // or \Magento\Framework\App\Area::AREA_ADMINHTML, depending on yexternals
}
Call AreaCode frontend in externel script like this
use Magento\Framework\App\Bootstrap;
require __DIR__ . '/app/bootstrap.php';
$params = $_SERVER;
$bootstrap = Bootstrap::create(BP, $params);
$objectManager = $bootstrap->getObjectManager();
$state = $objectManager->get('Magento\Framework\App\State');
$state->setAreaCode('frontend');
-
do I need to call AreaCode in both locations: module and external script?Oktarin– Oktarin2019年06月24日 16:25:23 +00:00Commented Jun 24, 2019 at 16:25
-
I have setup your code in both locations. Now I get this:
Fatal error: Uncaught ArgumentCountError: Too few arguments to function Magento\Framework\App\Helper\AbstractHelper::__construct(), 0 passed in /usr/www/users/app/code/Oktarin/Nabavanet/Helper/Data.php on line 21 and exactly 1 expected in /usr/www/users/vendor/magento/framework/App/Helper/AbstractHelper.php:84Oktarin– Oktarin2019年06月24日 16:29:58 +00:00Commented Jun 24, 2019 at 16:29