Symfony 4.1 KernelTestCase Repository ConnectionException - doctrine

I'm following the symfony docs (https://symfony.com/doc/current/testing/doctrine.html) trying to test my repository classes against my MySQL database.
The relevant code part is this:
class ProductRepositoryTest extends KernelTestCase
{
/**
* #var \Doctrine\ORM\EntityManager
*/
private $entityManager;
/**
* {#inheritDoc}
*/
protected function setUp()
{
$kernel = self::bootKernel();
$this->entityManager = $kernel->getContainer()
->get('doctrine')
->getManager();
}
public function testSearchByCategoryName()
{
$products = $this->entityManager
->getRepository(Product::class)
->searchByCategoryName('foo')
;
$this->assertCount(1, $products);
}
/**
* {#inheritDoc}
*/
protected function tearDown()
{
parent::tearDown();
$this->entityManager->close();
$this->entityManager = null; // avoid memory leaks
}
}
When I execute the testclass with PhpUnit I get a Doctrine\DBAL\Exception\ConnectionException with the message: "An exception occurred in driver: SQLSTATE[HY000] [1045] Access denied for user 'root'#'localhost' (using password: NO)".
I stored my database connection data in the DATABASE_URL in the .env file and the connection works fine when executing: bin/console doctrine:migrations:migrate
But it seems this configuration is not used for testing (because 'NO' is not my password in the .env file). Do I have to store the connection configuration in another file for testing? And if yes, where do I have to store the configuration, so that it gets used in my testcase?
Thanks in advance for any help!

The .env file is only used in dev environment. If you're in prod or in test, it's not even read: https://symfony.com/doc/current/configuration.html#the-env-file-environment-variables. It's clear in some parts of the doc, but less in some others, which can be confusing.
In your case, you can check your config folder, more specifically probably under config/packages/doctrine.yaml and config/packages/parameters.yaml, and see how the DATABASE_URL is used (when it exists). From there, you can either hardcode that URL in config files specific to the test environment (creating a test subfolder under config/packages for instance), or you can give the proper DATABASE_URL environment variable to phpunit "manually" by using APP_ENV=... && bin/phpunit ....
Here's what a solution would look like in the first scenario :
# config/packages/test/doctrine.yaml
doctrine:
dbal:
url: 'mysql://db_user:db_password#127.0.0.1:3306/db_name'

Related

Dynamic Configuration with Laravel Horizon

I am trying to change the mail driver's username and password on the fly like the following.
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
config(['mail.username' => $this->username]);
config(['mail.password' => $this->password]);
Mail::to('me#me.com')->send(new OrderShipped());
}
The dynamic config setting was inside the queue job. For queue processing, I am using the Laravel horizon. But, when I execute the queue job. It's still using the default config. Not the config I set dynamically.
Note: when I log right after config set it was showing the dynamic value.
How can I set the config dynamically and make Laravel horizon to use dynamic configuration?
From Laravel version 7.x onwards you can now state the mail driver to use while sending an email. All you need to configure all your connections & credentials properly in app/config/mail.php. Once configured, you can specify the name of the driver via mailer() function as below:
Mail::mailer('postmark')
->to($request->user())
->send(new OrderShipped($order));
public function handle()
{
config([
'mail.username' => $this->username,
'mail.password' => $this->password,
]);
}
I did it like that. I think the important part is that you get the data you will use in the Job class from outside.
public function __construct($username,$password)
{
$this->username= $username;
$this->receiver = $password;
}

Reset Redis database after each test in laravel

In my laravel application, I use Redis to store some cache (e.g. the list of items to show on the front page). I always access Redis through the Facade: Illuminate\Support\Facades\Redis.
I created a different Redis database for testing (1 instead of 0), but I also need to reset it after each test, so that the test never gets data from a previous test.
Is there an efficient way to create this behaviour?
I tried to implement it using the #before annotation:
/**
* #before
*/
public function prepareForTesting() {
Redis::flushdb();
}
But I get the error: Cannot use 'FLUSHDB' over clusters of connections.
Any ideas?
Maybe you could use the built in artisan cache:clear command?
Like this:
/**
* #before
*/
public function prepareForTesting() {
Artisan::call('cache:clear');
}

Check if input is from console

I want to share a variable of my views with:
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
\Schema::defaultStringLength(191);
$customers = Customer::get();
\View::share('customers', $customers);
}
}
it works as expected, but when I want to migrate my tables via artisan it throws an error, that the table for customers was not found because it is checked BEFORE the migration starts. So I need something like
if(!artisan_request) {
//request to laravel is via web and not artisan
}
But I haven't found anything in the documentation.
You can check if you are running in the console by using
app()->runningInConsole()
Underneath that, all it does is check the interface type
return php_sapi_name() == 'cli' || php_sapi_name() == 'phpdbg'
You can find more on the PHP Docs site
To detect whether the app is running in console, you can do something like this:
use Illuminate\Support\Facades\App;
if(App::runningInConsole())
{
// app is running in console
}
See, illuminate/Foundation/Application.php:520

PHPBB 3.1.10 Dependency Injection of User Object only delivers Anonymous User in a live environment

The goal is to get the login status of a User in PHPBB 3.1.10 in an Extension Module using only AJAX calls.
I have succeded with this on XAMPP on my local machine. (meaning the problem described does not exist in that environment) I am now trying to roll that out to my online site by installing the extension on a live PHPBB Installation.
The problem now is that as opposed to my local environment the #user
object delivered by the dependency injection mechanism is always
"Anonymous", no matter if I am logged in or not.
"Anonymous" is the Username of a PHPBB User who is not logged in.
Both envrionments use PHPBB 3.1.10.
The Folder Structure is deviates only in the name of the PHPBB3 Root Folder name.
Both have functioning URL Rewrite now, after I had to manually set
the Live Environments RewriteBase in .htaccess.
Board Settings seem to be identical but for the domain.
As for PHP Server settings - I have no direct influence on PHP config on the live environmenht but for .htaccess and I have very little knowladge about what is possible in that regard.
Here is my Service Defintion, Routing Information and the Authorization class used to read the #user object.
ext/foo/bar/services.yml
services:
foo.bar.helper.auth:
class: foo\bar\helper\Auth
arguments:
- '#user'
- '%core.root_path%'
- '%core.php_ext%'
ext/foo/bar/config/routing.yml
foo_bar_getUserStatus:
path: /getUserStatus
defaults: { _controller: foo.bar.helper.Auth:getUserStatus }
ext/foo/bar/helper/Auth.php
<?php
namespace foo\bar\helper;
class Auth{
/* #var \phpbb\user */
protected $user;
/** #var string */
protected $root_path;
/** #var string */
protected $php_ext;
/**
* Constructor
*
* #param \phpbb\user $user
* #param string $root_path
* #param string $php_ext php ext
* #access public
*/
public function __construct(
\phpbb\user $user,
$root_path,
$php_ext)
{
$this->user = $user;
$this->root_path = $root_path;
$this->php_ext = $php_ext;
include_once($this->root_path
. 'includes/functions_user.'
. $this->php_ext);
}
// AUTHORIZATION
public function __getUserStatus(){
$userStatus = array( 'isLoggedIn' => false );
if ($this->user->data['is_registered'] && ! $user->data['is_bot']){
$userStatus['isLoggedIn'] = true;
$ADMINS_GROUP_ID = '5';
if(group_memberships($ADMINS_GROUP_ID, $this->user->data['user_id'], true)){
$userStatus['isAdmin'] = true;
}
}
return $userStatus;
}
public function getUserStatus(){
return new \Symfony\Component\HttpFoundation\JsonResponse(array(
'success' => $this->__getUserStatus()
));
}
}
update 11.01.17
I have managed to get the extension to run properly on a fresh Installation of PHPBB 3.2 (which was released very recently) and PHP 7.0. (running in the same server environment as the live one)
I still have no idea yet why the user object was not set properly.
Also I have not checked out yet if migrating data from PHPBB 3.1.10 to a fresh installation of PHPBB 3.2 is feasible for me.
It will take some time for me to figure things out as I'm not working full time on it.

Symfony 1.4: Override doctrine:build-schema command

Is it possible to override a Symfony 1.4 CLI command?
More specifically, I was wondering if it's possible to override this command:
php symfony doctrine:build-schema
What I want to do is to add a new option in the database.yml file for each connection I find in it.
The option I want to add is a package option
So, an hypothetical connection could be:
all:
doctrine:
class: sfDoctrineDatabase
package: myPackageOption
param:
dsn: 'mysql:host=localhost;dbname=my_db_name'
username: db_user
password: db_password
If it would be possible, where can i find the code to override?
I suggest you to use some shell script that pre-generate the databses.yml and then auto-invoque the php symfony doctrine:build-schema. Something like:
build.sh, in project root folder:
#!/bin/bash
cp config/databases_1.yml config/databases.yml
php symfony doctrine:build
then, type ./build.sh (after added execution permissions) in your console.
The copy/replace of multiple databases_xxx.yml it's the easiest example. But you can do any processing you want.
If you don't know about shell scripting, you can do the file modification even with a php script, so your build.sh should looks like:
#!/bin/bash
php pregenerate_databases.php
php symfony doctrine:build
I'm trying to override the task but I can't make it work, but:
You can create your own task that inherits the doctrine task and do your stuff:
in lib/task add sfDoctrineBuildSchemaCustomTask.class.php:
class sfDoctrineBuildSchemaCustomTask extends sfDoctrineBuildSchemaTask
{
/**
* #see sfTask
*/
protected function configure()
{
$this->addOptions(array(
new sfCommandOption('application', null, sfCommandOption::PARAMETER_OPTIONAL, 'The application name', true),
new sfCommandOption('env', null, sfCommandOption::PARAMETER_REQUIRED, 'The environment', 'dev'),
));
$this->namespace = 'doctrine';
$this->name = 'build-schema-custom';
$this->briefDescription = 'Creates a schema from an existing database';
$this->detailedDescription = <<<EOF
The [doctrine:build-schema|INFO] task introspects a database to create a schema:
[./symfony doctrine:build-schema|INFO]
The task creates a yml file in [config/doctrine|COMMENT]
EOF;
}
/**
* #see sfTask
*/
protected function execute($arguments = array(), $options = array())
{
// do your stuff before original call
parent::execute($arguments,$options);
// do your stuff after original call
}
}
Then, you can call php symfony doctrine:build-schema-custom, and go!
Or, maybe, you can edit the original task located in lib/vendor/symfony/lib/plugins/sfDoctrinePlugin/lib/task/sfDoctrineBuildSchemaTask.class.php

Resources