├── .gitignore ├── LICENSE ├── README.md ├── composer.json ├── src └── ScopeExit.php └── tests └── BasicTest.php /.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | vendor/ 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 by Sara Golemon 2 | 3 | Some rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | * Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above 13 | copyright notice, this list of conditions and the following 14 | disclaimer in the documentation and/or other materials provided 15 | with the distribution. 16 | 17 | * The names of the contributors may not be used to endorse or 18 | promote products derived from this software without specific 19 | prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ScopeExit 2 | 3 | This simple class provides an implementation of C++'s `SCOPE_EXIT`, or GoLang's `defer`. 4 | 5 | To use, assign an instance of this object to a local variable. When that variable falls out of scope (or is explicitly `unset`), the callback passed to the constructor will be invoked. This is useful, for example, to aid cleanup at the end of a function. 6 | 7 | ```php 8 | function f(&$x) { 9 | $x = 1; 10 | $_ = new \PhpLang\ScopeExit(function() use (&$x) { $x = 2; }); 11 | // $x is still 1 at this point. 12 | return 42; 13 | // After the return, the local scope is cleaned up, the closure is invoked, and it's set to 2 14 | } 15 | 16 | f($a); 17 | var_dump($a); // int(2) 18 | ``` 19 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "phplang/scope-exit", 3 | "description": "Emulation of SCOPE_EXIT construct from C++", 4 | "type": "library", 5 | "keywords": [ 6 | "cleanup", 7 | "scope", 8 | "exit" 9 | ], 10 | "homepage": "https://github.com/phplang/scope-exit", 11 | "license": "BSD", 12 | "authors": [ 13 | { 14 | "name": "Sara Golemon", 15 | "email": "pollita@php.net", 16 | "homepage": "https://twitter.com/SaraMG", 17 | "role": "Developer" 18 | } 19 | ], 20 | "autoload": { 21 | "psr-4": { 22 | "PhpLang\\": "src/" 23 | } 24 | }, 25 | "require-dev": { 26 | "phpunit/phpunit": "*" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/ScopeExit.php: -------------------------------------------------------------------------------- 1 | onexit = $onexit; 31 | } 32 | 33 | /** 34 | * Invoke the callback since the object is falling out of scope 35 | */ 36 | public function __destruct() { 37 | $cb = $this->onexit; 38 | $cb(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/BasicTest.php: -------------------------------------------------------------------------------- 1 | assertEquals(1, $arg); 13 | return; 14 | } 15 | 16 | public function testFCall() { 17 | $x = 0; 18 | $this->fCall($x); 19 | $this->assertEquals(2, $x); 20 | } 21 | 22 | public function testUnset() { 23 | $x = 0; 24 | $_ = new ScopeExit(function() use (&$x) { $x = 123; }); 25 | $this->assertEquals(0, $x); 26 | unset($_); 27 | $this->assertEquals(123, $x); 28 | } 29 | } 30 | --------------------------------------------------------------------------------