Changing cache_dir and log_dir with Symfony2 - caching

Because of deployment constraints, I would like to have the log and cache directories used by my Symfony2 application somewhere under /var/... in my file system. For this reason, I am looking for a way to configure Symfony and to override the default location for these two directories.
I have seen the kernel.cache_dir and kernel.log_dir and read the class Kernel.php. From what I have seen, I don't think that it is possible to change the dir locations by configuration and I would have to patch the Kernel.php class.
Is that true, or is there a way to achieve what I want without modifying the framework code?

Add the following methods to app/AppKernel.php (AppKernel extends Kernel) making them return your preferred paths:
public function getCacheDir()
{
return $this->rootDir . '/my_cache/' . $this->environment;
}
public function getLogDir()
{
return $this->rootDir . '/my_logs';
}

I was happy to find your post, but I was a little bit confused of the unhelping answers.
I got the same problem and found out that the logs are depending on the config parameter
kernel.logs_dir.
So I just added it to my config.yml parameters:
kernel.logs_dir: /var/log/symfonyLogs
I hope it will helpfull for you even, if its a late answer.

i think the easiest way is to link the folder to another place. We have made this on the prod server but when you develop local perhaps on windows its a bit complicated to set the symlinks.
ln -s /var/cache/ /var/www/project/app/cache
something like this.

I would like to offer an alternative and that is to set environment variables to change these directories. This way it's easier to set depending on the stage. (testing, production or development)
export SYMFONY__KERNEL__CACHE_DIR "/your/directory/cache"
export SYMFONY__KERNEL__LOGS_DIR "/your/directory/logs"
Environment variables can also be set in the virtual host with SetEnv.
When reading kernel parameters symfony will look for all the $_SERVER variables that start with SYMFONY__, strip the first part and convert all the double underscores into a .
Source code
See line 568 to 608

In symfony you can override the cache (and logs) directory by extending the method in AppKernel.
// app/appKernel.php
class AppKernel extends Kernel
{
// ...
public function getCacheDir()
{
return $this->rootDir.'/'.$this->environment.'/cache';
}
}
Check out http://symfony.com/doc/current/cookbook/configuration/override_dir_structure.html#override-cache-dir

I used the configuration solution from Dragnic but I put the paths in the parameters.yml file because this file is ignored by git. in other words, it's not synchronized from my PC to the git repository so there is no impact in the prod environment.
# app/config/parameters.yml
parameters:
database_driver: pdo_mysql
[...]
kernel.cache_dir: "T:/project/cache"
kernel.logs_dir: "T:/project/logs"
Configuration: Windows7, WAMP 2.4 and Symfony 2.3.20.
But you have to know that:
Overwriting the kernel.cache_dir parameter from your config file is a very bad idea, and not a supported way to change the cache folder in Symfony.
It breaks things because you would now have different cache folders for the kernel Kernel::getCacheDir() and for the parameter.
Source: https://github.com/symfony/AsseticBundle/issues/370
So you should use it only in dev environment and if you don't want to change the content of the app/AppKernel.php file, otherwise see the other answers.

No accepted answer, and a really old question, but I found it with google, so I post here a more recent way to change the cache directory, and the logs directory, (source here)
remember, short syntax for arrays require php 5.4
you can select the env to modify, and manage different cache and logs directories if you want
public function getCacheDir()
{
if (in_array($this->environment, ['prod', 'test'])) {
return '/tmp/cache/' . $this->environment;
}
return parent::getCacheDir();
}
public function getLogDir()
{
if (in_array($this->environment, ['prod', 'test'])) {
return '/var/log/symfony/logs';
}
return parent::getLogDir();
}

Related

Trait not found by Laravel base class using Composer 2 autoloader?

I'm on a Laravel project using new-ish versions of PHP, Laravel and Composer 2, as of this writing. I added a new app/Traits/MyTrait.php file beside several existing trait files but unfortunately Composer absolutely will not detect the new file. I'm getting this error:
Trait 'App\Traits\MyTrait' not found
Similar to:
Laravel Custom Trait Not Found
Here is the general layout of the code:
# app/Traits/MyTrait.php:
<?php
namespace App\Traits;
trait MyTrait {
// ...
}
# app/Notifications/MyBaseClass.php:
<?php
namespace App\Notifications;
use App\Traits\MyTrait;
class MyBaseClass
{
use MyTrait;
// ...
}
# app/Notifications/MyChildClass.php
<?php
namespace App\Notifications;
class MyChildClass extends MyBaseClass
{
// ...
}
The weird thing is that this code runs fine in my local dev, but no matter what I try, it won't work when deployed to the server while running in a Docker container. I've tried everything I can think of like saving "optimize-autoloader": true in composer.json and running composer dump-autoload -o during deployment, but nothing fixes it:
https://getcomposer.org/doc/articles/autoloader-optimization.md
I'm concerned that this inheritance permutation may not have been tested properly by Composer or Laravel, so this may be a bug in the tools. If worse comes to worse, I'll try these (potentially destructive) workarounds:
Calling composer dump-autoload -o (greatly slows deployment, as this is a large project, and so far doesn't seem to fix it anyway)
Deleting via rm vendor/composer/autoload_classmap.php, rm vendor/composer/autoload_psr4.php and/or rm vendor/composer/autoload_namespaces.php (or similar) in the vendor folder before each deployment to force Composer to rebuild.
Deleting via rm -rf vendor
The sinister part about this is that we must have full confidence in our deploy process. We can't hack this in our server dev environments by manually deleting stuff like vendor and then have it fail in the production deploy because Composer tripped over stale data in its vendor folder. My gut feeling is that this is exactly what's happening, perhaps due to an upgrade from Composer 1 to Composer 2 or version change or stale cache files from work in recent months.
Even a verification like "this minimal sample project deployed to Docker works for us" would help to narrow this down thanks.
Edit: this is a useful resource on how the Composer autoloader works: https://jinoantony.com/blog/how-composer-autoloads-php-files
The problem turned out to be caused by the container/filesystem on AWS being case-sensitive, but my local dev environment on macOS being case-insensitive.
My original trait (kept secret) ended with URL in its name, but I was including its path as, and using it in the base class as, Url.
So this issue had nothing to do with traits, base classes or Composer. It also didn't require any modification of composer.json or the way we call it during deployment. But I think it's still best practice to have this in composer.json, I use it this way in local dev too currently (good/bad?):
"config": {
"optimize-autoloader": true
},
The real problems here (industry-wide) are:
Vague error messages
Lack of effort by code to drill down and find actual causes (by attempting to load as case-insensitive and returning a warning when found, for example)
Lack of action items for the user (have you checked the case? checked that the file exists? checked file permissions? etc etc, written into the error message itself, with perhaps a link to a support page/forum)
It wasn't convenient to ssh into the server (by design). So to troubleshoot, I temporarily committed this onto my branch:
# app/Http/Controllers/TestController.php
class TestController extends Controller
{
public function test()
{
return response('<pre>' .
'# /var/www/html/vendor/composer/autoload_classmap.php' . "\n" . file_get_contents('/var/www/html/vendor/composer/autoload_classmap.php') . "\n" .
'# /var/www/html/vendor/composer/autoload_files.php' . "\n" . file_get_contents('/var/www/html/vendor/composer/autoload_files.php') . "\n" .
'# /var/www/html/vendor/composer/autoload_namespaces.php' . "\n" . file_get_contents('/var/www/html/vendor/composer/autoload_namespaces.php') . "\n" .
'# /var/www/html/vendor/composer/autoload_psr4.php' . "\n" . file_get_contents('/var/www/html/vendor/composer/autoload_psr4.php') . "\n" .
'# /var/www/html/vendor/composer/autoload_real.php' . "\n" . file_get_contents('/var/www/html/vendor/composer/autoload_real.php') . "\n" .
'# /var/www/html/vendor/composer/autoload_static.php' . "\n" . file_get_contents('/var/www/html/vendor/composer/autoload_static.php') . "\n"
);
}
}
# routes/api.php
Route::get('/test', 'TestController#test');
Then deployed without merging in GitLab and compared the response to the error in AWS Cloudwatch, which is when the typo jumped out.
Then I removed the temporary commit with:
git reset --soft HEAD^
And force-pushed my branch with:
git push --force-with-lease
So was able to solve this without affecting our CI/CD setup or committing code permanently to the develop or master branches.
I've been doing this for a lot of years, and even suspected a case-sensitivity issue here, but sometimes we're just too close to the problem. If you're knee-deep in code and about to have an anxiety attack, it helps to have another set of eyes review your thought process with you from first principles.
I also need to figure out how to run my local Docker containers as case-sensitive as well, to match the server (since that's the whole point of using Docker containers in the first place).
I had the same problem and it was related to my file name. I had put it in lowercase at the beginning, that is: apiResponser.php. I added some changes and renamed my file to ApiResponser.php and sent it to production, but ... oh, oh!
I had the same problem.
The only way it worked for me was, do the git name replacement:
📦 git mv app/Traits/apiResponser.php app/Traits/ApiResponser.php
This way I was able to solve. I understand that you have solved it in
another way, however this may help another developer. 🙂

Using sbt-native-packager, how can I simply prepend a directory to my bash script's ${app_classpath}?

My project uses sbt-native-packager with packageArchetype.java_application.
During sbt stage I have a task that generates some final Typesafe style configuration file that I then copy to:
target/universal/stage/conf/application.conf
I'd like to prepend this directory to the runtime classpath in the bash script, and am looking for the simplest way to do that. I'd hate to maintain a separate src/main/templates/bash-template for something so simple, and am not seeing exactly how to go about it otherwise.
Thanks!
Short Answer
Define a package mapping
mappings in Universal <+= (packageBin in Compile, sourceDirectory ) map {
(_, src) =>
// we are using the reference.conf as default application.conf
// the user can override settings here
val conf = src / "main" / "resources" / "reference.conf"
conf -> "conf/application.conf"
}
Create a jvmopts in src/universal/conf with
-Dconfig.file=/<installation-path>/conf/application.conf
Add to build.sbt
bashScriptConfigLocation := Some("${app_home}/../conf/jvmopts")
Example for server_archetype:
Follow the example application. A bit of description can be found here.
Long answer
Changing the classpath is not supported directly by the sbt-native-packager, because it can cause problems like
classpath ordering
security issues
Like Typesafe Config, most libraries which use config files, provide a parameter to define the location of the configuration file. Use the parameters describe in the documentation.
It seems your are trying to run a server, which means you can use the
packageArchetype.java_server
which is designed to read external configurations. Take a look at the example application how to use it.
The following setting:
scriptClasspath in bashScriptDefines ~= (cp => "../conf" +: cp),
Allows you to do exactly what you need.
In this specific example I prepend the "../conf" directory to the classpath entries.
Also, you need to import the following configuration keys to your build SBT:
import com.typesafe.sbt.packager.Keys.bashScriptDefines
import com.typesafe.sbt.packager.Keys.scriptClasspath
The question you asked in the title is a bit different from the description. I am answering the question in the title here - i.e. how can you prepend a directory into the classpath:
This is very hacky and brittle in that it will probably break if/when the sbt-native-packager makes changes to how the script is generated, but for now it works for me:
private lazy val ClasspathPattern = "declare -r app_classpath=\"(.*)\"\n".r
bashScriptDefines := bashScriptDefines.value.map {
case ClasspathPattern(classpath) => "declare -r app_classpath=\"/path/to/some/external/lib/*:" + classpath + "\"\n"
case _#entry => entry
},

How to disable Kint in local environment under Laravel 4

I'm using Kint via Composer in Laravel 4 by loading kint first in composer.json so that dd() is defined by kint, not laravel (suggested here).
I want to leave debug calls in my app, and disable Kint if not in the local environment. I'm successfully using config overrides for Anvard using the following structure:
/app/config/local/packages/provider/package_name/overridefile.php
Unfortunately, this is not working for Kint with the following structure:
/app/config/packages/raveren/kint/local/config.php or
/app/config/packages/raveren/kint/local/config.default.php
The Kint documentation states:
You can optionally copy the included config.default.php and rename to config.php to override default values…
…which works for me (/vendor/raveren/kint/config.php)
How do I achieve this:
without editing a file in the /vendor/ directory that will get overwritten by composer
so that kint is only enabled in the local envirnoment
I've also tried adding the following to a helpers.php file which is called before composer in /bootstrap/autoload.php as suggested here:
<?php
isset( $GLOBALS['_kint_settings'] ) or $GLOBALS['_kint_settings'] = array();
$_kintSettings = &$GLOBALS['_kint_settings'];
/** #var bool if set to false, kint will become silent, same as Kint::enabled(false) or Kint::$enabled = false */
$_kintSettings['enabled'] = false;
unset( $_kintSettings );
(but no dice :)
Any suggestions? TIA!
I'm not familiar with kint but checked the documentation and found that, to disable kint output, you may use (in runtime)
// to disable all output
Kint::enabled(false);
In Laravel you can check the environment using
$env = App::environment();
if($env == 'your_predefined_environment') {
Kint::enabled(false);
}
To configure your environment, you may check the documentation.
Update : I've setup my local environment as givel below (in bootstrap/start.php)
$env = $app->detectEnvironment(array(
'local' => array('*.dev'),
));
And in my local machine, I've setup a virtual mashine which has laravel4.dev as it's base url, so if I visit the app using laravel4.dev or laravel4.dev/logon then I can check the environment in my BaseController.php and it detects the local environment because of .dev
public function __construct()
{
if(App::environment() == 'local') {
// do something
}
}
In your case, I don't know where is the first debug/trace you used to print the output, so you should keep the environment checking and disabling the Kint code before you use any debug/trace but you may try this (if it works for you) but you can check the environment in your filter/routes files too.
Hmm.. I'm not sure if this is the ideal way to do it, but this works, and seems Laravel'ish:
// top of app/start/global.php
Kint::enabled(false);
and
// app/start/local.php
Kint::enabled(true);
(assuming you've got a local environment defined: see #TheAlpha's answer for more info)
http://laravel.com/docs/lifecycle#start-files

composer and site configuration files

Is it possible to install a file out of the 'vendor' directory when doing a composer install/update?
Let me elaborate a bit more if your not sure what i mean.
I have a config file(s) that are stored in /config/ini/<filename>.ini and lots of vendor modules in the vendor directory. Would it be possible to package the ini files with the vendor packages so upon installation they are written to the correct directory?
Ideally I need to be able to achieve this because i have an Authentication vendor module that will need to be installed in various different applications. Being able to do this will mean that the private key and other shared configuration options can be stored with the vendor module (in a private repo ofc).
Thanks Mike
Yes, you can. You need to create a script which is attached to post-install-cmd or post-update-cmd. That script will look in the package directories, select the issues and dump them in the correct dir.
It'll be somewhere around these lines:
use Composer\Script\CommandEvent;
class ScriptHandler
{
public function bundleConfigs(CommandEvent $event)
{
$homeDir = $event->getComposer()->getConfig()->get('home');
$vendorDir = $event->getComposer()->getConfig()->get('vendor-dir');
$files = glob($vendorDir, '/*Module/config/*.ini');
foreach ($files as $file) {
copy($file, $homeDir.'/config/ini/'.basename($file));
}
}
}

How can I change config file path in Codeigniter?

I use Codeigniter framework , and you know when I try to load a config file then use it
I do something like that :
$this->load->config('myconfig', TRUE);
myconfig.php file is located inside application folder ( application/config/myconfig.php)
and use it like this :
$this->config->item('get_item', 'myconfig')
My question is : how can I change the location of myconfig file and use it properly ?
I want to put the config file(s) in out folder like this :
mysite -> system(folder)
mysite -> user_guide(folder)
mysite -> myConfigFiles(folder)
mysite -> myConfigFiles(folder) / myconfig.php
I need to do something like this :
$this->load->config(base_url.'myConfigFiles/myconfig', TRUE);
any help ?
Yes - it is possible to do this. The loader will accept ../../relative/paths. You can use a path relative from the default config directory (an absolute path will not work).
So let's say you have this structure (had a hard time following your description):
mysite
application
config <-- default directory
system
myConfigFiles
myconfig.php
You can just do this:
$this->load->config('../../myConfigFiles/myconfig', TRUE);
This works for pretty much everything - views, libraries, models, etc.
Note that with the introduction of the ENVIRONMENT constant in version 2.0.1, you can automatically check for config files within the config directory in another directory that matches the name of the current environment. This is really intended to be a convenience method for loading different files depending on if you are in production or development. I'm not 100% sure what your goals are, but this additional knowledge may also help you achieve them, or it may be totally irrelevant.
Really not sure WHY you would want to do this (and I wouldn't recommend it), but since all config files are is regular PHP files you can put a config file in the standard location that loads your extra config files. As an example:
mysite -> application -> config -> myconfigloader.php
then in myconfigloader.php put this:
<?php
require_once(APPPATH.'../myConfigFiles/myconfig.php');
So once you do
$this->load->config('myconfigloader', TRUE);
It will load everything in your myconfig.php file. Let me know if that works for you.

Resources