I am trying to get breadcrumb path in my controller by using this helper
public function __construct(\Magento\Catalog\Helper\Data $catalogData, ) {
$this->catalogData = $catalogData;
}
$path = $this->catalogData->getBreadcrumbPath();
When I print $path it's giving me an empty array. But when I get this helper function in any product phtml file like this
$helper = $this->helper('\Magento\Catalog\Helper\Data');
$values = $helper->getBreadcrumbPath();
it's giving me the full path in phtml. How can I access this function in my controller as well?
You will get breadcrumbpath in your custom controller by doing this:
namespace Vendor\ModuleName\Controller\Index;
Class ControllerClass extends \Magento\Framework\App\Action\Action{
protected $catalogData;
protected $_pageFactory;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Catalog\Helper\Data $catalogData,
\Magento\Framework\View\Result\PageFactory $pageFactory)
{
$this->catalogData = $catalogData;
$this->_pageFactory = $pageFactory;
return parent::__construct($context);
}
public function execute()
{
$path = $this->catalogData->getBreadcrumbPath();
print_r($path);
return $this->_pageFactory->create();
}
}
Related
There's a way to passing parameters from controller to phtml view using PageFactory class?
Controller code:
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\View\Result\Page;
use Magento\Framework\View\Result\PageFactory;
use MyModule\Services\Service\CurlService;
class Index extends Action implements HttpGetActionInterface
{
protected $resultPageFactory;
protected $curlService;
public function __construct(
Context $context,
PageFactory $resultPageFactory,
CurlService $curlService
) {
parent::__construct($context);
$this->resultPageFactory = $resultPageFactory;
$this->curlService = $curlService;
}
public function execute()
{
if(isset($_GET['action']) && $_GET['action'] == true)
{
$response = json_decode($this->curlService->response());
switch($response->status)
{
case 'ok': $msgReturn = 'Successfull'; break;
default: $msgReturn = 'Error'; break;
}
}
$resultPage = $this->resultPageFactory->create();
$resultPage->setActiveMenu(static::MENU_ID);
$resultPage->getConfig()->getTitle()->prepend(__('Page Title'));
return $resultPage;
}
I need passing $msgReturn using PageFactory to the corresponding view
To add data to your phtml block, simply enter this example in the controller where you set your data.
use Magento\Framework\View\Result\PageFactory;
$page = $this->pageFactory->create();
$block = $page->getLayout()->getBlock('block_alias');
$block->setData('name_var', $data);
And then in the phtml file
$data = $block->getData('name_var');
I try to call a function from a module A to a module B
here is the module A code
namespace A\Epayment\Model;
class Etransactions
{
public function customPayment{
return "test";
}
and module b code
namespace B\Payment\Controller\Index;
class Payment extends \Magento\Framework\App\Action\Action
{
protected $_pageFactory;
protected $_transaction;
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $pageFactory,
\ETransactions\Epayment\Model\Etransactions $transaction
)
{
$this->_pageFactory = $pageFactory;
$this->_transaction = $transaction;
parent::__construct($context);
}
public function execute()
{
echo "Hello World".PHP_EOL;
$foo="a";
echo $foo;
echo $this->_transaction->customPayment();
//echo $this->customPayment();
echo $foo;
exit;
}
}
this code return the "hello world", the first $foo, not the second and doesn't display any error
can someone explain me where is my error ?
EDIT: i didn't change anything but it works fine now.
thanks for the answers anyway
The object you want create the path your are injecting is incorrect.
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $pageFactory,
\A\Epayment\Model\Etransactions $transaction // changes are here
)
{
$this->_pageFactory = $pageFactory;
$this->_transaction = $transaction;
parent::__construct($context);
}
Kindly use exception handling.
try{
$this->_transaction->customPayment();
}catch(Exception $e){
//log your exception here.
}
In Magento, Helper classes are available to use anywhere (Block, Controller, Model, Observer, View). So you should create a method in helper class and call it anywhere by the following way.
Declar the helper class and method: ModuleA\Epayment\Helper\Data.
<?php
namespace ModuleA\Epayment\Helper;
class Data extends \Magento\Framework\App\Helper\AbstractHelper
{
public function yourHelperMethod()
{
# code...
}
}
Call the method:
$helper = $this->_objectManager->create(ModuleA\Epayment\Helper\Data::class);
$helper->yourHelperMethod();
Note: If the object manager is not injected in your class. Please follow the steps below:
1) declare private property:
private $_objectManager;
2) inject in the constructor to initialize:
public function __construct(
\Magento\Framework\ObjectManagerInterface $objectmanager
) {
$this->_objectManager = $objectmanager;
}
3) use in some method:
public function someMethod() {
$helper = $this->_objectManager->create(ModuleA\Epayment\Helper\Data::class);
$helper->yourHelperMethod();
}
I have made a service to get Doctrine connection in my models (Not sure if it is a nice approach but I dont want to pass connection from controller to model constructor each time).
So lets say I want products in my controller
public function getProductsAction(Request $request) {
$product_model = new ProductModel();
return $product_model->getProducts();
}
I have Product model Which will access a helper to get "database_connection"
use AppBundle\Helper\ContainerHelper;
class ProductModel {
function getProducts() {
$helper = new ContainerHelper();
$db = $helper->getDoctrine();
$query = "SELECT * FROM customer_products;";
$statement = $db->prepare($query);
$statement->execute();
$result = $statement->fetchAll(PDO::FETCH_ASSOC);
return $result;
}
}
Now this helper is defined in src/AppBundle/Helper/ContainerHelper.php
namespace AppBundle\Helper;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
class ContainerHelper {
private $container;
public function __construct(Container $container) {
$this->container = $container;
}
public static function getDoctrine() {
$database_connection = $this->container->get('database_connection');
return $database_connection;
}
}
Lets say this service needs "service container" so in app/config/services.yml
services:
app.container_helper:
class: AppBundle\Helper\ContainerHelper
arguments: ['#service_container']
But it gives me error:
Catchable Fatal Error: Argument 1 passed to
AppBundle\Helper\ContainerHelper::__construct() must implement
interface Symfony\Component\DependencyInjection\ContainerInterface,
none given, called in \src\AppBundle\Model\ProductModel.php
on line 148 and defined
While I believe that I have implemented it correctly according to http://symfony.com/doc/current/book/service_container.html and http://anjanasilva.com/blog/injecting-services-in-symfony-2/, its certain that I have missed something or just got the whole bad idea. I need to know if it is a correct concept or what I have missed
While #pavlovich is trying to fix your existing code, I really think you are making this much more convoluted than it has to be. ProductModel itself should be a service with your database connection injected into it.
class ProductModel {
public function __construct($conn) {
$this->conn = $conn;
}
public function getProducts() {
$stmt = $this->conn->executeQuery('SELECT * FROM customer_products');
return $stmt->fetchAll();
}
services:
product_model:
class: AppBundle\...\ProductModel
arguments: ['#database_connection']
// controller.php
$productModel = $this->get('product_model'); // Pull from container
$products = $productModel->getProducts();
Rather than using helpers, I'd recommend using constructor injection and autowiring. It's more safe, future proof and easier to extend and test.
In such case, you'd have to create ProductRepository (more common and standard name for ProductModel) and pass it to controller.
1. Controller
<?php
class SomeController
{
/**
* #var ProductRepository
*/
private $productRepository;
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
public function getProductsAction()
{
return $this->productRepository->getProducts();
}
}
If you have difficulties to register controller as a service, just use Symplify\ControllerAutowire bundle.
2. ProductRepository
// src/AppBundle/Repository/ProductRepository.php
namespace AppBundle\Repository;
class ProductRepository
{
/**
* #var Doctrine\DBAL\Connection
*/
private $connection;
public function __construct(Doctrine\DBAL\Connection $connection)
{
$this->connection = $connection;
}
public function fetchAll()
{
$query = "SELECT * FROM customer_products;";
$statement = $this->connection->prepare($query);
$statement->execute();
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
}
3. Service registration
# app/cofig/servies.yml
services:
product_repository:
class: AppBundle\Repository\ProductRepository
autowire: true
For more you can see similar question with answer here: Symfony 3 - Outsourcing Controller Code into Service Layer
With new version of Symfony 3.3, a new feature is added (Auto-wired Services Dependencies)
https://symfony.com/doc/current/service_container/autowiring.html
https://symfony.com/doc/current/service_container/3.3-di-changes.html
Using this feature, I solved this issue in following way:
Added a new directory /src/AppBundle/Model
Added my model classes in this directory
namespace AppBundle\Modal;
use Doctrine\ORM\EntityManagerInterface;
class ProductModal
{
private $em;
// We need to inject this variables later.
public function __construct(EntityManagerInterface $entityManager)
{
$this->em = $entityManager;
}
// We need to inject this variables later.
public function getProducts()
{
$statement = $this->em->getConnection()->prepare("SELECT * FROM product WHERE 1");
$statement->execute();
$results = $statement->fetchAll();
return $results;
}
}
Added in my app/config/services.yml
AppBundle\Modal\:
resource: '../../src/AppBundle/Modal/*'
public: true
In my controller I can use it like
$products = $this->get(ProductModal::class)->getProducts();
P.S. Dont forget to add use AppBundle\Entity\Product\Product; in controller
Maybe it will be a very lame question, but i just try.
I built my own MVC framework.
In the controller, i am creating a new object, called $Object.
Object class has a private property $id, and a getter getId();
In the controller, i am creating a new View(), what is loading a template file.
So my controllers seems like this:
$View = new View('templateFile.php');
$View->Object = new Object();
$View->show();
If i am editing this in the controller, when typing $View->Object->ge... netbeans automatically try to autocomplete it to getId or offers all methods what starts with "ge".
Cool.
I am editing the template file, where the $this is the View object.
When i type, $this-> and CTLR+Space, there are no suggession.
Is it possible to earn this somehow?
That could be a dream, if i could do this with $this->Object-> and CTRL+Space.
Here are my important pieces of my View class:
public function show() {
echo $this->getViewContent();
}
public function getViewContent() {
$container = null;
$defaultViewHeader = '';
if ($this->showDefaultViewHeader) {
if (file_exists($this->viewsDir . $this->defaultViewHeaderFile)) {
$defaultViewHeader = $this->getContent($this->viewsDir . $this->defaultViewHeaderFile);
} else {
$defaultViewHeader = $this->getContent($this->commonDir . $this->defaultViewHeaderFile);
}
}
$pageContent = $this->getContent($this->file);
if ($this->showDefaultViewHeader) {
$pageContent = $defaultViewHeader . $pageContent;
}
if ($this->showContainer) {
$container = $this->getContent($this->viewsDir . $this->containerFile);
$pageContent = str_replace('[' . HTD_PAGECONTENT . ']', $pageContent, $container);
}
return $pageContent;
}
public function getContent($file) {
ob_start();
include ($file);
$content = ob_get_contents();
ob_end_clean();
return $content;
}
You could specify a variable type to netbeans using the "var" annotation.
Try to add this line into your template :
/* #var $this View */
More on this here https://blogs.oracle.com/netbeansphp/entry/defining_a_variable_type_in
I created a parent CRUD class for several controllers and when I render the script it isn't recognizing the paginator variable I set within the listAction(). The code is from my parent class. For instance, I extend Admin_UserController to create Webapp_Controller_Crud.
class Webapp_Controller_Crud extends Zend_Controller_Action
{
public function init()
{
$actionController = get_class($this);
$actionController = str_replace('Admin_',null,$actionController);
$actionController = str_replace('Controller',null,$actionController);
$this->_actionClassName = $actionController;
$actionController = 'Model_' . $this->_actionClassName;
$this->_actionModel = new $actionController();
}
/**
* #return Zend_Paginator
*/
public function getPaginator()
{
$model = $this->getActionModel();
$adapter = new Zend_Paginator_Adapter_DbSelect($model->select());
$paginator = new Zend_Paginator($adapter);
$paginator->setItemCountPerPage(10);
$page = $this->_request->getParam('page', 1);
$paginator->setCurrentPageNumber($page);
return $paginator;
}
public function listAction()
{
$this->view->paginator = $this->getPaginator();
}
}
You use
$this->getView()->paginator = $this->getPaginator();
Which should be
$this->view->paginator = $this->getPaginator();