Skip to content

Commit 80c738a

Browse files
committed
refactor to slim app
1 parent ac7e74a commit 80c738a

File tree

8 files changed

+213
-135
lines changed

8 files changed

+213
-135
lines changed

cloud_sql/mysql/pdo/README.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,10 @@
22

33
## Before you begin
44

5-
1. Before you use this code sample, you need to have [Composer](https://getcomposer.org/) installed or downloaded into this folder. Download instructions can be found [here](https://getcomposer.org/download/).
5+
1. Before you use this code sample, you need to have [Composer](https://getcomposer.org/) installed or downloaded into this folder. Download instructions can be found [here](https://getcomposer.org/download/). Once you've installed composer, use it to install required dependencies by running `composer install`.
66
2. Create a MySQL Cloud SQL Instance by following these [instructions](https://cloud.google.com/sql/docs/mysql/create-instance). Note the connection string, database user, and database password that you create.
77
3. Create a database for your application by following these [instructions](https://cloud.google.com/sql/docs/mysql/create-manage-databases). Note the database name.
88
4. Create a service account with the 'Cloud SQL Client' permissions by following these [instructions](https://cloud.google.com/sql/docs/mysql/connect-external-app#4_if_required_by_your_authentication_method_create_a_service_account). Download a JSON key to use to authenticate your connection.
9-
5. Use the information noted in the previous steps:
10-
11-
```bash
12-
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json
13-
export CLOUD_SQL_CONNECTION_NAME='::'
14-
export DB_USER='my-db-user'
15-
export DB_PASS='my-db-pass'
16-
export DB_NAME='my-db-name'
17-
export DB_HOSTNAME='localhost'
18-
```
19-
20-
Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Cloud KMS](https://cloud.google.com/kms/) to help keep secrets safe.
219

2210
## Running Locally
2311

@@ -45,6 +33,19 @@ $ ./cloud_sql_proxy \
4533
--credential_file=$GOOGLE_APPLICATION_CREDENTIALS
4634
```
4735

36+
Set the required environment variables for your connection to Cloud SQL. If you are using TCP mode as described above, do not set the `CLOUD_SQL_CONNECTION_NAME` variable.
37+
38+
```bash
39+
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service/account/key.json
40+
export CLOUD_SQL_CONNECTION_NAME='::'
41+
export DB_USER='my-db-user'
42+
export DB_PASS='my-db-pass'
43+
export DB_NAME='my-db-name'
44+
export DB_HOSTNAME='localhost'
45+
```
46+
47+
Note: Saving credentials in environment variables is convenient, but not secure - consider a more secure solution such as [Secret Manager](https://cloud.google.com/secret-manager/) to help keep secrets safe.
48+
4849
Execute the following:
4950

5051
```bash

cloud_sql/mysql/pdo/app.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
runtime: php72
1616

1717
# Remember - storing secrets in plaintext is potentially unsafe. Consider using
18-
# something like https://cloud.google.com/kms/ to help keep secrets secret.
18+
# something like https://cloud.google.com/secret-manager/ to help keep secrets
19+
# secret.
1920
env_variables:
2021
CLOUD_SQL_CONNECTION_NAME: ::
2122
DB_USER: my-db-user
2223
DB_PASS: my-db-pass
23-
DB_NAME: my_db
24+
DB_NAME: my-db
2425

2526
# Defaults to "serve index.php" and "serve public/index.php". Can be used to
2627
# serve a custom PHP front controller (e.g. "serve backend/index.php") or to

cloud_sql/mysql/pdo/composer.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "google/cloud-sql-mysql-example",
3+
"autoload": {
4+
"psr-4": {
5+
"Google\\Cloud\\Samples\\CloudSQL\\MySQL\\": "src"
6+
}
7+
},
8+
"require": {
9+
"slim/slim": "^4.5",
10+
"slim/twig-view": "^3.1",
11+
"pimple/pimple": "^3.3",
12+
"guzzlehttp/psr7": "^1.6",
13+
"http-interop/http-factory-guzzle": "^1.0"
14+
}
15+
}

cloud_sql/mysql/pdo/index.php

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,36 @@
1515
* limitations under the License.
1616
*/
1717

18-
require_once 'src/DB.php';
19-
require_once 'src/Votes.php';
18+
declare(strict_types=1);
2019

21-
use Google\Cloud\Samples\CloudSQL\MySQL\DB;
22-
use Google\Cloud\Samples\CloudSQL\MySQL\Votes;
20+
use GuzzleHttp\Psr7;
2321

24-
$votes = new Votes(DB::createPdoConnection());
22+
include __DIR__ . '/vendor/autoload.php';
2523

26-
if ($_SERVER['REQUEST_URI'] == '/' && $_SERVER['REQUEST_METHOD'] == 'GET') {
27-
$list = $votes->list();
24+
$app = include __DIR__ . '/src/app.php';
2825

29-
$vote_count = $votes->count_candidates();
30-
$tab_count = $vote_count['tabs'];
31-
$space_count = $vote_count['spaces'];
26+
$app->get('/', function ($request, $response) {
27+
return $this->get('view')->render($response, 'template.twig', [
28+
'votes' => $this->get('votes')->listVotes(),
29+
'tabCount' => $this->get('votes')->getCountByValue('TABS'),
30+
'spaceCount' => $this->get('votes')->getCountByValue('SPACES'),
31+
]);
32+
});
3233

33-
include_once("./template.php");
34-
} elseif ($_SERVER['REQUEST_URI'] == '/' && $_SERVER['REQUEST_METHOD'] == 'POST') {
34+
$app->post('/', function ($request, $response) {
3535
$message = 'Invalid vote. Choose Between TABS and SPACES';
3636

37-
if (!empty($_POST['team']) && in_array($_POST['team'], ['SPACES', 'TABS'])) {
38-
$message = $votes->save($_POST['team']);
37+
$formData = $request->getParsedBody() + [
38+
'voteValue' => ''
39+
];
40+
41+
if (in_array($formData['voteValue'], ['SPACES', 'TABS'])) {
42+
$message = $this->get('votes')->insertVote($formData['voteValue'])
43+
? 'Vote cast for ' . $formData['voteValue']
44+
: 'An error occurred';
3945
}
4046

41-
echo $message;
42-
}
47+
return $response->withBody(Psr7\stream_for($message));
48+
});
49+
50+
$app->run();

cloud_sql/mysql/pdo/src/DB.php

Lines changed: 0 additions & 54 deletions
This file was deleted.

cloud_sql/mysql/pdo/src/Votes.php

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,68 +15,89 @@
1515
* limitations under the License.
1616
*/
1717

18+
declare(strict_types=1);
19+
1820
namespace Google\Cloud\Samples\CloudSQL\MySQL;
1921

2022
use PDO;
2123

24+
/**
25+
* Manage votes using the Cloud SQL database.
26+
*/
2227
class Votes
2328
{
29+
/**
30+
* @var PDO
31+
*/
2432
private $connection;
2533

34+
/**
35+
* @param PDO $connection A connection to the database.
36+
*/
2637
public function __construct(PDO $connection)
2738
{
2839
$this->connection = $connection;
29-
$this->create_table();
40+
$this->createTable();
3041
}
3142

32-
private function create_table()
43+
/**
44+
* Creates the table if it does not yet exist.
45+
*
46+
* @return void
47+
*/
48+
private function createTable()
3349
{
3450
$sql = "CREATE TABLE IF NOT EXISTS votes (
3551
vote_id INT NOT NULL AUTO_INCREMENT,
3652
time_cast DATETIME NOT NULL,
37-
candidate VARCHAR(6) NOT NULL,
53+
vote_value VARCHAR(6) NOT NULL,
3854
PRIMARY KEY (vote_id)
3955
);";
4056

4157
$this->connection->exec($sql);
4258
}
4359

44-
public function list()
60+
/**
61+
* Returns a list of the last five votes
62+
*
63+
* @return array
64+
*/
65+
public function listVotes() : array
4566
{
46-
$sql = "SELECT candidate, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5";
67+
$sql = "SELECT vote_value, time_cast FROM votes ORDER BY time_cast DESC LIMIT 5";
4768
$statement = $this->connection->prepare($sql);
4869
$statement->execute();
49-
return $statement->fetchAll();
70+
return $statement->fetchAll(PDO::FETCH_ASSOC);
5071
}
5172

52-
public function count_candidates()
73+
/**
74+
* Get the number of votes cast for a given value.
75+
*
76+
* @param string $value
77+
* @param int
78+
*/
79+
public function getCountByValue(string $value) : int
5380
{
54-
$sql = "SELECT COUNT(vote_id) as voteCount FROM votes WHERE candidate = ?";
55-
$count = [];
81+
$sql = "SELECT COUNT(vote_id) as voteCount FROM votes WHERE vote_value = ?";
5682

5783
$statement = $this->connection->prepare($sql);
84+
$statement->execute([$value]);
5885

59-
//tabs
60-
$statement->execute(['TABS']);
61-
$count['tabs'] = $statement->fetch()[0];
62-
63-
//spaces
64-
$statement->execute(['SPACES']);
65-
$count['spaces'] = $statement->fetch()[0];
66-
67-
return $count;
86+
return (int) $statement->fetch(PDO::FETCH_COLUMN);
6887
}
6988

70-
public function save($team)
89+
/**
90+
* Insert a new vote into the database
91+
*
92+
* @param string $value The value to vote for.
93+
* @return boolean
94+
*/
95+
public function insertVote(string $value) : bool
7196
{
72-
$sql = "INSERT INTO votes (time_cast, candidate) VALUES (NOW(), :candidate)";
97+
$sql = "INSERT INTO votes (time_cast, vote_value) VALUES (NOW(), :voteValue)";
7398
$statement = $this->connection->prepare($sql);
74-
$statement->bindParam('candidate', $team);
75-
76-
if ($statement->execute()) {
77-
return "Vote successfully cast for '$team'";
78-
}
99+
$statement->bindParam('voteValue', $value);
79100

80-
return print_r($statement->errorInfo(), true);
101+
return $statement->execute();
81102
}
82103
}

cloud_sql/mysql/pdo/src/app.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
2+
/*
3+
* Copyright 2020 Google LLC.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
declare(strict_types=1);
19+
20+
use Google\Cloud\Samples\CloudSQL\MySQL\Votes;
21+
use Pimple\Container;
22+
use Pimple\Psr11\Container as Psr11Container;
23+
use Slim\Factory\AppFactory;
24+
use Slim\Views\Twig;
25+
use Slim\Views\TwigMiddleware;
26+
27+
$container = new Container;
28+
AppFactory::setContainer(new Psr11Container($container));
29+
$app = AppFactory::create();
30+
31+
$container['votes'] = function (Container $container) {
32+
return new Votes($container['db']);
33+
};
34+
35+
$container['db'] = function () {
36+
$username = getenv("DB_USER");
37+
$password = getenv("DB_PASS");
38+
$schema = getenv("DB_NAME");
39+
$hostname = getenv("DB_HOSTNAME") ?: "127.0.0.1";
40+
$cloud_sql_connection_name = getenv("CLOUD_SQL_CONNECTION_NAME");
41+
42+
try {
43+
// # [START cloud_sql_mysql_pdo_create]
44+
// // $username = 'your_db_user';
45+
// // $password = 'yoursupersecretpassword';
46+
// // $schema = 'your_db_name';
47+
// // $cloud_sql_connection_name = getenv("CLOUD_SQL_CONNECTION_NAME");
48+
49+
if ($cloud_sql_connection_name) {
50+
// Connect using UNIX sockets
51+
$dsn = sprintf(
52+
'mysql:dbname=%s;unix_socket=/Users/jdp/cloudsql/%s',
53+
$schema,
54+
$cloud_sql_connection_name
55+
);
56+
} else {
57+
// Connect using TCP
58+
// $hostname = '127.0.0.1';
59+
$dsn = sprintf('mysql:dbname=%s;host=%s', $schema, $hostname);
60+
}
61+
62+
$conn = new PDO($dsn, $username, $password);
63+
# [END cloud_sql_mysql_pdo_create]
64+
} catch (PDOException $e) {
65+
throw new RuntimeException(
66+
"Could not connect to the Cloud SQL Database. " .
67+
"Refer to https://cloud.google.com/sql/docs/mysql/connect-admin-proxy " .
68+
"for more assistance. The PDO error was " . $e->getMessage(),
69+
$e->getCode(),
70+
$e
71+
);
72+
}
73+
74+
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
75+
return $conn;
76+
};
77+
78+
$container['view'] = function() {
79+
return Twig::create(__DIR__ . '/../views');
80+
};
81+
82+
$app->add(TwigMiddleware::createFromContainer($app));
83+
84+
$app->addErrorMiddleware(true, false, false);
85+
86+
return $app;

0 commit comments

Comments
 (0)