Given you are in a BE or CLI context (e.g. sending emails via extbase command controller task), the following worked up to 7 LTS for rendering a fluid standalone view:
$view = $this->objectManager->get(StandaloneView::class);
$view->setTemplatePathAndFilename('/Absolute/Path/To/Template.html');
$view->setFormat('html');
$view->getRequest()->setControllerExtensionName('Myextensionname');
return trim($view->render());
However, in 8 LTS, this throws the following exception:
Tried resolving a template file for controller action "Standard->index" in format ".html", but none of the paths contained the expected template file… No paths configured.
As suggested in the wiki page at https://wiki.typo3.org/How_to_use_the_Fluid_Standalone_view_to_render_template_based_emails#Usage_in_TYPO3_8.7, I tried setting layout and partial root paths for the view:
$view->setLayoutRootPaths(['EXT:Myextensionname/Resources/Private/Layouts/']);
$view->setPartialRootPaths(['EXT:Myextensionname/Resources/Private/Partials/']);
However, this won't do the trick.
Digging a bit deeper, I could imagine that one would have to set the controller and action name, e.g. by setting the controller context, but that does not seem to be a solid solution as multiple other class instances are tied to it.
What is the correct way to render fluid standalone views in 8 LTS?
Here an example from our current webproject where we want to show a simple note in backend context based on a FLUID HTML in TYPO3 8.7
protected function renderMarkup(): string
{
$standaloneView = GeneralUtility::makeInstance(StandaloneView::class);
$standaloneView->getRequest()->setControllerExtensionName('in2template');
$templatePathAndFile = 'EXT:in2template/Resources/Private/Templates/Tca/ToolbarNoteEmptyFields.html';
$standaloneView->setTemplatePathAndFilename(GeneralUtility::getFileAbsFileName($templatePathAndFile));
$standaloneView->assign('toolbar', 'toolbarstuff');
return $standaloneView->render();
}
StandaloneView likes to receive all template paths (partial, template and layout root paths) so if you don't already provide all of them, you should do so. The reason being that the naming "Standalone" refers to the view being tied neither to a specific MVC action nor a specific extension context.
That said, if you use 8.7.5 there's a chance you are hit by a regression that is going to be solved by https://review.typo3.org/#/c/53917/ so it might be worth checking that out before you do a major refactoring. Technically the StandaloneView can be operated like a TemplateView with extension context, it's just not officially supported behavior and TYPO3 may not consistently apply all of the context you expect.
In my 8.7 extension I use the following code to get the StandaloneView:
$extbaseFrameworkConfiguration = $this->configurationManager->getConfiguration(ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
/** #var StandaloneView $emailView */
$emailView = $this->objectManager->get(StandaloneView::class);
$emailView->getRequest()->setControllerExtensionName($controllerExtensionName);
$emailView->getRequest()->setPluginName($pluginName);
$emailView->getRequest()->setControllerName($controllerName);
$emailView->setTemplateRootPaths($extbaseFrameworkConfiguration['view']['templateRootPaths']);
$emailView->setLayoutRootPaths($extbaseFrameworkConfiguration['view']['layoutRootPaths']);
$emailView->setPartialRootPaths($extbaseFrameworkConfiguration['view']['partialRootPaths']);
$emailView->setTemplate('Email/' . ucfirst($templateName));
$emailView->assignMultiple($variables);
$emailBody = $emailView->render();
In my function I gave the $controllerExtensionName, $pluginName and $controllerName as parameter with default values, so that other controllers/plugins can use this function, too.
I have been using Eloquent as a standalone package in Slim Framework 2 successfully.
But now that I want to make use of Illuminate\Support\Facades\DB since I need to show some statistics by getting the info from 2 tables and using a Left Join and a Counter from the database like this:
use Illuminate\Support\Facades\DB;
$projectsbyarea = DB::table('projects AS p')
->select(DB::raw('DISTINCT a.area, COUNT(a.area) AS Quantity'))
->leftJoin('areas AS a','p.area_id','=','a.id')
->where('p.status','in_process')
->where('a.area','<>','NULL')
->orderBy('p.area_id');
I get the following error:
Type: RuntimeException
Message: A facade root has not been set.
File: ...\vendor\illuminate\support\Facades\Facade.php
Line: 206
How can I solve it?
So far I have found out, in this link that I need to create a new app container and then bind it to the Facade. But I haven't found out how to make it work.
This is how I started the rest of my Eloquent and working fine:
use Illuminate\Database\Capsule\Manager as Capsule;
$capsule = new Capsule();
$capsule->addConnection([
'my' => $app->config->get('settings'),
/* more settings ...*/
]);
/*booting Eloquent*/
$capsule->bootEloquent();
How do I fix this?
Fixed
As #user5972059 said, I had to add $capsule->setAsGlobal();//This is important to make work the DB (Capsule) just above $capsule->bootEloquent();
Then, the query is executed like this:
use Illuminate\Database\Capsule\Manager as Capsule;
$projectsbyarea = Capsule::table('projects AS p')
->select(DB::raw('DISTINCT a.area, COUNT(a.area) AS Quantity'))
->leftJoin('areas AS a','p.area_id','=','a.id')
->where('p.status','in_process')
->where('a.area','<>','NULL')
->orderBy('p.area_id')
->get();
You have to change your code to:
$Capsule = new Capsule;
$Capsule->addConnection(config::get('database'));
$Capsule->setAsGlobal(); //this is important
$Capsule->bootEloquent();
And at the beginning of your class file you have to import:
use Illuminate\Database\Capsule\Manager as DB;
I have just solved this problem by uncommenting $app->withFacades(); in bootstrap/app.php
Had the same issue with laravel 8. I replaced
use PHPUnit\Framework\TestCase;
with:
use Tests\TestCase;
Try uncommenting in app.php $app->withFacades();
Do not forget to call parent::setUp(); before.
fails
public function setUp(): void {
Config::set('something', true);
}
works
public function setUp(): void {
parent::setUp();
Config::set('something', true);
}
One random problem using phpUnit tests for laravel is that the laravel facades have not been initialized when testing.
Instead of using the standard PHPUnit TestCase class
class MyTestClass extends PHPUnit\Framework\TestCase
one can use
class UserTest extends Illuminate\Foundation\Testing\TestCase
and this problem is solved.
I got this error after running:
$ php artisan config:cache
The solution for me was to delete the /bootstrap/cache/config.php file. I'm running Laravel 5.5.
The seems to arise in multiple situation, and not just about facades.
I received the following message while running tests using PHPUnit v.9.5.4, PHP v.8.0.3 and Lumen v. 8.2.2:
PHP Fatal error: Uncaught RuntimeException: A facade root has not
been set. in path_to_project/vendor/illuminate/support/Facades/Facade.php:258
And that happened although I had apparently already configured my app.php to enable facades ($app->withFacades();), still I received this error message whenever I tried to run tests using Illuminate\Support\Facades\DB. Unfortunately, none of the other answers helped me.
This error was actually been thrown due to my configs in phpunit.xml, which didn't point to my app.php file, where I actually enabled facades.
I just had to change
<phpunit (...OTHER_PARAMS_HERE) bootstrap="vendor/autoload.php">
to
<phpunit (...OTHER_PARAMS_HERE) bootstrap="bootstrap/app.php">
Hope it helps.
wrong way
public function register()
{
$this->app->bind('Activity', function($app)
{
new Activity;
});
}
right way 👍
public function register()
{
$this->app->bind('Activity', function($app)
{
return new Activity;
});
}
---------------------------------- don't forget return
Upgrade version for php, I encountered this error while calling the interface.
$ php artisan config:cache
Deleting the /bootstrap/cache/config.php file is a very effective way.
In my project, I managed to fix this issue by using Laravel Dependency Injection when instantiating the object. Previously I had it like this:
$class = new MyClass(
new Client(),
env('client_id', 'test'),
Config::get('myapp.client_secret')
);
The same error message happened when I used Laravel env() and Config().
I introduced the Client and env in the AppServiceProvider like this:
$this->app->bind(
MyClass::class,
function () {
return new MyClass(
new Client(),
env('client_id', 'test')),
Config::get('myapp.client_secret')
);
}
and then instantiated the class like this:
$class = app(MyClass::class);
See more from https://laravel.com/docs/5.8/container .
In my case, for a while a ran a PHP project in PHP version 8, and that time I used some PHP 8 features like param definition and method's multiple return type declarations supported by only PHP 8 and above. When I downgraded from PHP 8 to PHP 7.4 I faced this issue. After removing the return types and param hinting the problems are gone.
Tested on Laravel 8.78
tests/bootstrap.php
<?php
use Illuminate\Foundation\Bootstrap\RegisterFacades;
use Illuminate\Foundation\Bootstrap\LoadConfiguration;
require_once __DIR__ . '/../vendor/autoload.php';
$app = require_once __DIR__ . '/../bootstrap/app.php';
(new LoadConfiguration())->bootstrap($app);// <------- Required for next line
(new RegisterFacades())->bootstrap($app);// <------- Add this line
Here is yet another instance of this error, happened to me after upgrading Laravel 8 to 9.
I had feature tests with a #dataProvider to supply data to those tests. Some of the data supplied by the data provider methods came from an application service. It was being initialised like this:
/**
* #dataProvider myDataProvider
*/
public function testSomeStuff(...)
{
...
}
public function myDataProvider()
{
$myService = app(Service::class); // This is trouble
return [
['test1_data' => $myService::SOME_CONSTANT],
[...],
...
];
}
This worked under Laravel 8, but not in Laravel 9. All other solutions listed in this SO thread were checked and were correctly set up.
The problem is that the application is not being inititialised until after the data provider method is run. It was presumably initialised before this stage in the Laravel 8 install. So app(Service::class) was failing due to it using facades internally.
One workaround could be to force the application to initialise earlier, in the data provider function: $this->createApplication(). I would not recommend this due to potential side effects of the test parts running in the wrong order, though it does appear to work when I tried it.
Best solution is to avoid accessing any part of the application functionality in the data provider methods. In my case it was easy to replace $myService::SOME_CONSTANT with MyService::SOME_CONSTANT after making sure those constants were public.
Hopefully this will help somebody suddenly hitting this problem running feature tests after a Laravel 9 upgrade.
If you recently upgrade Laravel on Homestead & VirtualBox environment or do not find any reason that causing please be sure your Vagrant is up to date.
Referance
I had Taylor lock this thread. The past several replies have restated the solution, which is to Upgrade to Virtualbox 6.x, the thread is locked to prevent other issues that are not related from being dogpiled on here.
#melvin's answer above works correctly.
In case someone is wondering about it, the mistake people do is to choose Yes when VSCode asks them if they are making a Unit Test. Remember, Unit Tests should really be unit tests, independent of other application features (models, factories, routes; basically anything that would require the Laravel app to be fired up). In most scenarios, people really actually want to make Feature Tests and therefore should answer No to the above question. A feature test inherits from Tests\TestCase class (which takes care of firing up Laravel app before running the test) unlike unit tests that inherit from the class PHPUnit\Framework\TestCase which use just PHPUnit and are therefore much faster.
credit with thanks to #Aken Roberts's answer here.
From Laravel Documentation: Generally, most of your tests should be feature tests. These types of tests provide the most confidence that your system as a whole is functioning as intended.
I have a view helper being called in my layout that works fine in the default module, but I get an exception when I am in another module.
I have already changed my app.ini to use the default layout across all modules by setting:
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
And searching here and google provided me with another app.ini setting to add the view helper path for all modules:
resources.view.helperPath.Zend_View_Helper = APPLICATION_PATH "/views/helpers"
However instead of fixing the problem, that additional setting causes the Zend Exception to become a WSOD.
Without that second app.ini setting, I see the layout and get this exception:
Plugin by name 'AutoScript' was not found in the registry; used paths: Admin_View_Helper_: /Applications/XAMPP/xamppfiles/htdocs/dad/application/modules/admin/views/helpers/ Zend_View_Helper_: Zend/View/Helper/:./views/helpers/
With the helperPath.Zend_View_Helper ini setting I get a WSOD with the following:
Fatal error: Uncaught exception 'Zend_Loader_PluginLoader_Exception' with message 'Plugin by name 'AutoScript' was not found in the registry; used paths: Zend_View_Helper_: Zend/View/Helper/:./views/helpers/'
It appears the plugin loader is looking in public/views/helpers/ for the AutoScript.php file even though it should be using the APPLICATION_PATH value as a prefix.
My layout invocation looks like this
<?php $this->AutoScript(); ?>
My AutoScript.php file's class is defined in application/views/helpers/
class Zend_View_Helper_AutoScript extends Zend_View_Helper_Abstract {
public function AutoScript() {...}
}
My current fix is to copy the AutoScript.php file from application/views/helpers into modules/admin/views/helpers which fixes the issue, but duplicates a file. What am I missing? Do I have to add this view helper path programmatically by creating an _initView function in my bootstrap?
Typically, you would name your custom view helper with your own prefix, not the Zend_ prefix. Beyond that, there are several choices for where to put and name your view helpers.
If this view-helper is really a single-application helper, then I find it natural for it to reside somewhere in the application folder. Within that possibility space, I would ask if the view-helper will be used in a single module or across multiple modules.
If the view-helper is intended for use in a single module, then I depend upon the build-in resource-autoloader mappings and place my view-helper class Mymodule_View_Helper_Myhelper in the file application/modules/mymodule/views/helpers/Myhelper.php.
If the view-helper is intended for use across multiple modules , I might pull it up a little higher than the modules folder, say Application_View_Helper_Myhelper (assuming an appnamespace of Application) stored in
application/views/helpers/Myhelper.php. In this case, we need to tell the view that there are helpers with prefix Application_View_Helper_ in that directory. This can be done at bootstrap:
protected function _initViewHelperPaths()
{
$this->bootstrap('view');
$view = $this->getResource('view');
$view->addHelperPath(APPLICATION_PATH . '/views/helpers', 'Application_View_Helper_');
}
Sometimes, you need a view-helper in one module that exists in another module and you cannot - in practical terms - move the original one around. In that case, one workaround is to define an empty shell of a view-helper in your consuming module extending your unmovable view-helper. In file application/mymodule/views/helpers/MyHelper.php:
class Mymodule_View_Helper_Myhelper extends Othermodule_View_Helper_Myhelper
{
}
This way, the code for the helper implementation is not duplicated. The module-specific resource-autoloader mappings will allow all those classes to be found when they invoked as view-helpers from a view-script.
Finally, if this view helper is to be used in multiple projects, then there is an argument for placing it outside of application scope, out in in the library folder. So perhaps a class MyLibrary_View_Helper_Myhelper stored in the file library/MyLibrary/View/Helper/Myhelper.php. As before, you would need to inform the view - probably at bootstrap or in a front-controller plugin - of the prefix/path mapping:
$view->addHelperPath(APPLICATON_PATH . '/../library/MyLibrary/View/Helper', 'MyLibrary_View_Helper_');
Note that in all cases above, the invocation of the view-helper functionality itself - say, inside a view-script - is:
<?php echo $this->myhelper($params) ?>
Note, in particular, the casing difference between the classname and the invocation.
the thing is these this lines:
$loginUrl = $this->view->url(array('controller'=>'auth', 'action'=>'index'));
$registerUrl = $this->view->url(array('controller'=>'register', 'action'=>'index'));
based on rob allens' Zend_Auth login/logout tutorial (win7/apache),
are placed in a view helper, and this one:
echo $this->url(array('controller'=>'index','action'=>'add'));
is placed in the index view script.
The generated links Do work fine in LOCAL, but in REMOTE only the 3rd line works.
ANY IDEAS? Where should i look for this? wich way to follow?
I was tempt to think in the remote server conf but the 3rd line works fine, so..
thanks!
Try this helper instead of view Zend_Controller_Action_Helper_Url:
//simple($action, $controller = null, $module = null, array $params = null)
//so your lines will look like:
$loginUrl = $this->_helper->url->simple('index','auth');
$registerUrl = $this->_helper->url->simple('index','register');
P.S. your lines work properly on Win7 and Ubuntu servers check registry of the lines
I found out that was the server. (.htacces and mod_rewrite) was not included in the package.
I think the third line was working because it was in the index controller, but when calling the others, then happened the object not found.
To work out this, i found an example using zend debug (was in german) so i inferred it (and then wrote to the hosting service), but still not quite sure how to check (phpinfo?) if a host have this features available or not in your package.
Using the Catalyst::Controller::FormBuilder module to handle forms in a Catalyst application.
The documentation says you can set the form_path like this:
form_path => File::Spec->catfile( $c->config->{home}, 'root', 'forms' ),
But the call to config() in my application is at the top level of the base module. Therefore, $c is undefined. So I can't call $c->config->{home}.
What is the proper way to configure form_path please?
You should be able to access configuration values that have already been set from your application's main module using the __PACKAGE__->config hash. Example: __PACKAGE__->config->{home} or __PACKAGE__->config->{'Controller::FormBuilder'}->{form_path}.
If you're trying to set the FormBuilder configuration in your applications main module, you should be able to use the code provided in the documentation and just replace $c->config->{home} with __PACKAGE__->config->{home}. I think they might have even made a mistake by not doing it this way, but I'm not sure.