Symfony 3.2 - set environment variables in runtime [duplicate] - doctrine-orm

In my config.yml I have this:
parameters:
gitek.centro_por_defecto: 1
Now, I want to change this value from my controller using a form, like this:
public function seleccionAction(Request $request)
{
$entity = new Centro();
$form = $this->createForm(new SeleccionType(), $entity);
$centro = $this->container->getParameter('gitek.centro_por_defecto');
if ($this->getRequest()->getMethod() == 'POST') {
$form->bind($this->getRequest());
if ($form->isValid()) {
$miseleccion = $request->request->get('selecciontype');
$this->container->setParameter('gitek.centro_por_defecto', $miseleccion['nombre']);
// return $this->redirect($this->generateUrl('admin_centro'));
}
}
return $this->render('BackendBundle:Centro:seleccion.html.twig', array(
'entity' => $entity,
'form' => $form->createView(),
));
}
I´m getting Impossible to call set() on a frozen ParameterBag. error all the time.
Any help or clue?

You can't modify Container once it has been compiled, which is done before invoking the controller.
The DIC parameters are intended for configuration purposes - not a replacement for global variables. In addition it seems you want to persist some kind of permanent modification. In that case consider using session if it's a per-user modification or persisting it (e.g. into DB) if it's supposed to be application-wide.
If you need to modify DIC parameters or services, you can do so using a compiler pass. More info on how to write custom compiler passes can be found at:
http://symfony.com/doc/master/cookbook/service_container/compiler_passes.html

You can set $_ENV variables and get that after
putenv("VAR=1");
And to get
getenv("VAR");

Related

Symfony4 returning serialized json repsonse

I'm looking at a new Symfony5 project , where I'm trying to return a JSON response of some data.
I have a Project and a ProjectItem
I have the following:
// Project.php
/**
* #ORM\OneToMany(targetEntity="App\Entity\ProjectItem", mappedBy="project")
*/
private $projectItems;
// ProjectItem.php
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Project", inversedBy="projectItems")
*/
private $project;
I have one Project, that can have many ProjectItems
I then have a controller that I'm trying to return a json response:
public function index()
{
$itemsList = $this->getDoctrine()
->getRepository(Project::class)
->findAll();
$items = $this->get('serializer')->serialize($itemsList, 'json');
return new Response($items, 200);
}
This is currently returning an error:
A circular reference has been detected when serializing the object of class "App\Entity\Project" (configured limit: 1)
Am I using the serializer correctly or are my models incorrectly configured?
Simply use json_encode:
public function index()
{
$itemsList = $this->getDoctrine()
->getRepository(Project::class)
->findAll();
return new Response(
json_encode($itemsList),
200
);
}
or use JsonResponse class:
return new JsonResponse($itemsList);
You have a circular reference with your relations. Im guessing ProjectItem has a field project that is referencing Project which causes a loop for the serializer. You can ignore said attribute to prevent this from happening. Checkout the ignored attributes section of the serializer documentation.
Another option would be to use Serialization Groups. Every property would get a Group annotation like for example #Groups("group1") excluding that reference property back to Project.
You would then tell the serializer to serialize that group:
$json = $serializer->serialize(
$itemList,
'json', ['groups' => 'group1']
);
You may also checkout JMS Serializer which adds #Exclude and #Include annotations to make this step a bit easier.

How can I test a Yii2 model in a library project?

I'm trying to implement an adapter that is using a Yii model object extending yii\db\ActiveRecord. The object is passed as constructor arg to the adapter class.
My issue is now that I still couldn't figure out how to get this to work properly. I've even tried mocking it but got stuck because Yii is using lots of static methods to get it's objects. Sure, I could now try to mock them... But there must be a better way?
public function testSuccessFullFind(): void
{
$connection = (new Connection([
'dsn' => 'sqlite:test'
]))
->open();
$queryBuilder = new \yii\db\sqlite\QueryBuilder($connection);
$app = $this->createMock(Application::class);
\Yii::$app = $app;
$app->expects($this->any())
->method('getDb')
->willReturn($this->returnValue($connection));
$userModel = new UserModel();
$resovler = new Yii2Resolver($userModel);
$result = $resolver->find(['username' => 'test', 'password' => 'test']);
// TBD asserts for the result
}
The UserModel is used to find a user record internally.
This results in:
1) Authentication\Test\Identifier\Resolver\Yii2ResolverTest::testSuccessFullFind
Error: Call to a member function getDb() on null
vendor\yiisoft\yii2-dev\framework\db\ActiveRecord.php:135
vendor\yiisoft\yii2-dev\framework\db\ActiveQuery.php:312
vendor\yiisoft\yii2-dev\framework\db\Query.php:237
vendor\yiisoft\yii2-dev\framework\db\ActiveQuery.php:133
tests\TestCase\Identifier\Resolver\Yii2ResolverTest.php:31
The code above is obviously the WIP of a test case.
So how can I configure a test connection and get my ActiveRecord object to use it?
You can pass connection as argument of all() method:
$results = UserModel::find()->where(['id' => 1])->all($connection);

Test JSON-returning controller method without MissingViewError

I am testing a Controller method that has only a JSON view. My method runs as expected, but the test method only returns "MissingViewException". Is there a solution to avoiding this exception in the unit test (besides inserting an empty file at View/People/map_leads.ctp)?
PeopleController.php
public function mapLeads($territory_id = null) {
$leads = $this->Person->getPeople([
'territory_id' => $territory_id
]);
$this->set('leads', $leads);
}
AppController.php
public $components = ['RequestHandler'];
routes.php
Router::parseExtensions('json');
PeopleControllerTest.php
public function testMapLeads() {
$id = 40;
$result = $this->testAction('/people/mapLeads/' . $id, array('return' => 'vars'));
}
View/People/json/map_leads.ctp exists and is properly utilized by CakePHP; it is only the test that wants to see View/People/map_leads.ctp.
I checked at CakePHP: calling testAction to a json-returning method causes missing view exception reminding about adding RequestHandler to $components. This does not resolve the exception.
You aren't issuing a JSON request/accessing a JSON endpoint, as neither your request URL does contain the .json extension, nor does your request send an appropriate Accept header (I don't remember whether the latter is possible with the 2.x controller test case class at all).
Use the .json extension and you should be good.
$this->testAction('/people/mapLeads/' . $id . '.json', array('return' => 'vars'));
Write this code inside your action.
$this->autoLayout = false;
$this->autoRender = false;
$this->response->type('application/javascript');

cakephp 2.6 controller test case throwing MissingActionException on duplicate testAction()-call

I hope anyone can help me out with my testing environment.
my setup
I am implementing unit tests based on phpunit 3.7.22 with the cake release 2.6.9. Running on ubuntu 12.04 LTS with PHP 5.4.43-1 and postgresql 9.1.
I immplemented controller tests mocking cakes Auth Component to have a user in the session, since my tests depent on that. My controllers return json results, since its an API for a JS-based frontend. I call my controller methods using the testAction() call of a generated controller.
<?php
App::uses('RequesttypesController', 'Svc.Controller');
class RequesttypesWithResultControllerTest extends ControllerTestCase
{
public $fixtures = array(
'app.requesttype',
'app.user',
'app.privilege',
'app.groupsprivilege',
'app.groupsuser',
'app.groupscompany',
'app.company',
);
/**
* Mock the requesttype object so that it can return results depending on the desired outcome
*
* #see CakeTestCase::setUp()
*/
public function setUp()
{
parent::setUp();
$this->controller = $this->generate('Svc.Requesttypes', array(
'models' => array(
'Requesttype'
),
'components' => array(
'Auth' => array(
'user'
),
'Session',
'RequestHandler'
)
));
$this->controller->Auth->staticExpects($this->any())
->method('user')
->will($this->returnValue(array(
'id' => 123,
'username' => 'myTestUser',
'company' => 'myTestCompany',
'usertype_id' => '456',
))
);
$authResult = $this->controller->Auth->user();
}
public function tearDown()
{
parent::tearDown();
unset($this->controller);
}
/**
* A logged in user produces a number of requesttypes
*/
public function testLoggedInUser()
{
$result = $this->testAction('/svc/requesttypes/getMyRequesttypes', array('return' => 'vars'));
$this->assertNotEmpty($this->vars, 'Did not receive webservice response');
$this->assertTrue(isset($this->vars['data']['code']), 'Received invalid webservice response');
$this->assertEqual($this->vars['data']['code'], SvcAppController::RESPONSE_CODE_SUCCESS);
}
}
?>
This test passes without errors. Now I want to test my controller-action with different setups, for example users with a different usertype, from a different company, and so on. If I now create a second test-method in my RequesttypesWithResultControllerTest-class, calling the same testAction-url, i get a MissingActionException saying:
"Action RequesttypesController::() could not be found."
It seems that the testAction calls an empty controller-action, even if the action-url is passed as a parameter. I tried reinitializing the controller by nulling it and calling $this->generate() again, but this does not help either.
Of course I can help myself out by creating an own test-controller for every test ending up in a bunch of duplicate test-code, but this somehow seems not right to me.
Am I misusing the test-environment or how can this exception be explained? Any ideas?
Thanks in advance for sharing my headache!
After some further code debugging we finally found the error. We accidently changed the require statement of the last line of the /Config/routes.php file to a require_once because of some "Class already defined Exceptions" thrown in the test-environment.
Wrong routes.php:
require_once CAKE . 'Config' . DS . 'routes.php';
For the application itself that made no difference, since the routes are only needed to be initialized once per request. But in a test-environment, the routes are reinitialized several times, which was not possible anymore with the require_once include.
This is how the line is supposed to look like, which it does by default:
Correct routes.php:
require CAKE . 'Config' . DS . 'routes.php';

Drupal preprocess function and session

I set a session var at template preprocess function in a theme I use, but the first time I open the site I cant read the session var, if I refresh the page it works fine, anybody know what can be the problem??
This is the code I use in the preprocess function:
function m_preprocess(&$vars, $hook) {
$default_location = array(
'country_code' => 'ec',
'province_code' => 'p',
'province' => 'Pichincha',
'city' => 'Quito',
'city_path' => 'lugares/u/ec/p/*'
);
if (isset($_COOKIE['proximity_path'])) $default_location['proximity_path'] = $_COOKIE['proximity_path'];
$default_location['path'] = isset($_COOKIE['sort-by']) && $_COOKIE['sort-by']=='proximity'? $_COOKIE['proximity_path'] : $default_location['city_path'];
$_SESSION['location'] = $default_location;
}
A couple of things:
Try dsm($_SESSION); to see what is the var content when the site first load.
I don't know where you create $_COOKIE['proximity_path'], but it is not in the code you show.
Check for typos
The template pre-process function is called before node.tpl.php (that's why it is called pre-process) and that is why the value of the $_SESSION variable is not available in the template preprocess function.
Like you pointed out, it works after the first page load. This happens when only after $_SESSION variable is set in the node body (using the PHP filter)