How do I access values from .env in Laravel 5.1 TestCase - testing

In Laravel 5.1 TestCase, the baseUrl is hard-coded. I'd like to set it based on the value I have set in .env.
How do I access the .env variables within the TestCase class?

in Laravel 5.0 TestCase, I can get .env variable with following function.
getenv('APP_VARIABLE');
I think it should work with Laravel 5.1 as well as getenv() is a PHP function.

Start Dotenv to get .env variables in the TestCase stage
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make('Illuminate\Contracts\Console\Kernel')->bootstrap();
Dotenv::load(__DIR__.'/../');
$this->baseUrl = env('APP_URL', $this->baseUrl);
return $app;
}

I can confirm that Christopher Raymonds suggestion above, replacing the
Dotenv::load call
with
this $app->loadEnvironmentFrom('.env.testing');
works with Laravel 5.4
See Example:
protected $baseUrl = 'http://localhost';
/**
* Creates the application.
*
* #return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
$app->loadEnvironmentFrom('.env');
$this->baseUrl = env('APP_URL', $this->baseUrl);
return $app;
}

I have this in my .env file:
APP_URL=http://project.dev
I then modified the createApplication function in tests/TestCase.php
/**
* Creates the application.
*
* #return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$this->baseUrl = env('APP_URL', $this->baseUrl);
$app = require __DIR__ . '/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
return $app;
}

Turned out I needed to add the APP_URL key to my phpunit.xml file.
For whatever reason, I thought some .env file would also be loaded in the process but apparently that's not the case.

I modified the createApplication function in tests/TestCase.php adding this lines after bootstrap ...->bootstrap();
$env = new Dotenv\Dotenv(dirname(__DIR__), '../.env');
$env->load();

In Laravel 5.2 I replaced the Dotenv::load call with this ...
$app->loadEnvironmentFrom('.env.testing');

Related

How to hide some views only in production env Laravel

I am pretty new to Laravel. So I have a Laravel Vue app where i want to hide a view.blade only in my production environment and not on staging , i tried with the config file view but i didn't succeed.
Can anyone help me please ?
Thank you
One possible solution would be to use an if statement for the view. It's difficult to give a more contextual answer without more context.
example below:
<template>
<view v-if="inProduction"></view>
</template>
export default {
computed: {
inProduction(){
return process.env.NODE_ENV === "production";
}
}
}
You could do a conditional route middleware too so it just checks the config file (cached) for the env. Then you can send them anywhere you want if someone tried to hit that route.
If you're trying to hide a full route on certain env best way would be to create a Middleware like this:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class AppEnv
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* #return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
public function handle(Request $request, Closure $next, $env)
{
if(config('app.env') == $env) {
return $next($request);
}
abort(404);
}
}
You'll have to register this middleware on the app/Http/Kernel $routeMiddleware array
Then you can use it like this:
Route::view('/', 'welcome')->middleware(['env:local'])
(Change local for the env where you want to show this route)

Too few arguments to function Livewire\LivewireManager::mount(), 0 passed in

Thanks in advance for helpful advice. I am using Laravel Livewire for creating components and Jetstrap for authentication for those routes that require it.
At the moment I only have one route set up for testing authentication, yet after I have logged in to view that route, I get the following error:
Too few arguments to function Livewire\LivewireManager::mount(), 0 passed in /var/www/mvp/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php on line 261 and at least 1 expected
This seems to be originating from the LivewireManager class, inside the getInstance() function:
public function getInstance($component, $id)
{
$componentClass = $this->getClass($component);
throw_unless(class_exists($componentClass), new ComponentNotFoundException(
"Component [{$component}] class not found: [{$componentClass}]"
));
return new $componentClass($id);
}
It seems to be expecting a component argument from the Facade class in /vendor/laravel/framework/src/Illuminate/Support/Facades/, but isn't getting the component it needs. I checked the page code, and there is definitely a component there.
The Facade function creating the error:
/**
* Handle dynamic, static calls to the object.
*
* #param string $method
* #param array $args
* #return mixed
*
* #throws \RuntimeException
*/
public static function __callStatic($method, $args)
{
$instance = static::getFacadeRoot();
if (! $instance) {
throw new RuntimeException('A facade root has not been set.');
}
return $instance->$method(...$args);
}
And the page that's supposed to be loading its component:
#extends('layouts.app')
#section('content')
#livewire('component')
#stop
Is there a simple way to fix the problem? Or am I missing something?
I got same error like what you get when i try to passing parameter and then i'm solving the problem by following the documentation with changing the way to render livewire component from using blade directive #livewire() into <livewire: >

Respect\Validation custom Rule with PDO?

I am learning Slim Framework v4 and decided to use Respect\Validation to validate inputted data and have hit a snag where I do not know how to inject the PDO into my custom rule I created.
The idea is to validate some inputs against the database if the provided data exist (or in another instances, if it was inputted correctly). In this specific case, I am tying to validate user's credentials for log in. My idea is this:
AuthController.php:
v::with('app\\Validators\\');
$userValidation = v::notBlank()->email()->length(null, 255)->EmailExists()->setName('email');
EmailExists() is my custom rule.
EmailExists.php:
namespace app\Validators;
use PDO;
use Respect\Validation\Rules\AbstractRule;
class EmailExists extends AbstractRule
{
protected $pdo;
public function __construct(PDO $pdo)
{
$this->pdo = $pdo;
}
public function validate($input, $id = null)
{
// a PDO query that checks if the email exists in database
}
}
But I get an error of Too few arguments to function app\Validators\EmailExists::__construct(), 0 passed and exactly 1 expected, which is somewhat expected since the AbstractRule does not have a PDO injected and my class extends it.
So how to inject the PDO interface so that I can use it in my custom rules?
Are you guys using another approach in validating this kind of data? Do note that I am writing an API, so the database validation is somewhat a must and after Googling for past two days, I have no solutions at hand.
I am also using a PHP-DI where I create PDO interface. This is my dependencies.php file:
declare(strict_types=1);
use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;
use app\Handlers\SessionMiddleware;
return function (ContainerBuilder $containerBuilder) {
$containerBuilder->addDefinitions([
PDO::class => function (ContainerInterface $c) {
$settings = $c->get('settings')['db'];
$db = new PDO("mysql:host={$settings['host']};dbname={$settings['database']};charset={$settings['charset']},{$settings['username']},{$settings['password']}");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND, "SET NAMES 'utf8',time_zone='{$offset}'");
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
return $db;
},
'session' => function(ContainerInterface $c) {
return new SessionMiddleware;
}
]);
};
And (part of) index.php:
declare(strict_types=1);
use DI\ContainerBuilder;
use Slim\Factory\AppFactory;
// Instantiate PHP-DI ContainerBuilder
$containerBuilder = new ContainerBuilder();
// Set up settings
$settings = require __DIR__ . '/../app/settings.php';
$settings($containerBuilder);
// Set up dependencies
$dependencies = require __DIR__ . '/../app/dependencies.php';
$dependencies($containerBuilder);
// Build PHP-DI Container instance
$container = $containerBuilder->build();
// Instantiate the app
AppFactory::setContainer($container);
$app = AppFactory::create();
// Register middleware
$middleware = require __DIR__ . '/../app/middleware.php';
$middleware($app);
// Register routes
$routes = require __DIR__ . '/../app/routes.php';
$routes($app);
// Add Routing Middleware
$app->addRoutingMiddleware();
// Run App & Emit Response
$response = $app->handle($request);
$responseEmitter = new ResponseEmitter();
$responseEmitter->emit($response);
Any help would be appreciated.
Use your user model to count the number of rows in the user table where there is a hit.
If it is not exactly 0, the check returns false, if it is exactly 0, the check passes.
So you don't have to include a PDO at this point. I use Slim 3 and that works quite well.
namespace app\Validators;
use Respect\Validation\Rules\AbstractRule;
class EmailAvailable extends AbstractRule {
/**
* #param $input
*
* #return bool
*/
public function validate ($sInput) {
return User::where('user_email', $sInput)->count() === 0;
}
}
class EmailAvailable extends AbstractRule {
/**
* #param $input
*
* #return bool
*/
public function validate ($sInput) {
return User::where('user_email', $sInput)->count() === 0;
}
}

How to access services from a view script in Zend Framework 3?

I have a custom authentication service and in ZF2 I accessed this as follows:
Application/view/layout/layout.phtml
$authenticationService = $this->getHelperPluginManager()
->getServiceLocator()
->get('AuthenticationService');
$currentIdentity = $authenticationService->getIdentity();
Now the Zend\ServiceManager#getServiceLocator() is deprecated.
How to get a service available in a view script (or concrete in this case in the layout) in ZF3?
For this purpose there is already Identity View Helper
As documentation says
// Use it any .phtml file
// return user array you set in AuthenticationService or null
$user = $this->identity();
The solution is to assign a global view variable in the onBootstrap(...):
namespace Application;
use ...
class Module
{
public function onBootstrap(MvcEvent $e)
{
...
$serviceManager = $e->getApplication()->getServiceManager();
$viewModel = $e->getApplication()->getMvcEvent()->getViewModel();
$viewModel->authenticationService = $serviceManager->get('AuthenticationService');
}
...
}
Another (perhaps an even better/cleaner) solution is to use a ViewHelper. See also here.

Symfony3 Profiler Storage

in the Docs
http://symfony.com/doc/master/cookbook/profiler/storage.html
you still can find Information about Profiler Storage.
I just checked the code and could not find any clues how to set a custom storage.
I also find no Documentation stating this except some #legacy notes in the Original Source at 2.8.
Is there a Reason why this was removed?
I was using redis to store this data with a lifetime of eta 1hour.
Now I need to run a manual cleanup to whipe all files in that directory.
If anybody has some clues or hints on helping me with this issue are appreceated ^^
Chris
Thanks to the Tip of Matteo I was able to solve this quite flexible.
The Team of Symfony removed this, because it was hard coded into the Profiler Subsystem.
Instead of fixing this by adding a class parameter I had to solve it. :)
Ok, here is the code, If somebody needs this to.
First of all we need the Original Classes from Symfony 2.7 (at least I reused them as I only need the Redis Option ( I use it, because I can Compress the data using igbinary)
Next you need to implement a Compiler Pass.
namespace AcmeBunlde\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class ProfilerCompilerPass implements CompilerPassInterface
{
/**
* You can modify the container here before it is dumped to PHP code.
*
* #param ContainerBuilder $container
*/
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('profiler');
$definition->addArgument('%acmebundle.profiler.defaultEnabled%');
$definition->addArgument('%acmebundle.profiler.class%');
$definition->addArgument('%acmebundle.profiler.dsn%');
$definition->addArgument('%acmebundle.profiler.username%');
$definition->addArgument('%acmebundle.profiler.password%');
$definition->addArgument('%acmebundle.profiler.ttl%');
$definition->setClass('acmebundle\Profiler\Profiler');
}
}
This needs to be loaded inside the Bundle Loader:
public function build(ContainerBuilder $container)
{
...
$container->addCompilerPass(new ProfilerCompilerPass());
}
After this we need to add the Configuration for the New Profiler Storage in the DependencyInjection Folder.
namespace AcmeBundle\DependencyInjection;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
/**
* This is the class that validates and merges configuration from your app/config files
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
* #author Chris
*/
class Configuration implements ConfigurationInterface
/**
* {#inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('library');
$rootNode
->children()
->arrayNode('profiler')
->addDefaultsIfNotSet()
->children()
->booleanNode('defaultStorage')
->defaultTrue()
->end()
->scalarNode('class')
->defaultValue('')
->end()
->scalarNode('dsn')
->defaultValue('')
->end()
->scalarNode('username')
->defaultValue('')
->end()
->scalarNode('password')
->defaultValue('')
->end()
->scalarNode('ttl')
->defaultValue('3600')
->end()
->end()
->end();
return $treeBuilder();
}
}
Now set the Default Values in The Dependency Injection Bundle Loader
<?php
namespace AcmeBundle\DependencyInjection;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
/**
* This is the class that loads and manages your bundle configuration
*
* To learn more see {#link http://symfony.com/doc/current/cookbook/bundles/extension.html}
* #author Chris
*/
class AcmeExtension extends Extension
{
/**
* {#inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
...
$container->setParameter('acmebundle.profiler.defaultEnabled',$config['profiler']['defaultStorage']);
$container->setParameter('acmebundle.profiler.class',$config['profiler']['class']);
$container->setParameter('acmebundle.profiler.dsn',$config['profiler']['dsn']);
$container->setParameter('acmebundle.profiler.username',$config['profiler']['username']);
$container->setParameter('acmebundle.profiler.password',$config['profiler']['password']);
$container->setParameter('acmebundle.profiler.ttl',$config['profiler']['ttl']);
...
}
...
}
As Last Step you need to build a basic container for adding the new Profiler Handler.
I have choosen to implement it not to complex:
<?php
namespace AcmeBundle\Profiler;
use Psr\Log\LoggerInterface;
use \Symfony\Component\HttpKernel\Profiler\Profiler as ProfilerSrc;
use Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface;
/**
* Profiler.
*/
class Profiler extends ProfilerSrc
{
public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger, $defaultEnabled=true,$class=null,$dsn=null,$username=null,$password=null,$ttl=3600)
{
if($defaultEnabled!==true)
{
$storage = new $class($dsn,$username,$password,$ttl);
}
parent::__construct($storage , $logger);
}
}
I have also added a Library to define the Constructor of the Storage Interface.
<?php
namespace AcmeBundle\Profiler;
use Symfony\Component\HttpKernel\Profiler\ProfilerStorageInterface as ProfilerStorageSource;
interface ProfilerStorageInterface extends ProfilerStorageSource
{
/**
* ProfilerStorageInterface constructor.
*
* #param $dsn
* #param $username
* #param $password
* #param $ttl
*/
public function __construct($dsn,$username,$password,$ttl);
}
All you need to do now is to define some Options in your config_dev.yml file.
acmebundle:
profiler:
defaultEnabled: false
class:CLASSNAME INCLUDING NAMESPACE
dsn: redis://localhost/1
username:
password
ttl: 3600
with defaultEnabled = true you can reenable to Original Handler.
the rest is, I believe self explaining.
username + password is from the original feature set.
(ttl == lifetime)
I hope this helps somebody else as well :)
Is marked as deprecated since 2.8 with the suppression in the 3.0. I can't find any motivation about in the PR. The doc is not yet updated as you mention.
The only suggestion is about a comment in this issue:
If you want to use your own implementation of a profiler storage,
then just override the profile.storage service.
Hope this help