AdminBundle sonata_type_collection Delete Column: Pitfall

I ran into a problem today working with AdminBundle. Basically i am trying to manipulate the delete column that automatically gets inserted. It would not work if i check the box and hit update or global delete. It would just not do anything or remove the whole top entity.

Any thoughts?

I have tried several things but nothing. Any hint appreciated.

After this thanks to @rander hint, I was able to figure out that the way to do this was:

* @ORM\OneToMany(targetEntity="StartDate", mappedBy="course", cascade={ "persist", "remove"}, orphanRemoval="true")

The xml version on the documentation here was cryptic to my eyes even though I went through that.

Open Letter On The Behat+PHPSpec Expand-Collapse Methodology

hi,

on another note, i saw your bowling example [_md's].

I see how behat is very good on one side at the high level. You probably could have designed the class without relying on PHPSpec.

HOWEVER, if you chose to use PHPSpec once you got the red on behat and then came back after you greened all your PHPSpec descriptions just to ensure some adding of scenarios for completeness then it is great.

I believe bowling example is not very clear. But I see two patterns.

When the logic behavior (methods/what it does) described in the scenarios matches closely the class and when scenarios really describe acceptance behavior at a high level and it is not close to class behavior because the logic behavior is not very clear at the moment. This has to do I think with separation of concerns.

When separation of concerns is not clearly laid out or is mixed or embedded neatly into a behavior then it is hard to describe behavior that matches class behavior of the methods. When separation of concerns seems to be easily described with particular scenarios then we realize that separation of concerns has already been decoupled into method-like logic behavior (bowling case).

When separation of concerns is coupled and cannot be decoubled at the high level which is in most cases then extra procedure is followed:

1. PHPSpec will here be more heavily used to attempt the decoupling of the behavior in expected functionality, more and more fine grained each time or at least the description will be able to extend past the behat scenarios and can then describe some borders and more shape to what the class does. This is in all separation of concerns and some more other design.

2. After PHPSpec passes and Class(es) is(are) implemented then next step is to put to the test the Class(es) so designed and behat will fulfill the role of integration scenario BDD process.

So PHPSpec helps with separation and splitting to define finer behavior whereas Behat starts putting things back together to orchestrate things split to a larger view back together.

Expand-Collapse/Separation-Reunion concept of Design which is how things are designed.

I am currently working on a minesweeper example that shows perhaps some more clear this process… not sure how far i can get but i will try to be more clearer hopefully. Great job _md, this is a great advance in understanding these great tools! Behat+PHPSpec FTW.

Please let me know your thoughts!

Zombie Pitfalls: Part II

I ran into a problem with connection refused (111) by zombie. And I was told by @havvg to do the following. This is adapted from @havvg gist. You can find his blog here too.

    zombie:
      auto_server: false

and

var net = require('net');
var sys = require('sys');
var zombie = require('zombie');
var browser = null;
var pointers = [];
var buffer = "";
 
net.createServer(function (stream) {
  stream.setEncoding('utf8');
  stream.allowHalfOpen = true;
 
  stream.on('data', function (data) {
    buffer += data;
  });
 
  stream.on('end', function () {
    if (browser == null) {
      browser = new zombie.Browser({ debug: true });
 
      // Clean up old pointers
      pointers = [];
    }
 
    eval(buffer);
    buffer = "";
  });
}).listen(8124, '127.0.0.1');
 
console.log('Zombie.js server running at 127.0.0.1:8124');

This works.

Another problem was that zombie was interacting with modernizr library:

"TypeError: Cannot set property cssText of [object Object] which has only a gettern    at Object.a (/js/libs/modernizr-1.7.min.js:2:2493)n    at Object.flexbox (/js/libs/modernizr-1.7.min.js:2:2595)n    at Object.<anonymous> (/js/libs/modernizr-1.7.min.js:2:7228)n    at Object.<anonymous> (/js/libs/modernizr-1.7.min.js:2:8964)n    in http://h.local/app_test.php/login"

I took away the library and of course it solved the problem.

Symfony2 Zombie Behat Pitfalls

While setting up node and zombie for my first time in ubuntu I ran into problems while installing node. I resolved my problems removing via apt-get node and then installing via git and checking out the stable version which is told us in the webpage for node. The instructions for compiling and for removing also were found here. After that I was able to finish this behat guide which is a good guide teaching some more stuff on doctrine for the steps and also some nice trick with the environment variable for environment dependable database selection.

// configuration
dbname:   %database_name%_%kernel.environment%
// cli sets the environment to test
... -e=test

And this other trick removing entity entries:

$this->getEntityManager()->remove($eachEntity);

Symfony2 TDD with Phabric: Series 3

On our previous blog post on phabric series 2 we saw how we could already set up a Symfony2 project that can capitalize on the advantages provided by phabric within a Symfony2 behat environment.

This time we are going to see a bit about how to work with Phabric. Working a bit more with the settings of Phabric we realize that it supports a lot of things but it does not support read of previously inserted values. At least currently it does not support that now, hopefully it will soon. Phabric’s work is to insert some data and work with it. This is call mapping of data in Phabric. Phabric maps data to a Phabric space where information is tracked. The main object is called Phabric bus from which all operations are performed and all Phabric entities are derived. Notice that Phabric entities are not Symfony2 entities. They have different roles although for configuration it sounds like they correlate one to one sometimes. For all we have said, if we consider existing data mapping in Phabric we realize read is not implemented in the adapter. There was a proposal to subclass the adapter, however we have not gone into it yet.

Persisting Relational Data
While persisting relational data, the important concept is that usually we always persist one main entity/table from which all other tables are but child tables that are related to the main parent table. In Phabric it is always best to think in terms of the main parent table while configuring things. This is important because as long as we get right the configuration for this main table, all the other configuration will follow without problems.
For instance let’s take a look at the main configuration for a main entity `class` and a derived entity `student`. We usually have an entity class with a related column for that table giving the name of the class. However there are some instances where there will be no class name to be set depending on the specifications. In that case we set the `nameCol` to `NULL`. The related entity is `student` and for that we require a transformation to get the `id` of the related object on the derived table (notice the STUDENTLOOKUP closure defined later).

'class' =>
    array (
        'tableName' => 'class',
        'primaryKey' => 'id',
        'nameCol' => NULL,
        'nameTransformations' =>
            array (
                'Class Start' => 'class_start',
                'Student' => 'student_id',
            ),
        'dataTransformations' =>
            array (
                'student_id' => 'STUDENTLOOKUP',
            ),
        ),

After we are done with the main configuration we can proceed to fill the other configuration for student entity which is much simpler. On the Gherkin side, the scenario would provide the `student` table first and then the main table for `class`. It is important to have both of these tables and in that order because of the Phabric mapping.

  Background:
    ...
    And The following student exists
    | Student Name | Student Grade |
    | John Smith   | F             |
    And The following class exists
    | Student     | Class Start |
    | John Smith  | Summer 2011 |
    ...
 
  @insulated @passing
  Scenario: Do something else
    Then ...

You can see above that the Student column on the parent table below needs to be mapped to student_id, then searched with that name, now turned into an id, across the child table and its value returned. This thing happens whenever there is such a relationship between tables. This operation must be achieved with a data transformation closure as follows:

$this->phabric->addDataTransformation(
    'STUDENTLOOKUP', function($studentName, $bus) {
        $ent = $bus->getEntity('student');
        $id = $ent->getNamedItemId($studentName);
        return $id;
    }
);

We have used a behat background block since this sets up the scenario background common for our set of scenarios for that feature. And finally don’t forget to use the insert operation within the step definition on the Feature Context for the entity we have inserted above:

$this->phabric->insertFromTable('class', $table);

I would like to thank my friend Marco Pivetta for his patient guidance and brainstorming.

If this has helped you, please consider donating.