The following problem I am facing, error look likes this;
An error occurred
An error occurred during execution; please try again later.
Additional information:
Zend\Mvc\Exception\DomainException
File: .../vendor/zendframework/zendframework/library/Zend/Mvc/Controller/Plugin/Url.php:63
Message:
Url plugin requires that controller event compose a router; none found
I never faced this problem while I am trying to redirect from my controller. Lets say I implement the following function for redirection in my controller, which produces the error above;
public function __construct()
{
# Get user identity
$auth = new AuthenticationService();
if ($auth->hasIdentity()) {
$this->identity = $auth->getIdentity();
} else {
$this->redirect()->toRoute('admin/login');
}
}
The routing does exist as I can reach site.com/admin/login/ .. login is a child of admin so notation must be good. I am wondering what's going wrong and how to fix this issue or even, where to look for it would be a great starting point as well.
Thanks!
If you look at the error looks like you cant use the redirect plugin during the constructions of controller.
Url plugin requires that controller event compose a router; none found
might better to put that code in the onDispatch function like this.
public function onDispatch(MvcEvent $e)
{
# Get user identity
$auth = new AuthenticationService();
if ($auth->hasIdentity()) {
$this->identity = $auth->getIdentity();
} else {
return $this->redirect()->toRoute('admin/login');
}
return parent::onDispatch($e);
}
remember to return the redirect as otherwise the action will still be executed.
Related
I have a LoginController where I do my usual login operation with combination of an email address and a password associated with the account.
I have separated my Hybridauth related code into a separate controller named OauthController where I have all my Hybridauth magic and where my callback / endpoint resides.
In the OauthController I check if user's email from the specified provider is already registered, and in either case I try to login that user with $this->Auth->setUser(object).
Whenever, or whatever from the $this->Auth is called, I get a response stating:
Session was already started
I have browser through CakePHP 3 code and found the following statement in:
vendor/cakephp/cakephp/src/Network/Session.php (335)
public function start()
{
if ($this->_started) {
return true;
}
if ($this->_isCLI) {
$_SESSION = [];
$this->id('cli');
return $this->_started = true;
}
if (session_status() === \PHP_SESSION_ACTIVE) {
throw new RuntimeException('Session was already started');
}
...
And that's the point in code where that message is thrown at me.
Now, as I browsed through the Hybridauth code itself, I have found following in:
vendor/hybridauth/hybridauth/src/Storage/Session.php (46)
public function __construct()
{
if (session_id()) {
return;
}
if (headers_sent()) {
throw new RuntimeException('HTTP headers already sent to browser and Hybridauth won\'t be able to start/resume PHP session. To resolve this, session_start() must be called before outputing any data.');
}
if (! session_start()) {
throw new RuntimeException('PHP session failed to start.');
}
}
And both of them call session_start, one before the other, although CakePHP's part is blocking me.
I have tried removing !session_start() check from Hybridauth, but then Hybridauth doesn't know where to read out it's thingies it needs to read.
So, as a demonstrator, I am trying to achieve this in OauthController:
<?php
namespace App\Controller;
use Hybridauth\Hybridauth;
class OauthController extends AppController
{
public function callback($provider)
{
try {
$hybridauth = new Hybridauth($config);
// additional mystery code
$hybridauth->authenticate();
if($everything_okay) {
$this->Auth->setUser($userObject); // and this is the point of failure
return $this->redirect('/account'); // and this never happends... :(
}
}
}
}
Any help, ideas, insights on how to deal with this are all welcome!
Simply start the CakePHP session manually before using the Hybridauth library, so that it bails out at the session_id() check and picks up the existing session.
For example in your controller:
$this->getRequest()->getSession()->start();
// in CakePHP versions before 3.6/3.5
// $this->request->session()->start();
My aim is to fetch application concerned settings from a config file and load them to a DataSource and use it in the application. In the process of loading from the config file, I'd want to validate them and if they fail, Laravel should stop it's boot up. Sounds a bit a confusion, I guess. Hope the following example would help:
My config file appSettings.php is in app/config, just an example:
return array(
'color' => '',
'texture' => 'mixed',
'layers' => 3
);
My DataSource class DataSource.php is in source/DataSource.php, just an example:
public class DataSource {
public static function load() {
if (Config::get('appSettings.color').empty()) {
return false;
}
// Do other validations etc..
return true;
}
public function getColorForRoom($roomId) {
return something;
}
}
Now, what is the right place for me to call the method DataSource::load()?. DataSource will be used in the application for fetching certain data like calling getColorForRoom($roomId) function.
Maybe in intializers or somewhere I could do:
if (!DataSource::load()) {
// Stop booting up Laravel
}
But I'm not sure where exactly to put this and how to stop the application from booting up.
Possible Solutions
I'm not sure if this can be the right way, but it seems like a good approach:
In my bootstrap/start.php:
require $app['path.base'] . '/app/source/DataSource.php';
if (!DataSource::load()) {
Log::error("Failed to load datasource");
throw new ApplicationBootException();
}
Again, I'm not entirely sure about this. Is this a bad solution or are there any other better solutions?
The other possible solutions are loading DataSource from routes or filters as mentioned in the below answers.
Well - you could put it in the filters.php file
App::before(function($request)
{
if (!DataSource::load()) {
App::abort(500, 'Config is not correctly set');
}
});
Why don't you throw a custom Exception? Then you can catch this exception and redirect to a view that is like a 404 but custom to your application?
public class DataSource {
public static function load() {
if (Config::get('appSettings.color').empty()) {
throw new ApplicationBootException();
}
// Do other validations etc..
return true;
}
}
You could place this in the routes file.
App::error(function(ApplicationBootException $exception, $code){
//.. your code here to handle the exception
});
Please note I am just using ApplicationBootException as an example. You would have to create this class and have it extend Exception
I try to set up a maintenance page with ZF2 but it's not working. I put a maintenance.html page in public folder (www) and in my onbootstrap function I've got the following code :
$config = $e->getApplication()->getServiceManager()->get('Appli\Config');
if($config['maintenance']) {
$response = $e->getResponse();
$response->getHeaders()->addHeaderLine('Location', '/maintenance.html');
$response->setStatusCode(503);
return $response;
}
I enter the if cause $config['maintenance'] is true but it's not displaying my maintenance.html page as expected. Instead it displays the page asked.
Is there something wrong about my redirection ?
You appear to be attempting to short-circuit the request directly from your onBootstrap method. That won't work, at that point the route hasn't been resolved and the controller hasn't been dispatched. Essentially, all you're doing is pre-populating the response, only for it to be over-written once the request is routed and dispatched.
If you want to affect the response, you'll need to listen to one of the other MvcEvents. It seems you want to do this before a controller is dispatched, so the place to do it would be in the EVENT_ROUTE, ideally with a high priority so it happens before the route is resolved by the router (saves wasted processing resolving a route that will never be dispatched).
public function onBootstrap(MvcEvent $e)
{
$events = $e->getApplication()->getEventManager();
$events->attach(MvcEvent::EVENT_ROUTE, function (MvcEvent $r) {
$config = $r->getApplication()->getServiceManager()->get('Appli\Config');
if ($config['maintenance']) {
$response = $r->getResponse();
// set content & status
$response->setStatusCode(503);
$response->setContent('<h1>Service Unavailable</h1>');
// short-circuit request...
return $response;
}
}, 1000);
}
You can't set a 503 status code and redirect - the two are mutually exclusive, as redirects use a 3xx status code.
You probably want something more like:
$response->setContent(file_get_contents('/path/to/maintenance.html'));
$response->setStatusCode(503);
I started to create a small application using codeigniter framework
and i have dowloaded Facebook connect from github after creating my application inside facebook, at this moment all work alright my only problem is getUser() always return 0
i have create a facebook.php inside application/config/
alse i have extracting facebook.php & base_facebook.php inside application/libraries/
this is my code
class Welcome extends CI_Controller {
private $data = array();
public function index() {
$this->data['loginUrl'] = $this->facebook->getLoginUrl();
$this->data['userId'] = $this->facebook->getUser();
$this->load->view('welcome_message', $this->data);
}
}
in autoload
i have :
$autoload['libraries'] = array('database','session','facebook');
so why getUser() return 0 and how can i fix this problem
thx
on base_facebook.php, find the makeRequest() method, and, inside the function, find this line:
$opts = self::$CURL_OPTS;
Immediately following it, add:
$opts[CURLOPT_SSL_VERIFYPEER] = false;
or read from here
It does this, sometimes. I've never worked out why, but there is a simple solution that I now always follow.
As opposed to asking for getUser, ask for api(/me) wrapped in a try catch block. If this fails, user is not logged in/token is invalid. If it works the user is logged in, and you get the user id from the resultant array.
You're probably saving a call, as you'll ask for /me anyway. Just remember the try catch for error trapping!
I'm looking to create custom views for errors in CakePHP 2.1
I have been reading the following question here: CakePHP 2.0 - How to make custom error pages?
BUT there are somethings that do not work as expected!
1.) Exceptions and errors do not seem to be the same thing, as if I go to a bogus url I get the built in 404 page but if I manually do a notfound exception in the controller it will call the custom view... Why is this? I thought all errors in Cake went through the exceptions?
2.) I'm trying to render a view rather than ACTUALLY redirect the user...
so for example:
App::uses('ExceptionRenderer', 'Error');
class AppExceptionRenderer extends ExceptionRenderer {
public function notFound($error) {
$this->controller->redirect(array('controller' => 'errors', 'action' => 'error404'));
}
}
instead of that redirect I'm trying:
$this->controller->layout = null;
$this->controller->render('/Errors/error404');
but all I end up with is a blank page... Why is this? And this only happens when doing manual exceptions?
Can anyone answer these two questions please? Thanks
I've finally managed to get this figured out! Looking at the code from github, I've managed to get it working. Here's my AppExceptionRenderer.php:
App::uses('ExceptionRenderer', 'Error');
class AppExceptionRenderer extends ExceptionRenderer {
public function missingController($error) {
$this->controller->render('/Errors/error404', 'layout');
$this->controller->response->send();
}
public function missingAction($error) {
$this->missingController($error);
}
}
If you want to call your controller callbacks you'll have to do something like this as well before beforeFilter():
$this->controller->beforeFilter();
That $this->controller->response->send(); line is the kicker. Hopefully this works for you!
This is simple,
public function notFound($error) {
$this->_outputMessage('error404');
}
That's all what you need to do
Simply:
throw new NotFoundException;
See the example code in the documentation about "Built in Exceptions".
App::uses('ExceptionRenderer', 'Error'); should not be required.
For an individual view edit View/Errors/error400.ctp.