Symfony2 change log directory outside app (rootDir) - symfony

Here is my code, from symfony book.
public function getCacheDir() {
return $this->rootDir . '/access-logs/' . $this->environment . '/cache/';
}
public function getLogDir() {
return $this->rootDir . '/access-logs/' . $this->environment . '/logs/';
}
Now the directory is at PROJECTNAME/app/access-logs/dev/cache
But i need at PROJECTNAME/access-logs/dev/cache
NOTE : "I need outside app directory and inside project directory"

I presume you are editing this is AppKernel.php? Try this:
public function getCacheDir() {
return dirname(__DIR__) . '/access-logs/' . $this->environment . '/cache/';
}
public function getLogDir() {
return dirname(__DIR__) . '/access-logs/' . $this->environment . '/logs/';
}
dirname(__DIR__) returns the path to the PROJECTNAME dir.

The solution from symfony3
public function getRootDir()
{
return __DIR__;
}
public function getCacheDir()
{
return dirname(__DIR__).'/var/cache/'.$this->getEnvironment();
}
public function getLogDir()
{
return dirname(__DIR__).'/var/logs';
}
Now the location is PROJECT_DIR/var/ just change var/cache to access-logs

Related

Symfony / Fixtures "Reference already exists, use method setReference in order to override it"

I created 2 fixtures files and want to link them but got the error : Reference to "genre_reference" already exists, use method setReference in order to override it.
Here is my book fixtures :
class LivreFixtures extends Fixture implements DependentFixtureInterface
{
public function load(ObjectManager $manager): void
{
$faker = Factory::create('fr_FR');
$faker->seed(123);
for ($i = 0; $i < 10; $i++) {
$livre = new Livre();
$livre->setTitre($faker->sentence($nbWords = 4, $variableNbWords = true));
$livre->setAuteur($faker->name);
$livre->setDescription($faker->text);
$livre->setDateDeParution($faker->dateTime($format = 'Y-m-d'));
$livre->setGenre($this->getReference('genre_reference'));
$manager->persist($livre);
}
$manager->flush();
}
public function getDependencies()
{
return array(
GenreFixtures::class,
);
}
}
And my genre fixtures file :
class GenreFixtures extends Fixture
{
public function load(ObjectManager $manager): void
{
$faker = Factory::create('fr_FR');
$faker->seed(123);
for ($i=0; $i < 5; $i++) {
$genre = new Genre();
$genre->setName($faker->colorName);
$manager->persist($genre);
$this->addReference('genre_reference', $genre);
}
$manager->flush();
}
}
I don't really understand the setreference method, how to do it. Any help ?
I think you should add $i to your genre reference name.
$this->addReference('genre_reference_' . $i, $genre);
After that, you can use it by
$this->getReference('genre_reference_0');
//OR
$this->getReference('genre_reference_1');
//OR
$this->getReference('genre_reference_' . $i);

phpunit with psr-4 autoload needs manual "require" statement

I'm following the EmailTest example at https://phpunit.de/getting-started/phpunit-9.html. It works fine.
As I change the autoload from classmap to psr-4, I found that I needed to manually add this require __DIR__ . '/../vendor/autoload.php'; to make my tests work. Without it, I got Class 'App\Email' not found error.
My question is why the original example using classmap does not need that require line.
My codes are as follows.
composer.json
{
"autoload": {
"psr-4": {
"App\\": "src"
}
},
"require-dev": {
"phpunit/phpunit": "^9"
}
}
tests/EmailTest.php
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use App\Email;
require __DIR__ . '/../vendor/autoload.php';
final class EmailTest extends TestCase
{
public function testCanBeCreatedFromValidEmailAddress(): void
{
$this->assertInstanceOf(
Email::class,
Email::fromString('user#example.com')
);
}
public function testCannotBeCreatedFromInvalidEmailAddress(): void
{
$this->expectException(InvalidArgumentException::class);
Email::fromString('invalid');
}
public function testCanBeUsedAsString(): void
{
$this->assertEquals(
'user#example.com',
Email::fromString('user#example.com')
);
}
}
src/Email.php
<?php declare(strict_types=1);
namespace App;
final class Email
{
private $email;
private function __construct(string $email)
{
$this->ensureIsValidEmail($email);
$this->email = $email;
}
public static function fromString(string $email): self
{
return new self($email);
}
public function __toString(): string
{
return $this->email;
}
private function ensureIsValidEmail(string $email): void
{
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new \InvalidArgumentException(
sprintf(
'"%s" is not a valid email address',
$email
)
);
}
}
}
I realised that psr-4 does not actually need this require __DIR__ . '/../vendor/autoload.php';. Because phpunit already does it behind the scene.
How I fixed the issue is I run composer dump-autoload. I thought I did not need to do it for psr-4. But anyway I fixed the issue.

Setting body classes in Zend

I am working on a Zend 1.12 application and trying to get style classes assigned to layout body tag.
I found this sample Bootstrap.php file that seems to handle the task:
https://gist.github.com/fideloper/1302688
It seems to integrate nicely, but the body's class always comes out blank.
Can someone please point me in the right direction here on how to get classes assigned to body?
Thanks.
Made a small change to the snippet I referenced above.
class AppName_Helper_BodyClass extends Zend_View_Helper_Placeholder_Container_Standalone {
private $_classes = array();
public function __construct($classes = null) {
if(is_array($classes)) {
$this->addClass($classes);
}
}
public function addClass($class) {
if(is_array($class)) {
foreach($class as $k => $c) {
if(is_string($c)) {
if(is_string($k)) {
$this->addClass($k.'-'.$c); //recursion
} else {
$this->addClass($c);
}
} else {
throw new Zend_Exception('Class must be a string - is type: '.gettype($c));
}
}
return $this;
}
if(is_string($class)) {
$this->_classes[] = $class;
return $this;
} else {
throw new Zend_Exception('Class must be a string - is type: '.gettype($class));
}
return $this;
}
public function removeClass($class) {
$key = array_search($class, $this->_classes);
if($key !== false) {
unset($this->_classes[$key]);
}
return $this;
}
public function bodyClass() {
return $this;
}
public function toString() {
return implode(' ', $this->_classes);
}
}
This snippet goes into my layout:
$uri = Zend_Controller_Front::getInstance()->getRequest()->getParams();
$this->bodyClass()->addClass($uri);
The results is such (for module - "default", controller - "auth", action - "signin"):
<body class="controller-auth action-signin module-default">
I am grabbing current request's parameters and mapping them to the body class. Hope this helps someone dealing with this.
From the look of that helper you need to call one of it's methods to add a class. From one of your controllers:
$this->view->bodyClass()->addClass('something');
is that how you are using it?

Doctrine 2 custom type

I am trying to follow the example at
http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/types.html
and create a custom quantity type. Everything works fine when quantity type is defined as:
class Quantity extends Type
{
const QUANTITY = 'quantity'; // modify to match your type name
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return 'decimal(10,2)';
}
public function getName()
{
return self::QUANTITY;
}
}
However when introducting
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
return $value->toDecimal();
}
I get the following error when saving:
FatalErrorException: Error: Call to a member function toDecimal() on a non-object in ...\Types\Quantity.php line 26
The $value you get is either string or null. You can't call toDecimal on it. Try:
public function convertToDatabaseValue($value, AbstractPlatform $platform) {
return $value === null ? null : (float) $value;
}

Symfony2 + Twig: Translate label into a new twig extension

I have implemented a new twig extension and I have some text which had to be translated.
Unfortunately when I use a code label it appears as a sample text.
I mean when twig render this following extension, it displays: 5 entity.years instead of 5 years for example:
class MyExtension extends \Twig_Extension {
public function getFilters()
{
return array(
'myextension' => new \Twig_Filter_Method($this, 'myextension'),
);
}
public function myextension ($myId)
{
// ....
// Some operations concerning $myId...
// ....
if($myId!=0) {
$res = $myId. ' '.'entity.year';
} else {
$res = ($months == 0 ? $days.'entity.days' : $months.'entity.months');
}
return $res;
}
}
Where entity.years, entity.months, entity.days is defined into my translations folder.
Inject the translator service into your extension and use it. For example:
class MyExtension extends \Twig_Extension
{
private $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
// ...
public function myMethod()
{
return $this->translator->trans('my_string');
}
}

Resources