Laravel: Loading initial custom settings class - php

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

Related

ZF2 routing and redirect function in controller

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.

Laravel 4 - created singleton class not found

My journey into Laravel 4 continues. I'm trying to develop a menu that is dynamically created on the master view. To do this I found this article, and I'm trying to implement it.
I've got the code so far but this part appears to be causing a problem:
App::before(function ($request) {
// $myApp Singleton object
App::singleton('myApp', function () {
$app = new stdClass;
$app->title = "downsCMS";
if (Sentry::check()) {
$app->user = Sentry::getUser();
$app->isLogedin = TRUE;
} else {
$app->isLogedin = FALSE;
$app->user = FALSE;
}
return $app;
});
$app = App::make('myApp');
View::share('myApp', $app);
});
WHen I try to run the app I get a class not found 'myApp'
So it appears it's not creating the class. I did a composer dump-autoload but no effect.
I must admit I don't fully understand the ioc so please be gentle. Are there simple steps I am missing here?
Try unwrapping the block of code from within App::before(). Temporarily place the block of code at the top of the routes.php file and see what happens. If this fixes the issue, look into wrapping your code in a "service provider" class. That way it won't "muck up" the routes file, and will be tucked away nicely.
I gave up trying to implement the code - I re-wrote without creating a singleton.
It may not be as efficient but it works for now
Ta

Custom views for errors in CakePHP 2.1

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.

Preventing error pages caching when using Zend_Cache_Backend_Static

We're currently running an app that caches pages to static html files using Zend_Cache_Backend_Static. This works really well, except that our cache is getting filled with hundreds of empty files and folders when incorrect urls are requested. Is there any way to prevent a page being cached if an Exception is being thrown? I was surprised to discover that this wasn't standard behaviour.
I've done a little digging and the ZF code that actually deals with saving out the static html pages is as follows in Zend_Cache_Frontend_Capture:
public function _flush($data) {
$id = array_pop($this->_idStack);
if ($id === null) {
Zend_Cache::throwException('use of _flush() without a start()');
}
if ($this->_extension) {
$this->save(serialize(array($data, $this->_extension)), $id, $this->_tags);
} else {
$this->save($data, $id, $this->_tags);
}
return $data;
}
This function is the output_callback for ob_start. I've tried getting hold of the response object to test for status but it doesn't seem to work inside _flush.
$response = Zend_Controller_Front::getInstance()->getResponse();
if($response->getStatus() == '200') {
// do the save as normal
}
else {
// do nothing
return false;
}
My only other thought was to test the length of $data, only caching if strlen($data) > 0 seems to work but it doesn't feel robust enough.
Update:
Unfortunately by the time we hit the ErrorController the static page has already been written to the cache, so disabling the cache at that point won't work. However it is possible to remove the page based on $_SERVER['REQUEST_URI'], which is what is used as an id when the page is first written. This line can be added to the start of errorAction in the ErrorController:
$this->_helper->cache->removePage($_SERVER['REQUEST_URI'], true);
It works nicely, but I'd prefer not to write the page in the first place!
From further experimentation the problem is not down to standard Zend Framework exceptions that cause 404s (ie. Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE, Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER, Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION) but to my custom exceptions. This is now really obvious now that I think about it, as Zend_Cache_Backend_Static needs to be initialised in the init method of an action controller. Any situation where there is no route, controller or action it won't ever be initialised anyway.
I'm throwing exceptions in existing actions where a user may be querying for a non-existent article. Therefore caching has been enabled in init and the page has been written by the time we hit postDispatch in a Front Controller Plugin (still not sure why this is the case it just is) so I can't cancel at that point. One solution then is to cancel the cache at the point of throwing the exception. The standard method of managing static page caching is using the Zend_Controller_Action_Helper_Cache action helper. I've extended this to add a cancel method like so:
<?php
class Zend_Controller_Action_Helper_PageCache extends Zend_Controller_Action_Helper_Cache {
public function cancel() {
$cache = $this->getCache(Zend_Cache_Manager::PAGECACHE);
$cache->setOption('caching', false);
$cache->getBackend('disable_caching', true);
}
}
My action controller now looks like this:
<?php
class IndexController extends Zend_Controller_Action {
private $_model;
public function init() {
$this->_model = new Model();
// using extended pageCache rather than $this->_helper->cache:
$this->_helper->pageCache(array('index'), array('indexaction'));
}
public function indexAction() {
$alias = $this->_request->getParam('article');
$article = $this->_model->getArticleByAlias($alias);
if(!$article) {
// new cancel method will disable caching
$this->_helper->pageCache->cancel();
throw new Zend_Controller_Action_Exception('Invalid article alias', 404);
}
$this->view->article = $article;
}
}
You should alter your .htaccess file RewriteRules to check for filesizes with option -s
This way if an error should occur when a page is being cached (thus producing a 0 byte file) it won't permanently be stored in the cache.
If you are using the standard ErrorController to handle 404, 500, and unhandled exceptions, and you can get a reference to your cache object from there, you could disable caching from the error handler.
In your error controller (or wherever you would like to cancel caching from), try:
$cache->setOption('caching', false);
When the save() metod of Zend_Cache_Core is called by Zend_Cache_Frontend_Capture::_flush(), it will see the caching option is set to false and it will not actually save the data to the cache and return true.

SOAP Client Error: "Error Fetching Http Headers"

I am trying to use a SOAP Client-Server in my computer and it doesn't look like it is going to work, I am getting this error Error Fetching Http Headers when I try to run my SOAP Client.
I have been looking and the solution that I have encountred is to increase the default_socket_timeout from 60 to 120 seconds and it doesn't work for me, also I have seen another solution that is putting the vhost in my apache KeepAlive Off and that didn't work.
The WSDL is working fine because I try to use it in another computer and it work.
I am running PHP Version 5.3.5-1ubuntu7.4 in Linux Mint using Zend Framework, I hope some of you can help me fix this thank you.
I'm sorry but I don't know what you are using to set up your SOAP service.....
If you can give more information about your SOAP service (poss Zend_Soap given the Zend Framework tag) etc that would be great.
Also, as a quick alternative, you say you've looked at the WSDL on another computer, perhaps try the application in an alternative environment to ensure it's not an environment issue.
May be a simple issue with your client-server code.
UPDATE: Ok so I realised the example I mentioned yesterday wasn't fully implemented so I've hacked something together quickly that you can try to see if it works in your environment.
The code is a mix of something I found here (an example of Zend_Soap_Server) and something from another SO question here (an example of a basic SOAP service test).
I've tested it at my end using ZF 1.11 and the example I'm outlining uses the default Application path you get with a new ZF project (e.g models are in directory application/models so the model shown is headed up Application_Model_Classname).
If it works, you can tweak accordingly....if it doesn't work we can try something else.
Start by creating a new SOAP controller and set the class up like this:
<?php
class SoapController extends Zend_Controller_Action
{
public function init()
{
ini_set("soap.wsdl_cache_enabled", "0"); //disable WSDL caching
$this->_helper->layout()->disableLayout(); //disable the layout
$this->_helper->viewRenderer->setNoRender(); //disable the view
}
public function indexAction ()
{
if (isset($_GET['wsdl'])) {
//return the WSDL
$this->handleWSDL();
} else {
//handle SOAP request
$this->handleSOAP();
}
}
private function handleWSDL ()
{
$strategy = new Zend_Soap_Wsdl_Strategy_AnyType();
$autodiscover = new Zend_Soap_AutoDiscover();
$autodiscover->setComplexTypeStrategy($strategy);
$autodiscover->setClass('Application_Model_SoapService');
$autodiscover->handle();
}
private function handleSOAP ()
{
$server = new Zend_Soap_Server(null,
array('uri' => "http://YOURDOMAIN/soap?wsdl"));
$server->setClass("Application_Model_SoapService");
$server->handle();
}
public function testAction()
{
$client = new Zend_Soap_Client("http://YOURDOMAIN/soap?wsdl");
try {
echo $client->testMethod('test');
} catch (Exception $e) {
echo $e;
}
}
}
In the class above, the WSDL is automatically generated using Zend_Soap_Autodiscover with a SoapService.php file at application/models/SoapService.php used as the template. Note the DocBock comments above each method in your target class are integral to this process.
Next create the SoapService.php file in the default models folder:
<?php
class Application_Model_SoapService
{
/**
* testMethod
*
* #param string $string
* #return string $testSuccess
*/
public function testMethod(string $string)
{
$testSuccess = 'Test successful, the message was: ' . $string;
return $testSuccess;
}
}
If all is working as it should be you can visit:
http://YOURDOMAIN/soap?wsdl
to see the WSDL and visit:
http://YOURDOMAIN/soap/test
to get a success message with the string you specified in the client request within the testAction() code in the SoapController class as part of the message.
Let me know if it's working or not and we can go from there.
I'll be able to have another look on Monday.

Categories