PHP : $ _SESSION 내부에 '객체'저장


188

방금 $ _SESSION에 객체를 저장할 수 있다는 것을 알았 습니다. 다른 페이지로 이동할 때 여전히 객체가 있기 때문에 꽤 멋집니다. 이제이 방법을 사용하기 전에 이것이 실제로 좋은 아이디어인지 또는 잠재적 인 함정 이 있는지 확인하고 싶습니다 .

단일 진입 점을 가지고 있다면 그렇게 할 필요는 없지만 아직 거기에 없기 때문에 단일 진입 점이 없으며 실제로 물건을 보관하고 싶습니다. 내 상태를 잃어 버리지 (이제 상태 비 저장 사이트를 프로그래밍해야하지만 해당 개념을 아직 이해하지 못한다는 내용도 읽었습니다.)

그래서 짧은 :이 세션에서 저장 개체에 대한 확인인가, 그것으로 어떤 문제가 있습니까?


편집하다:

임시 요약 : 이제는 데이터베이스를 다시 쿼리해야하더라도 개체 를 다시 만드는 것이 좋습니다 .

추가 답변은 해당 측면 에서 좀 더 정교 해질 수 있습니다!


13
2008 년 '어리석은'어떻게 :-)
markus

49
2014 년에 우리처럼 멍청한 사람에게 유용한 질문 : D
Momin Al Aziz

3
아주 좋은 질문은 마르쿠스을 요청했습니다 .. :) 오늘 그것을 읽고)
gkd

1
당신은 바보 아니었다! 당신은 내가 무엇을 물어볼 것인지 물었고 10 년 후에는 견실했습니다.
toddmo

글쎄, 난 그냥 2019에 바보 같은 질문에서 저를 저장 추측
맥스웰

답변:


133

이 주제가 오래되었다는 것을 알고 있지만이 문제는 계속 발생하며 만족스럽게 해결되지 않았습니다.

$ _SESSION에 객체를 저장하거나 숨겨진 양식 필드에 저장된 데이터를 기반으로 전체 천을 재구성하거나 매번 DB에서 객체를 다시 쿼리 할 때 상태를 사용합니다. HTTP는 상태가 없지만 (거의; GET vs. PUT 참조) 웹 응용 프로그램과 관련된 거의 모든 사람이 상태를 유지해야합니다. 마치 국가를 구석 구석으로 밀어 넣는 것처럼 행동하는 것은 일종의 이론적 승리에 불과합니다. 상태는 상태입니다. 상태를 사용하면 상태 비 저장으로 인해 얻을 수있는 다양한 기술적 이점이 사라집니다. 미리 잠을 잃어야한다는 것을 알지 않는 한 잠을 잃을 일이 아닙니다.

나는 행크 게이 (Hank Gay)가 제시 한 "이중 whammy"논증에 의해받은 축복에 특히 당황 스럽다. OP는 분산되고로드 밸런싱 된 전자 상거래 시스템을 구축하고 있습니까? 내 추측은 아니요입니다. 그리고 그의 $ User 클래스 등을 직렬화하면 서버를 복구 할 수 없을 것입니다. 내 충고 : 응용 프로그램에 적합한 기술을 사용하십시오. $ _SESSION의 객체는 상식주의 사항에 따라 괜찮습니다. 앱이 갑자기 트래픽에 영향을 미치는 Amazon으로 바뀌면 다시 적응해야합니다. 인생이 다 그렇지.


16
내가 이것을 통해 읽었을 때 내 자신의 생각을 많이 포함시키는 멋진 대답. 현대 인터넷 상태가 필요합니다 . 일부 응용 프로그램은 상태가 필요없고 상태 비 저장 방식으로 만드는 것이 합리적이지만 현대 인터넷은 상태를 기반으로하는 너무 많은 시스템 (AKA : Logins!)을 사용하여 포기합니다! 인터넷의 위대한 신들은 그 기본 개념을 쿠키 형태로 몇 년 동안 통합했으며, 기본 수준에서 HTML의 로컬 저장소 형태로 추가했습니다. 일부 응용 프로그램에서는 과도한 상태 사용을 피하는 것이 합리적 이지만 일부는! = 모두!
RonLugge

글쎄, 사람이 불을 발명 한 직후에 그 질문을했을 때, 나는 오늘 내가 알고있는 많은 것을 알지 못했습니다. 그 동안 몇 가지 유용한 사용 사례가있을 수 있지만 일반적으로 다른 솔루션을 먼저 찾게됩니다. 다른 답변은 범주 형이므로 여전히 이것을 새로운 허용 답변으로 표시하십시오.
markus 2019

대답이 거의 없어서 크게 웃게됩니다. 이건 브라보 +1
toddmo

114

session_start () 호출 시간, 클래스 선언 / 정의가 이미 PHP에서 발생했거나 이미 설치된 오토로더에서 찾을 수있는 한 괜찮습니다. 그렇지 않으면 세션 저장소에서 객체를 직렬화 해제 할 수 없습니다.


12
감사! 버그 수정 : D
Matt Ellen

적절한 __autoload()기능 이 있으면이 문제를 피할 수 있다고 가정합니다 .
Langel

직렬화 된 객체를 직렬화 해제하려면 클래스 정의를 추가해야합니까 ??? 객체를 직렬화 할 때 클래스 정의가 필요하다는 데 동의하지만 직렬화 된 객체를 직렬화 해제 해야하는 파일에도 클래스 정의를 추가해야합니까 ???
Rajesh Paul

35

HTTP는 이유없는 상태 비 저장 프로토콜입니다. 세션은 HTTP에 상태를 용접합니다. 경험상 세션 상태를 사용하지 마십시오.

업데이트 : HTTP 수준에는 세션 개념이 없습니다. 서버는 클라이언트에게 고유 한 ID를 부여하고 클라이언트에게 모든 요청에 ​​대해 다시 제출하도록 지시함으로써이를 제공합니다. 그런 다음 서버는 해당 ID를 Session 개체의 큰 해시 테이블에 대한 키로 사용합니다. 서버는 요청을받을 때마다 클라이언트가 요청과 함께 제출 한 ID를 기반으로 세션 오브젝트의 해시 테이블에서 세션 정보를 찾습니다. 이 모든 추가 작업은 확장성에 대한 두 가지 이유입니다 (HTTP가 상태 비 저장 인 큰 이유).

  • Whammy One : 단일 서버가 수행 할 수있는 작업을 줄입니다.
  • Whammy Two : 요청을 이전 서버로 라우팅 할 수 없기 때문에 확장이 어려워집니다. 모두 동일한 세션을 가지고 있지는 않습니다. 주어진 세션 ID를 가진 모든 요청을 동일한 서버에 고정 할 수 있습니다. 쉬운 일이 아니며 단일 장애 지점입니다 (시스템 전체가 아니라 많은 사용자를위한). 또는 클러스터의 모든 서버에서 세션 스토리지를 공유 할 수 있지만 이제 네트워크 연결 메모리, 독립형 세션 서버 등과 같이 더 복잡합니다.

모든 것을 감안할 때 세션에 더 많은 정보를 넣으면 Vinko가 지적한 것처럼 성능에 미치는 영향이 커집니다. Vinko가 지적한 것처럼 객체를 직렬화 할 수 없으면 세션이 제대로 작동하지 않습니다. 따라서 경험상 세션에 반드시 필요한 것 이상을 두지 마십시오.

@Vinko 일반적으로 보낸 응답에 추적중인 데이터를 포함시키고 클라이언트가 다시 제출하도록 (예 : 숨겨진 입력으로 데이터를 전송) 서버 저장 상태를 유지할 수 있습니다. 서버 측 상태 추적 이 실제로 필요한 경우 백업 데이터 저장소에 있어야합니다.

(Vinko는 다음과 같이 덧붙입니다. PHP는 세션 정보를 저장하기 위해 데이터베이스를 사용할 수 있으며, 클라이언트가 매번 데이터를 다시 제출하도록하면 잠재적 인 확장 성 문제가 해결 될 수 있지만, 클라이언트가 모든 것을 제어 할 수 있다는 점에주의해야합니다. 당신의 상태)


1
HTTP 레벨에는 세션 개념이 없습니다. 서버는 클라이언트에게 고유 한 ID를 부여하고 클라이언트에게 모든 요청에 ​​대해 다시 제출하도록 지시함으로써이를 제공합니다. 그런 다음 서버는 해당 ID를 Session 개체의 큰 해시 테이블에 대한 키로 사용합니다. 계속…
행크 게이

1
서버는 요청을받을 때마다 클라이언트가 요청과 함께 제출 한 ID를 기반으로 세션 오브젝트의 해시 테이블에서 세션 정보를 찾습니다. 이 모든 추가 작업은 확장성에 대한 두 가지 이유입니다 (HTTP가 상태 비 저장 인 큰 이유). ... 계속하려면
행크 게이

1
어떻게 든 용접 상태없이 어떻게 HTTP를 통해 복잡한 애플리케이션을 구현할 수 있을지 궁금합니다
Vinko Vrsalovic

3
이 모든 의견을 포함하도록 답변을 수정하십시오. 위키에서는 읽기 쉽고 더 좋으며 어쨌든 주석에 중요한 모든 것이 있으면 대답을 수락 된 답변으로 선택할 수 없습니다. 감사!
markus

6
"허 악한 사람"나는 이것을 더 많이 내리고 싶다. 당신의 타이밍을 알아라. 메모리 참조 비용은 100 나노초 또는 0.0001ms입니다. 따라서 메인 메모리에 저장된 해시 테이블을 조회하는 데 문자 그대로 시간이 들지 않습니다. 당신 O(1)에게 무언가를 말 합니까 ? @whammy 2 : 모든 요청을 무작위로 임의의 서버로 라우팅하지 않습니까? 라운드 로빈을 수행하고 동일한 사용자로부터 동일한 서버로 라우팅을 유지하십시오. 이건 정말 분명하다. 30 개 이상의
투표

19
  • 직렬화 할 수 없거나 직렬화 할 수없는 멤버를 포함하는 오브젝트는 예상대로 $ _SESSION에서 나오지 않습니다.
  • 거대한 세션으로 인해 서버에 부담이 발생합니다 (매번 비용이 많이 드는 상태를 직렬화 및 역 직렬화하면 비용이 많이 듭니다)

그 외에는 아무런 문제가 없었습니다.


9

내 경험상, 일반적으로 일부 속성이있는 StdClass보다 복잡한 것에 대해서는 가치가 없습니다. 직렬화 해제 비용은 항상 세션 저장 식별자가 지정된 데이터베이스에서 다시 작성하는 것 이상이었습니다. 멋진 것처럼 보이지만 프로파일 링이 핵심입니다.


모든 요청에서 5x2 데이터 테이블 쿼리와 세션에서 결과 캐싱 및 사용 간의 성능에 대한 의견이 있습니까?
musicliftsme

6

절대적으로 필요한 경우가 아니면 상태를 사용하지 않는 것이 좋습니다. 세션을 사용하지 않고 오브젝트를 재 빌드 할 수있는 경우 수행하십시오. 웹 응용 프로그램에 상태가 있으면 응용 프로그램을 더 복잡하게 만들 수 있습니다. 모든 요청에 ​​대해 사용자의 상태를 확인해야합니다. 물론 세션 사용을 피할 수없는 경우가 있습니다 (예 : 세션이 진행되는 동안 사용자는 로그인 상태를 유지해야 함) 웹 애플리케이션). 마지막으로 세션 개체를 가능한 한 작게 유지하여 성능에 영향을 주어 큰 개체를 직렬화 및 직렬화 해제하는 것이 좋습니다.


따라서 모든 데이터베이스 쿼리를 다시 수행하는 것을 포함하여 객체를 다시 작성하는 것이 더 낫습니까? 이 작업에 대한 내 생각 중 하나는 동일한 물건에 대해 db를 다시 쿼리 할 필요가 없다는 것입니다.
markus

3
중요한 경우 데이터베이스를 다시 쿼리하지 않으므로 세션에 저장하는 대신 캐싱을 사용하십시오. 그러나 캐싱 빌드와 같은 작업을 수행하기 전에 실제로 성능이 저하되는지 확인하십시오.
Johnny

고마워, 나는 실제로 그렇지 않다고 생각합니다. 다시 쿼리해야합니다.
markus

4

리소스 유형 (예 : db 연결 또는 파일 포인터)은 페이지로드간에 유지되지 않으므로 보이지 않게 다시 만들어야합니다.

또한 세션 크기에 따라 저장 방법, 크기 제한 또는 대기 시간 문제가있을 수 있습니다.


0

소프트웨어 라이브러리를 업그레이드 할 때도 일 어설 것입니다. 소프트웨어를 업그레이드했고 이전 버전에는 V1 소프트웨어의 클래스 이름으로 세션에 개체가 있었으며 새 소프트웨어는 세션에 있던 개체를 V2로 만들려고 할 때 충돌했습니다. 소프트웨어는 더 이상 같은 클래스를 사용하지 않아 찾을 수 없었습니다. 우리는 세션 객체를 감지하고 발견되면 세션을 삭제하고 페이지를 다시로드하기 위해 수정 코드를 넣어야했습니다. 가장 큰 고통은 처음 에이 버그가 처음보고되었을 때 (너무 친숙한, "잘 작동한다") 버그를 재현하고 있다는 것을 염두에 두었습니다. 모든 사용자가 세션에 이전 세션 변수를 가지고 있었으며 모든 사용자에게 충돌을 일으켰으므로 출시 전에 발견했습니다.

어쨌든 수정 안에서 제안한 것처럼 객체를 다시 만드는 것이 좋습니다. 따라서 ID를 저장 한 다음 각 요청에서 데이터베이스에서 객체를 가져 오는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.