ScopeConfigInterface as parameter in constructor - Magento 2 - magento2

I'm working with Magento 2, I'm still new.
I have this constructor inside a controller class:
public function __construct(Context $context, PageFactory $pageFactory, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig)
{
$this->pageFactory = $pageFactory;
$this->scopeConfig = $scopeConfig;
return parent::__construct($context);
}
It was working until I added the ScopeConfigInterface.
Now, when I load my page I get this error:
Recoverable Error: Argument 3 passed to xxx\Customer\Controller\Login::__construct() must implement interface Magento\Framework\App\Config\ScopeConfigInterface, none given, called in...
Any ideas? Thanks.

I deleted folder:
"var/generation"
And that solved the problem.

Related

Typo3 Extension Scheduler Command Controller

here is a problem I encountered in TYPO3 Extension Development.
I've written an TYPO3-extension. It will display in browser the news in the DB. But I'd like to configure a scheduler task to recurrently update the news in the DB to be displayed.
In writing this scheduler task I've used a Command Controller.
namespace Vendor\Extension\Command;
class CheckNewsCommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandController
{
public function simpleCommand()
{
$newsRepository = $this->objectManager->get( \Vendor\Extension\Domain\Repository\NewsRepository::class );
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($newsRepository);
$all_news = $newsRepository->findAll();
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($all_news);
}
}
But the variable $all_news contains nothing, it equals to NULL !!! That means, the findAll() Function of the NewsRepository does NOT work at all !!!
In comparison, I've also used this NewsRepository in a normal Controller Class: Vendor\Extension\Controller\NewsController
namespace Vendor\Extension\Controller;
class NewsController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
public function listAction()
{
$newsRepository = $this->objectManager->get( \Etagen\EtSocNewsSt\Domain\Repository\NewsRepository::class );
$all_news = $newsRepository->findAll();
\TYPO3\CMS\Extbase\Utility\DebuggerUtility::var_dump($all_news);
}
And, in the NewsController, the function NewsRepository::findAll() DID really work, and returned all records in the DB.
So, who can tell me, why the Repository function will ONLY work in the class Vendor\Extension\Controller\NewsController, but NOT work in the class Vendor\Extension\Command\CheckNewsCommandController ?
The answer is EASY: You need to define the storagePid for your news records in the CommandController OR change the settings of the NewsRepository to IGNORE the storagePid.
How to set the storagePid for CommandController:
https://worksonmymachine.org/blog/commandcontroller-and-storagepid
How to set the repository to ignore storagePid:
http://typo3.sascha-ende.de/docs/development/database/how-to-ignore-the-page-id-pid-in-repository-database-query/

Redirect if request authorization is failed in Laravel 5.5

I am trying to redirect request if authorization is failed for it. I have following code:
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){ /* ... */}
public function failedAuthorization() {
return redirect('safepage');
}
}
By default I am redirected to the 403 error page, but I would like to specify some specific route. I noticed that method failedAuthorization() is run, but redirect() method does not work...
Previously this code worked well with Laravel 5.1 but I used forbiddenResponse() method to redirect wrong request. How can I fix it with new LTS version?
Looks like it is impossible to redirect() directly from the custom ValidateRequest class. The only solution that I found is create custom exception and than handle it in the Handler class. So, now it works with following code:
Update: The method redirectTo() was updated to make solution work on Laravel 6.x and higher
app/Requests/ValidateRequest.php
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){
return [];
}
public function failedAuthorization() {
$exception = new NotAuthorizedException('This action is unauthorized.', 403);
throw $exception->redirectTo("safepage");
}
}
app/Exceptions/NotAuthorizedException.php
<?php
namespace App\Exceptions;
use Exception;
class NotAuthorizedException extends Exception
{
protected $route;
public function redirectTo($route) {
$this->route = $route;
abort(Redirect::to($route));
}
public function route() {
return $this->route;
}
}
and app/Exceptions/Handler.php
...
public function render($request, Exception $exception){
...
if($exception instanceof NotAuthorizedException){
return redirect($exception->route());
}
...
}
So, it works, but much more slower than I expected... Simple measuring shows that handling and redirecting take 2.1 s, but with Laravel 5.1 the same action (and the same code) takes only 0.3 s
Adding NotAuthorizedException::class to the $dontReport property does not help at all...
Update
It runs much more faster with php 7.2, it takes 0.7 s
If you are revisiting this thread because in 2021 you are looking to redirect after failed authorization here's what you can do:
You cannot redirect from the failedAuthorization() method because it is expected to throw an exception (check the method in the base FormRequest class that you extend), the side effect of changing the return type is the $request hitting the controller instead of being handled on FormRequest authorization level.
You do not need to create a custom exception class, neither meddle with the Laravel core files like editing the render() of app/Exceptions/Handler.php, which will pick up the exception you threw and by default render the bland 403 page.
All you need to do is throw new HttpResponseException()
In the Laravel reference API we can see its job is to "Create a new HTTP response exception instance." and that is exactly what we want, right?
So we need to pass this Exception a $response. We can pass a redirect or JSON response!
Redirecting:
protected function failedAuthorization()
{
throw new HttpResponseException(response()->redirectToRoute('postOverview')
->with(['error' => 'This action is not authorized!']));
}
So we are creating a new instance of the HttpResponseException and we use the response() helper, which has this super helpful redirectToRoute('routeName') method, which we can further chain with the well known with() method and pass an error message to display on the front-end.
JSON:
Inspired by this topic
throw new HttpResponseException(response()->json(['error' => 'Unauthorized action!'], 403));
Thats'it.
You don't have to make ANY checks for validation or authorization in your controller, everything is done in the background before it hits the controller. You can test this by putting a dd('reached controller'); at the top of your controller method and it shouln't get trigered.
This way you keep your controller thin and separate concerns :)
Sidenote:
forbiddenResponse() has been replaced after lara 5.4 with failedAuthorization()
You can do through a middleware/policy i think. I don't know if you can do it from the validation.
You can override the function from FormRequest like this below:
/**
* Handle a failed authorization attempt.
*
* #return void
*
* #throws \Illuminate\Auth\Access\AuthorizationException
*/
protected function failedAuthorization()
{
throw new AuthorizationException('This action is unauthorized.');
}
And redirect where you want.

ZF3: set terminal / render view without layout (Zend-Expressive)

I have installed the skelleton app from ZF3 'zend-expressive'. In the routing config I have configured a few routes. Some of these routes should return a response without the layout. In ZF2 I simply used the ViewModel on which you could call "setTerminal". But now the ViewModel is not directy available in the Action, as it is nested as private property of the ZendViewRenderer. I cannot figure out how I can set the terminal, so the output is rendered without layout.
I have tried various options in the routing configuration, such as adding keys 'terminal', 'terminate' and 'may_terminate' with value true. Also have tried to make a seperate Factory, but ended up with the same problem that I cannot reach the ViewModel.. It also did not work to make a seperate ViewModel in the Action, when I setTerminal on true, and pass the object as 2nd parameter in the 'render' method of the ZendViewRenderer object, it fails when passing 'renderModal' of the same object: "Cannot render; encountered a child marked terminal"..
There must be a simple configuration that I am overlooking, so my question is. Does anyone know how I can set the view on terminal?
Hope that I explained my problem well. Many thanks in advance.
My solution!
Yes! I found a "solution". Instead of pushing into terminal setting of the ViewModal, I have implemented a new layout called "layout/terminal". This layout only outputs the variable $content. Reference: https://github.com/zendframework/zend-expressive/issues/360
To use this layout you should add a new Factory into the configuration.
<?php
namespace Factory;
use Interop\Container\ContainerInterface;
use Zend\Expressive\Template\TemplateRendererInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\View\Model\ViewModel;
class RenderWithoutTemplate implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$template = $container->has(TemplateRendererInterface::class)
? $container->get(TemplateRendererInterface::class)
: null;
$r = new \ReflectionClass($template);
$view = new ViewModel();
$view->setTerminal(true); // Does not affect any render behaviour (?)
$view->setTemplate('layout/terminal');
$prop = $r->getProperty('layout');
$prop->setAccessible(true);
$prop->setValue($template, $view);
return $template;
}
}
public function indexAction(){
return $this->getResponse();
}

zend controller can't specify layout

I have this code
class PagamentoController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
}
public function indexAction()
{
$model_pagamenti = new Model_Pagamento();
$this->_helper->layout->setLayout('/crudabstract/index.phtml');
$this->view->render('/crudabstract/index.phtml');
}
...
and when i run /pagamento/index
i get this error
An error occurred
Application error
Exception information:
Message: script 'pagamento/index.phtml' not found in path (C:/www/www/abc/application/views\scripts/)
Stack trace:
why won't it work ? it's not supposed to be looking for "pagamento/index.phtml", but for "/crudabstract/index.phtml"
thanks
found out how in my own code
$this->_helper->viewRenderer('crudabstract/'.$this->_request->getActionName(), null, true);
the error message states that there is no view script defined for the index action. when you define a controller, zend framework will automatically look for a corresponding view file which is not being found in your case. so create a corresponding view file in
application/views/script/pagamento/index.phtml
and it should work.

ZEND Controllers -- How to call an action from a different controller

I want to display a page that has 2 forms. The top form is unique to this page, but the bottom form can already be rendered from a different controller. I'm using the following code to call the action of the other form but keep getting this error:
"Message: id is not specified"
#0 .../library/Zend/Controller/Router/Rewrite.php(441): Zend_Controller_Router_Route->assemble(Array, true, true)
My code:
First controller:
abc_Controller
public function someAction()
{
$this->_helper->actionStack('other','xyz');
}
Second controller:
xyz_Controller
public function otherAction()
{
// code
}
Desired results:
When calling /abc/some, i want to render the "some" content along with the xyz/other content. I think I followed the doc correctly (http://framework.zend.com/manual/en/zend.controller.actionhelpers.html) but can't find any help on why that error occurs. When I trace the code (using XDebug), the xyz/other action completes ok but when the abc/some action reaches the end, the error is thrown somewhere during the dispatch or the routing.
Any help is greatly appreciated.
You can accomplish this in your phtml for your someAction. So in some.phtml put <?php echo $this->action('other','xyz');?> this will render the form found in the otherAction of XyzController
The urge to do something like this is an indication you're going about it in totally the wrong way. If you have the urge to re-use content, it should likely belong in the model. If it is truly controller code it should be encapsulated by an action controller plugin
In phtml file u can use the $this->action() ; to render the page and that response would be added to current response ..
The syntax for action is as follows::
public function action($action, $controller, $module = null, array $params = array())
You can create new object with second controller and call its method (but it`s not the best way).
You can extend your first controller with the second one and call $this->methodFromSecond(); - it will render second form too with its template.
BTW - what type of code you want to execute in both controllers ?
Just an update. The error had absolutely nothing to do with how the action was being called from the second controller. It turns out that in the layout of the second controller, there was a separate phtml call that was throwing the error (layout/abc.phtml):
<?php echo $this->render('userNavigation.phtml') ?>
line of error:
echo $this->navigation()->menu()->renderMenu(...)
I'll be debugging this separately as not to muddy this thread.
Thanks to Akeem and hsz for the prompt response. I learned from your responses.
To summarize, there were 3 different ways to call an action from an external controller:
Instantiate the second controller from the first controller and call the action.
Use $this->_helper->actionStack
In the phtml of the first controller, action('other','xyz');?> (as Akeem pointed out above)
Hope this helps other Zend noobs out there.
Hm I can't find and idea why you need to use diffrent Controlers for one view. Better practise is to have all in one Controller. I using this like in this example
DemoController extends My_Controller_Action() {
....
public function indexAction() {
$this->view->oForm = new Form_Registration();
}
}
My_Controller_Action extends Zend_Controller_Action() {
public function init() {
parent::init();
$this->setGeneralStuf();
}
public function setGeneralStuf() {
$this->view->oLoginForm = new Form_Login();
}
}
This kind of route definition:
routes.abc.route = "abc/buy/:id/*"
routes.abc.defaults.controller = "deal"
routes.abc.defaults.action = "buy"
routes.abc.reqs.id = "\d+"
requires a parameter in order to function. You can do this with actionStack but you can also specify a default id in case that none is provided:
$this->_helper->actionStack('Action',
'Controller',
'Route',
array('param' => 'value')
);
routes.abc.defaults.id = "1"
For Me this worked like a charm
class abcController extends Zend_Controller_Action
{
public function dashBoardAction()
{
$this->_helper->actionStack('list-User-Data', 'xyz');
}
}
class XyzController extends Zend_Controller_Action {
public function listUserDataAction()
{
$data = array('red','green','blue','yellow');
return $data;
}
}