├── src ├── config │ └── laravel-firebase.php ├── HttpHandler │ ├── FirebaseInterface.php │ ├── HttpHandlerFactory.php │ ├── Guzzle5HttpHandler.php │ └── Guzzle6HttpHandler.php ├── Provider │ └── FirebaseServiceProvider.php ├── Subscribers │ └── EnsureJson.php ├── GoogleConsole.php ├── Middleware │ └── EnsureJson.php └── Firebase.php ├── .idea └── vcs.xml ├── tests ├── unit │ └── SampleTest.php └── _env │ └── ServiceAccount.json ├── phpunit.xml ├── composer.json └── README.md /src/config/laravel-firebase.php: -------------------------------------------------------------------------------- 1 | storage_path('app/secret_file.json') 6 | 7 | ]; -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/unit/SampleTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 10 | } 11 | 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/HttpHandler/FirebaseInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | tests 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Provider/FirebaseServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 14 | __DIR__.'/../config/laravel-firebase.php' => config_path('laravel-firebase.php'), 15 | ], 'config'); 16 | 17 | } 18 | 19 | public function register() { 20 | 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /src/Subscribers/EnsureJson.php: -------------------------------------------------------------------------------- 1 | getRequest(); 15 | } 16 | 17 | /** 18 | * @return array 19 | */ 20 | public function getEvents() 21 | { 22 | return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]]; 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /tests/_env/ServiceAccount.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "service_account", 3 | "project_id": "project", 4 | "private_key_id": "private_key_id", 5 | "private_key": "-----BEGIN PRIVATE KEY-----ADD KEY HERE-----END PRIVATE KEY-----\n", 6 | "client_email": "client@email.tld", 7 | "client_id": "1234567890", 8 | "auth_uri": "https://some.google.tld/o/oauth2/auth", 9 | "token_uri": "https://some.google.tld/o/oauth2/token", 10 | "auth_provider_x509_cert_url": "https://some.google.tld/oauth2/v1/certs", 11 | "client_x509_cert_url": "https://some.google.tld/robot/v1/metadata/x509/user%40project.iam.gserviceaccount.com" 12 | } 13 | -------------------------------------------------------------------------------- /src/HttpHandler/HttpHandlerFactory.php: -------------------------------------------------------------------------------- 1 | =5.3.0", 14 | "guzzlehttp/guzzle": "~5.3|~6.0", 15 | "guzzlehttp/psr7": "~1.2", 16 | "illuminate/support": "^5.2.8" 17 | 18 | }, 19 | "authors": [ 20 | { 21 | "name": "Luqman", 22 | "email": "luqmanrom@gmail.com" 23 | } 24 | ], 25 | "autoload": { 26 | "psr-4": { 27 | "Geckob\\Firebase\\": "src" 28 | } 29 | }, 30 | "require-dev": { 31 | "phpunit/phpunit": "^6" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/GoogleConsole.php: -------------------------------------------------------------------------------- 1 | scopes = [ 15 | 'https://www.googleapis.com/auth/userinfo.email', 16 | 'https://www.googleapis.com/auth/firebase.database', 17 | ]; 18 | 19 | $this->credentials = [ 20 | 'client_email' => $config['client_email'], 21 | 'client_id' => $config['client_id'], 22 | 'private_key' => $config['private_key'], 23 | ]; 24 | } 25 | 26 | public function getCredentials() 27 | { 28 | return $this->credentials; 29 | } 30 | 31 | public function getScopes() 32 | { 33 | return $this->scopes; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/Middleware/EnsureJson.php: -------------------------------------------------------------------------------- 1 | getUri(); 15 | $path = $uri->getPath(); 16 | 17 | if (substr($path, -5) !== '.json') { 18 | $uri = $uri->withPath($path.'.json'); 19 | $request = $request->withUri($uri); 20 | } 21 | 22 | $request = $request->withHeader('Content-Type', 'application/json'); 23 | 24 | return $handler($request, $options); 25 | }; 26 | }; 27 | } 28 | 29 | 30 | 31 | } -------------------------------------------------------------------------------- /src/Firebase.php: -------------------------------------------------------------------------------- 1 | 0]) 18 | { 19 | if (func_num_args() == 0) { 20 | $secretFilePath = config('laravel-firebase.secretPath'); 21 | } 22 | 23 | $this->config = array_merge($this->extractSecrets($secretFilePath), $config); 24 | 25 | $googleConsole = new GoogleConsole($this->config); 26 | 27 | $this->httpClient = HttpHandlerFactory::setup($this->config, $this->path, $googleConsole); 28 | 29 | } 30 | 31 | private function extractSecrets($secretFilePath) 32 | { 33 | $config = file_get_contents($secretFilePath); 34 | return json_decode($config, true); 35 | } 36 | 37 | public function setPath($path) 38 | { 39 | $this->path = $path; 40 | 41 | $this->httpClient->setPath($path); 42 | 43 | return $this; 44 | } 45 | 46 | 47 | public function set($key, $value) 48 | { 49 | $this->httpClient->set($key, $value); 50 | } 51 | 52 | public function get($key) 53 | { 54 | return $this->httpClient->get($key); 55 | } 56 | 57 | public function delete($key) 58 | { 59 | $this->httpClient->delete($key); 60 | } 61 | 62 | public function push($arr) 63 | { 64 | $this->httpClient->push($arr); 65 | } 66 | 67 | 68 | } -------------------------------------------------------------------------------- /src/HttpHandler/Guzzle5HttpHandler.php: -------------------------------------------------------------------------------- 1 | config = $config; 26 | 27 | $this->databaseUri = sprintf('https://%s.firebaseio.com/', $this->config['project_id']); 28 | 29 | $this->http = new Client([ 30 | 'base_url' => $this->databaseUri, 31 | 'defaults' => [ 32 | 'auth' => 'google_auth' 33 | ] 34 | ]); 35 | 36 | $this->http->getEmitter()->attach(new AuthTokenSubscriber( 37 | new ServiceAccountCredentials( 38 | $googleConsole->getScopes(), 39 | $googleConsole->getCredentials() 40 | ))); 41 | } 42 | 43 | public function setPath($path) 44 | { 45 | $this->path = $path; 46 | } 47 | 48 | public function set($key, $value) 49 | { 50 | $response = $this->http->put($this->path . $key . '.json', 51 | ['body' => json_encode($value), 'timeout' => $this->config['timeout']]); 52 | 53 | return (string) $response->getBody(); 54 | 55 | } 56 | 57 | public function get($key) 58 | { 59 | $response = $this->http->get($this->path. $key . '.json', ['timeout' => $this->config['timeout']]); 60 | 61 | return (string) $response->getBody(); 62 | 63 | 64 | } 65 | 66 | public function delete($key) 67 | { 68 | $response = $this->http->delete($this->path. $key . '.json', ['timeout' => $this->config['timeout']]); 69 | 70 | return (string) $response->getBody(); 71 | } 72 | 73 | public function push($arr) 74 | { 75 | $response = $this->http->post($this->path . '.json', 76 | ['body' => json_encode($arr), 'timeout' => $this->config['timeout']]); 77 | 78 | return (string) $response->getBody(); 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /src/HttpHandler/Guzzle6HttpHandler.php: -------------------------------------------------------------------------------- 1 | config = $config; 28 | 29 | $this->databaseUri = new Uri(sprintf('https://%s.firebaseio.com', $this->config['project_id'])); 30 | 31 | $googleAuthTokenMiddleware = new AuthTokenMiddleware( 32 | new ServiceAccountCredentials( 33 | $googleConsole->getScopes(), 34 | $googleConsole->getCredentials() 35 | )); 36 | 37 | $stack = HandlerStack::create(); 38 | $stack->push(EnsureJson::run(), 'ensure_json'); 39 | $stack->push($googleAuthTokenMiddleware, 'auth_service_account'); 40 | 41 | $this->http = new Client([ 42 | 'base_uri' => $this->databaseUri, 43 | 'handler' => $stack, 44 | 'auth' => 'google_auth', 45 | ]); 46 | 47 | } 48 | 49 | public function setPath($path) { 50 | $this->path = $path; 51 | } 52 | 53 | public function set($key, $value) 54 | { 55 | 56 | $response = $this->http->request('PUT', $this->databaseUri->withPath($this->path.$key), 57 | ['body' => json_encode($value), 'timeout' => $this->config['timeout']] 58 | ); 59 | 60 | return $response->getBody()->getContents(); 61 | 62 | 63 | } 64 | 65 | public function get($key) 66 | { 67 | 68 | $response = $this->http->request('GET', $this->databaseUri->withPath($this->path. $key, 69 | ['timeout' => $this->config['timeout']])); 70 | 71 | return $response->getBody()->getContents(); 72 | 73 | } 74 | 75 | public function delete($key) 76 | { 77 | $response = $this->http->request('DELETE', $this->databaseUri->withPath($this->path. $key, 78 | ['timeout' => $this->config['timeout']])); 79 | 80 | return $response->getBody()->getContents(); 81 | } 82 | 83 | public function push($arr) 84 | { 85 | $response = $this->http->request('POST', $this->databaseUri->withPath($this->path), 86 | ['body' => json_encode($arr), 'timeout' => $this->config['timeout']]); 87 | 88 | return $response->getBody()->getContents(); 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firebase PHP Wrapper 2 | 3 | 4 | [![Packagist](https://img.shields.io/packagist/dt/geckob/firebase.svg)](https://packagist.org/packages/geckob/firebase) 5 | 6 | 7 | This package makes the authentication and the basic CRUD 8 | operation on Firebase Database as simple as possible. 9 | For now, it supports both Guzzle 5 and Guzzle 6. 10 | 11 | 12 | ## Installation 13 | 14 | The easiest way it via Composer 15 | 16 | ``` 17 | composer require geckob/firebase 18 | ``` 19 | 20 | ## Usages 21 | 22 | 23 | ### 1. Authentication 24 | 25 | **1.1 Generate Service Account secret file** 26 | 27 | This package supported authentication using secrets file generated in the Service Account page. 28 | 29 | To generate the secret file, follow this steps 30 | 31 | 1. Go to [Firebase Console](https://console.firebase.google.com/) 32 | 2. Choose your project 33 | 3. Click the gear icon and go to Project Settings 34 | 4. Click the Service Accounts tab 35 | 5. Scroll down and click "Generate New Private Key" button. Save it to somewhere secure but 36 | accessible for your internal server 37 | 38 | **1.2 Use the secret file to authenticate** 39 | 40 | ```php 41 | $firebase = new \Geckob\Firebase\Firebase('path_to_your_secret_file.json'); 42 | ``` 43 | ### 2. CRUD Operation 44 | 45 | The CRUD operation on Firebase Database is based on the [Firebase REST API Docs](https://www.firebase.com/docs/rest-api.html). 46 | 47 | Assuming the authentication is succesfully done, 48 | 49 | ```php 50 | // Set the parent node. 51 | $firebase = $firebase->setPath('bookings/'); 52 | 53 | // Create a new node with key = test and value = testValue. 54 | // If the node already exist, it will update the value 55 | $firebase->set('test','testValue'); 56 | 57 | // Support multiple nodes, if it doesnt exist, it will create the node 58 | $firebase->set('testObject/testKey', 'testValueObject'); 59 | 60 | 61 | // Same as set but without keys. This requires to call setPath first to identify the parent 62 | $firebase->push([ 63 | 'test' => 'value', 64 | 'test1' => 'value1' 65 | ]); 66 | 67 | // Get the value of node with key = test 68 | $firebase->get('test'); 69 | 70 | // Get the value of using multilevel key 71 | $firebase->get('testObject/testKey'); 72 | 73 | 74 | 75 | 76 | // Delete the node with key = test 77 | $firebase->delete('test'); 78 | 79 | // Delete the multilevel node and all it's children 80 | $firebase->delete('testObject/testKey'); 81 | 82 | 83 | ``` 84 | 85 | // 86 | 87 | ## Others 88 | 89 | This package works perfectly fine for my use case for now. Should you have any other 90 | use cases that requires me to extend the features, or suggestions how this package 91 | can be improved, feel free to open issues or email me at luqmanrom@gmail.com 92 | 93 | 94 | ## License 95 | 96 | #### The MIT License (MIT) 97 | ``` 98 | Copyright (c) 2012-2016 Tamas Kalman 99 | 100 | Permission is hereby granted, free of charge, to any person obtaining a copy 101 | of this software and associated documentation files (the "Software"), to deal 102 | in the Software without restriction, including without limitation the rights 103 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 104 | copies of the Software, and to permit persons to whom the Software is 105 | furnished to do so, subject to the following conditions: 106 | 107 | The above copyright notice and this permission notice shall be included in 108 | all copies or substantial portions of the Software. 109 | 110 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 111 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 112 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 113 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 114 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 115 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 116 | THE SOFTWARE. 117 | ``` 118 | 119 | 120 | 121 | --------------------------------------------------------------------------------