Symfony parameters.yml nfs mounted filepath changes to local - symfony

On the production server, my nfs mounted path is being translated to a local directory. Any ideas what could cause this?
parameters.yml
parameters:
files_dir: /n/fs/web/doc_root/Files
services.yml
app.file_manager:
class: AppBundle\Services\FileManager
public: true
arguments: ["%files_dir%"]
FileManager.php
namespace AppBundle\Services;
class FileManager
{
/**
* #var string
*/
private $filesDir;
/**
* FileManager constructor.
* #param $filesDir
*/
public function __construct($filesDir)
{
echo $filesDir;
$this->filesDir = $filesDir;
}
}
Expected output: /n/fs/web/doc_root/Files
Actual Output: /opt/rh/httpd24/root/var/www/sites/web/doc_root/Files
Edit:
So it looks like in the container class file, appProdProjectContainer.php, the files_dir parameter is treated as a dynamic parameter.
$dir = __DIR__;
for ($i = 1; $i <= 5; ++$i) {
$this->targetDirs[$i] = $dir = dirname($dir);
}
...
case 'files_dir': $value = ($this->targetDirs[5].'/Files'); break;
This breaks in my environment because the output of __DIR__ in the context of composer install on a command line is /n/fs/web/doc_root, but when running via apache the output of __DIR__ is /opt/rh/httpd24/root/var/www/sites/web/doc_root . I'm able to delete the var/cache/prod directory and regenerate the container class file by accessing the site through a web browser or curl and it fixes my problem. Is there a better way to do this?

Related

You have requested a non-existent service "test.service_container". Did you mean this: "service_container"?

PHPUnit 7.5.15 by Sebastian Bergmann and contributors.
Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException : You have requested a non-existent service "test.service_container". Did you mean this: "service_container"?
/opt/project/backend/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:277
/opt/project/backend/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:225
/opt/project/backend/tests/Functional/KernelAwareTest.php:49
/opt/project/backend/tests/Functional/FlightTaskManagement/AssignEmployeeToTaskTest.php:47
public function setUp(): void
{
global $kernel;
$this->kernel = TestKernel::get();
$kernel = $this->kernel;
$container = $this->kernel->getContainer();
if ($container === null)
throw new \InvalidArgumentException('Container can not be null.');
$this->container = $container->get('test.service_container');
// $this->container = $container->get('service_container');
/** #var Registry $doctrine */
$doctrine = $this->container->get('doctrine');
/** #var \Doctrine\ORM\EntityManager $manager */
$manager = $doctrine->getManager();
$this->entityManager = $manager;
$this->entityManager->beginTransaction();
if (!$this->container->initialized(WorkDistributionTransport::class)) {
$this->container->set(WorkDistributionTransport::class, new InMemoryTransport());
}
if (!$this->container->initialized(Configuration::class)) {
$this->container->set(Configuration::class, new TestConfiguration());
}
parent::setUp();
}
It fails at line
$this->container = $container->get('test.service_container');
Symfony is 4.1 but looks like not finished to update. I can't remember by what we decided that it was not finished to update from earlier version.
Not clear if that is the problem that it is not finished to update. Looks like in 4.0 there is no such service so thats why. But then how to make it appear here?
Or maybe I can use
$this->container = $container->get('service_container');
as with earlier versions? Just what is faster way?
I just tried using
$this->container = $container->get('service_container');
but I then get
Doctrine\DBAL\DBALException : An exception occured while establishing a connection to figure out your platform version.
You can circumvent this by setting a 'server_version' configuration value
But I had set the version in config_test.yml so not clear which way is faster to fix.
doctrine:
dbal:
server_version: 5.7
driver: pdo_mysql
host: db_test
port: null
dbname: project
user: project
password: project
Probably if I load service_container then it does not load test config and thats why I get this server_version error. So then need to somehow make it load test config.
Found: I had hardcoded dev environment in AppKernel. Probably thats why I was getting this error. Hardcoding test env fixed. Would be good somehow to make it without hardcoding, but it is still better than nothing:
public function __construct($environment, $debug)
{
// $environment ='dev';
$environment ='test';
$debug= true;
parent::__construct($environment, $debug);
date_default_timezone_set('UTC');
}

Re-init application laravel

I have two websites in the one laravel app. Http requests have no problems: depending of domain app include different views, config and other. But commands and async jobs have problems. Default app create. I transmit parameter (domain), but can't re-init app. I do anything, but pathes are default.
$app = require DIR.'/../bootstrap/app.php'; $app->make(Kernel::class)->bootstrap();
I tried, but it not helped.
Tell me please how do it.
I hope that it will be helpful for anybody. I wrote this helper:
/**
* Init the application.
*
* #param string $domain
* #return void
*/
function initApplication(string $domain = App::DOMAINS[App::DEFAULT_SUBDIR])
{
if (function_exists('putenv')) {
array_map('putenv', array_keys($_ENV));
}
$_SERVER = array_diff_key($_SERVER, $_ENV);
$_ENV = [];
global $app;
$_SERVER['SERVER_NAME'] = $domain;
$app = require __DIR__.'/../bootstrap/app.php';
(new Dotenv\Loader($app->environmentFilePath()))->load();
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
}

symfony 4 : How to get "/public" from RootDir

I have an image under the public folder.
How can I get my image directory in symfony4 ?
In symfony 3, it's equivalent is :
$webPath = $this->get('kernel')->getRootDir() . '/../web/';
It is a bad practice to inject the whole container, just to access parameters, if you are not in a controller. Just auto wire the ParameterBagInterface like this,
protected $parameterBag;
public function __construct(ParameterBagInterface $parameterBag)
{
$this->parameterBag = $parameterBag;
}
and then access your parameter like this (in this case the project directory),
$this->parameterBag->get('kernel.project_dir');
Hope someone will find this helpful.
Cheers.
You can use either
$webPath = $this->get('kernel')->getProjectDir() . '/public/';
Or the parameter %kernel.project_dir%
$container->getParameter('kernel.project_dir') . '/public/';
In Controller (also with inheriting AbstractController):
$projectDir = $this->getParameter('kernel.project_dir');
In config/services.yaml:
parameters:
webDir: '%env(DOCUMENT_ROOT)%'
In your controller:
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
...
public function yourFunction(Parameterbag $parameterBag)
{
$webPath = $parameterBag->get('webDir')
}
If you need to access a directory within public, change the last line to the following:
$webPath = $parameterBag->get('webDir') . '/your/path/from/the/public/dir/'
You can inject KernelInterface to the service or whatever and then get the project directory with $kernel->getProjectDir():
<?php
namespace App\Service;
use Symfony\Component\HttpKernel\KernelInterface;
class Foo
{
protected $projectDir;
public function __construct(KernelInterface $kernel)
{
$this->projectDir = $kernel->getProjectDir();
}
public function showProjectDir()
{
echo "This is the project directory: " . $this->projectDir;
}
}
Starting from Symfony 4.3 we can generate absolute (and relative) URLs for a given path by using the two methods getAbsoluteUrl() and getRelativePath() of the new Symfony\Component\HttpFoundation\UrlHelper class.
New in Symfony 4.3: URL Helper
public function someControllerAction(UrlHelper $urlHelper)
{
// ...
return [
'avatar' => $urlHelper->getAbsoluteUrl($user->avatar()->path()),
// ...
];
}
All above answers seems valid, but I think it's simplier if you configure it as parameter in services.yaml
If you need to use it in serveral services, you can bind it like this:
# services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
bind:
$publicDir: "%kernel.project_dir%/public"
# src/Services/MyService.php
class MyService
{
public function __construct(
private string $publicDir,
) {
}
// …
}
This way, this is configured at one place only, and if later you decide to change /public to something else, you will have to change it only in .yaml file.
If you don't need the root directory but a subdirectory, it might be better to define the final target path: This way you will be more flexible if you need later to move only that directory, like $imageDir or $imagePath (depends if you will use the full directory or only the public path).
Note also the default public path is defined in composer.json file, in the extra.public-dir key

Migrations fail when SQLite database file does not exist?

It seems that migrations (sort of) fail silently when the database file does not exist. The migration executes but no db file is created and I can run the migration again. (It never says "nothing to migrate") If I create a blank file then it works.
This is odd because I thought SQLite always created the db file if it was not found so I'm not sure if this is a bug or something I've done wrong. Maybe it's a permissions problem? But everything else is working so I don't know. I'm using Windows 7 and the project is in my
User blamh suggested to add the following snippet to app/start/artisan.php to automatically recreate the database when it doesn't exist, instead of throwing an exception.
if (Config::get('database.default') === 'sqlite') {
$path = Config::get('database.connections.sqlite.database');
if (!file_exists($path) && is_dir(dirname($path))) {
touch($path);
}
}
With this, you can safely delete the SQLite database and then re-migrate and re-seed it, if you wish.
I've issued this bug against laravel/framework.
Hopefully future versions will give an error if the database doesn't exist, or automatically create one.
This is an updated and more flexible solution from Virtlinks answer
<?php
namespace App\Providers;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\ServiceProvider;
class SqliteServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
if (DB::getDriverName() === 'sqlite') {
$path = DB::getConfig('database');
if (!file_exists($path) && is_dir(dirname($path))) {
touch($path);
}
}
}
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
}
Here's yet another way to automatically create the database file, tested on Laravel 5.4.
This is the same as Gummibeer's answer except that I moved the logic to the App\Console\Kernel class (app/Console/Kernel.php), and the check will be performed only when running the migrate command.
<?php
use Illuminate\Support\Facades\DB;
class Kernel extends ConsoleKernel
{
/**
* #param \Symfony\Component\Console\Input\InputInterface $input
* #param \Symfony\Component\Console\Output\OutputInterface $output
* #return int
*/
public function handle($input, $output = null)
{
$this->touchSQLiteDatabase($input);
return parent::handle($input, $output);
}
protected function touchSQLiteDatabase($input)
{
$this->bootstrap();
if (substr((string)$input, 0, 7) == 'migrate' && DB::getDriverName() === 'sqlite') {
$path = DB::getConfig('database');
if (!file_exists($path) && is_dir(dirname($path))) {
touch($path);
}
}
}
}

symfony2 behat in test enviroment: DB tables not created

I am trying to behat my application and I have a big problem; DB tables are not created so I can't put any fixtures.
My scenario is:
Scenario: Check the stories page
Given Database is set
And I am logged as "admin" and password "123123123"
And print last response
...
Part of FeatureContext:
/**
* #Given /^Database is set$/
*/
public function databaseIsSet()
{
$this->generateSchema() ;
$admin = new User() ;
$admin->setRoles(array(User::ROLE_SUPER_ADMIN)) ;
$admin->setEnabled(true) ;
$admin->setUsername("admin") ;
$admin->setPlainPassword("123123123") ;
$admin->setEmail("admin#mysite.com") ;
$em = $this->getEntityManager() ;
$em->persist($admin) ;
$em->flush() ;
echo $admin->getId() . "==" ;
echo "db set" ;
}
/**
* #Given /^I am logged as "([^"]*)" and password "([^"]*)"$/
*/
public function iAmLoggedAsAndPassword($username, $password)
{
return array(
new Step\When('I am on "/login"'),
new Step\When('I fill in "username" with "' . $username . '"'),
new Step\When('I fill in "password" with "' . $password . '"'),
new Step\When('I press "Login"'),
);
}
protected function generateSchema()
{
// Get the metadatas of the application to create the schema.
$metadatas = $this->getMetadatas();
if ( ! empty($metadatas)) {
/**
* #var \Doctrine\ORM\Tools\SchemaTool
*/
$tool = new SchemaTool($this->getEntityManager());
// $tool->dropDatabase() ;
$tool->createSchema($metadatas);
} else {
throw new Doctrine\DBAL\Schema\SchemaException('No Metadata Classes to process.');
}
}
/**
* Overwrite this method to get specific metadatas.
*
* #return Array
*/
protected function getMetadatas()
{
$result = $this->getEntityManager()->getMetadataFactory()->getAllMetadata() ;return $result;
}
protected function getEntityManager()
{
return $this->kernel->getContainer()->get("doctrine")->getEntityManager() ;
}
....
The code for generateSchema is taken somewhere from internet and used in Phpunits tests I have and works perfectly.
But; when I run bin/behat, I get
SQLSTATE[HY000]: General error: 1 no such table: tbl_user
after login part of scenario.
The echo statement I have is also shown in output, just to make sure the method is actually executed. Also, $admin gets an ID of 1 which is also visible in output.
My test env is using default sqlite DB, and it is irrelevant if I put 'http://mysite.local/app_dev.php/' or 'http://mysite.local/app_test.php/' for base_url in config; the login doesn't work although I copy&pasted it from knpLabs page. To make sure $admin is still in DB, I tried to reload it from repository and it works (I removed that part of code).
Help?
Actually, I found the problem. Sqlite works in-memory and upon each request to some page like login url, the previous state had been lost. I created new enviroment app_behat.php with these setting in config_behat.yml:
imports:
- { resource: config.yml }
framework:
test: ~
session:
storage_id: session.storage.mock_file
doctrine:
dbal:
dbname: other_database
and it works now. Maybe someone will find this usefull.
I had the same problem and for me the problem was in config_test.yml file.
I changed pdo_sqlite to pdo_mysql.
doctrine:
dbal:
driver: pdo_mysql
# driver: pdo_sqlite
And it works like a charm.

Resources