It provides the ability to restore an object to it’s previous state (undo
via rollback) or to gain access to state of the object, without revealing
it’s implementation (i.e., the object is not required to have a function
to return the current state).

The memento pattern is implemented with three objects: the Originator, a
Caretaker and a Memento.

Memento – an object that contains a concrete unique snapshot of state of
any object or resource: string, number, array, an instance of class and so on.
The uniqueness in this case does not imply the prohibition existence of similar
states in different snapshots. That means the state can be extracted as
the independent clone. Any object stored in the Memento should be
a full copy of the original object rather than a reference to the original
object. The Memento object is a “opaque object” (the object that no one can
or should change).

Originator – it is an object that contains the actual state of an external
object is strictly specified type. Originator is able to create a unique
copy of this state and return it wrapped in a Memento. The Originator does
not know the history of changes. You can set a concrete state to Originator
from the outside, which will be considered as actual. The Originator must
make sure that given state corresponds the allowed type of object. Originator
may (but not should) have any methods, but they they can’t make changes to
the saved object state.

Caretaker controls the states history. He may make changes to an object;
take a decision to save the state of an external object in the Originator;
ask from the Originator snapshot of the current state; or set the Originator
state to equivalence with some snapshot from history.

<?phpnamespaceDesignPatterns\Behavioral\Memento;/** * Ticket is the "Originator" in this implementation */classTicket{/** * @var State */private$currentState;publicfunction__construct(){$this->currentState=newState(State::STATE_CREATED);}publicfunctionopen(){$this->currentState=newState(State::STATE_OPENED);}publicfunctionassign(){$this->currentState=newState(State::STATE_ASSIGNED);}publicfunctionclose(){$this->currentState=newState(State::STATE_CLOSED);}publicfunctionsaveToMemento():Memento{returnnewMemento(clone$this->currentState);}publicfunctionrestoreFromMemento(Memento$memento){$this->currentState=$memento->getState();}publicfunctiongetState():State{return$this->currentState;}}

<?phpnamespaceDesignPatterns\Behavioral\Memento\Tests;useDesignPatterns\Behavioral\Memento\State;useDesignPatterns\Behavioral\Memento\Ticket;usePHPUnit\Framework\TestCase;classMementoTestextendsTestCase{publicfunctiontestOpenTicketAssignAndSetBackToOpen(){$ticket=newTicket();// open the ticket$ticket->open();$openedState=$ticket->getState();$this->assertEquals(State::STATE_OPENED,(string)$ticket->getState());$memento=$ticket->saveToMemento();// assign the ticket$ticket->assign();$this->assertEquals(State::STATE_ASSIGNED,(string)$ticket->getState());// now restore to the opened state, but verify that the state object has been cloned for the memento$ticket->restoreFromMemento($memento);$this->assertEquals(State::STATE_OPENED,(string)$ticket->getState());$this->assertNotSame($openedState,$ticket->getState());}}