4
votes

Ok so we have this MASSIVE bare metal php project that we want to slowly convert over into Symfony3

It's a constantly changing and updated project so we need this to be transparent, to make sure not to disrupt the people who are using it. They shouldn't notice a difference at all.

So the solution we decided to try was this:

  1. Stick the whole application into the /web
  2. Keep the authenticator script in the legacy application (it's far too complex to port to the new one, and then update the old one to make use of the new session system) as all it's doing is setting a couple $_SESSION keys
  3. Nowhere else in the application is setting any session variables, just the authenticator.

The problem is that the suffering through configuration of the Legacy Bridge, and a few choice stack overflow answers havent gotten us anywhere.

  1. Using the Bridge
    Configuring with the bridge as this doc says didn't affect anything except that the session it was reading from had nothing added to the $_SESSION['_sf2_attributes'] assoc or anywhere else for that matter.

  2. Using the Bridge Component
    As per this document that describes using the PhpBridgeSessionStorage component, when configured, would output along the lines of:

ContextErrorException in classes.php line 83: Warning: ini_set(): A session is active. You cannot change the session module's ini settings at this time

When I combine it with the first method, it becomes exactly liek the first method. It works, BUT I see absolutely NONE of the session data set in the legacy app, in my symfony controller

DefaultController.php on line 16:
array:3 [▼
  "_sf2_attributes" => & []
  "_sf2_flashes" => & []
  "_sf2_meta" => & array:3 [▼
    "u" => 1469839893
    "c" => 1469836213
    "l" => "0"
  ]
]
DefaultController.php on line 17:
Session {#2519 ▼
  #storage: PhpBridgeSessionStorage {#2520 ▼
    #bags: array:2 [▼
      "attributes" => AttributeBag {#2218 ▼
        -name: "attributes"
        -storageKey: "_sf2_attributes"
        #attributes: & []
      }
      "flashes" => FlashBag {#2219 ▼
        -name: "flashes"
        -flashes: & []
        -storageKey: "_sf2_flashes"
      }
    ]
    #started: true
    #closed: false
    #saveHandler: SessionHandlerProxy {#2522 ▼
      #handler: SessionHandler {#2217}
      #wrapper: true
      #saveHandlerName: "files"
    }
    #metadataBag: MetadataBag {#2521 ▼
      -name: "__metadata"
      -storageKey: "_sf2_meta"
      #meta: & array:3 [▼
        "u" => 1469839893
        "c" => 1469836213
        "l" => "0"
      ]
      -lastUsed: 1469839892
      -updateThreshold: "0"
    }
  }
  -flashName: "flashes"
  -attributeName: "attributes"
}
  1. Using a Listener
    One of the most popular "solutions" to this issue was this one from this SO answer

But when setup, and setup with a listener in app/config/services.yml like this: services: session.legacy: class: AppBundle\Session\LegacySessionHandler tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

we get an error like this:

LogicException in NativeSessionStorage.php line 240: Cannot register a bag when the session is already started.

I understand what this solution is trying to do, but it stuffers two problems from my side:

I feel that by the time the kernel.request fires and my classes method is invoked, the event is supposed to still see actual real data set outside of the symfony context stored in the $_SESSION super global. As its supposed to kinda loop through the $_SESSION assoc and apply that data to a new bag.

1st problem is that there's nothing to set. There is no key's set from the legacy app found in the session assoc that the listener has to work with

2nd problem is that for some reason, i'm blocked from registereing a new bag...

  1. The "F-it" approach

Because I could SEE keys like _sf2_attributes in the legacy app when I var_dump the $_SESSION super global, I decided hey why not just get the authenticator to dump it's keys into the _sf2_attributes key instead of the root!

This didn't work either. Like, at all. None of it shows up in my symfony controller.


I'm near my wits end here. Is this a bug, is this by design?

1
What are your session INI settings, as seen by Symfony after your legacy session has started and before Symfony starts?bishop

1 Answers

2
votes

I had this same problem and solved it by adding this in the config.yml:

session: 
        storage_id: session.storage.native
        handler_id: session.handler.native_file
        save_path: ~

To debug, I used the following PHP code in two places: 1) in a legacy script. 2) in a symfony controller.

$sessPath   = ini_get('session.save_path');
$sessCookie = ini_get('session.cookie_path');
$sessName   = ini_get('session.name');

echo '<br>sessPath: ' . $sessPath;
echo '<br>sessCookie: ' . $sessCookie;
echo '<br>sessName: ' . $sessName;

My issue was that the session.save_path was different for symfony vs. the legacy application. Therefore, the symfony code could not access my legacy $_SESSION variables.

Adding, the following line the config.yml fixed the problem:

save_path: ~

After I fixed this, the symfony controller code can see all of the $_SESSION variables directly:

echo "<pre>"; print_r($_SESSION); echo "</pre>";

No need for the "class LegacySessionHandler implements EventSubscriberInterface" solution, mentioned in the other stackoverflow question. (part 3 of this question)