[PHP] Associate and operate MySQL database and then deploy the database to ECS

Use VS Code on a Mac computer to develop PHP and associate it with the MySQL database, and then deploy the database to ECS.

1. Install PHP and MySQL

Make sure you have PHP and MySQL installed on your Mac. You can use Homebrew to install them:

$ brew install php 
$ brew install mysql

After installing mysql, remember this sentence:

MySQL is configured to only allow connections from localhost by default

To connect run:
    mysql -u root

Use the following command to query the installation status:

$ php -v
$ mysql --version

Start the MySQL service:

$ brew services start mysql

Restart the MySQL service:

$ brew services restart mysql

Stop the MySQL service:

$ brew services stop mysql

2. Create MySQL users, databases and permissions

Log in to MySQL:

// 无密码直接用这一句登录
$ mysql -u root
// 也可以用这指令,输密码是直接回车跳过就是
$ mysql -u root -p

Create new database:

$ CREATE DATABASE mydatabase;

Create a new user and set a password (replace myuser and mypassword with your own settings):

$ CREATE USER'myuser'@'localhost' IDENTIFIED BY'mypassword';

Authorize new users to access the database:

$ GRANT ALL PRIVILEGES ON mydatabase.*TO'myuser'@'localhost';

Refresh permissions:

$ FLUSH PRIVILEGES;

Exit MySQL:

$ EXIT;

3. Configure PHP to connect to MySQL

You need to use PDO or mysqli extension in PHP code to connect to MySQL database.

Make sure your MySQL service is running and that you have created the appropriate users, databases, and permissions.

1).PDO

<?php
$host = '127.0.0.1';
$db   = 'your_database';
$user = 'your_username';
$pass = 'your_password';
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;dbname=$db;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}
?>

2).mysqli extension

<?php

// 数据库连接配置
$host = 'localhost';
$dbname = 'mydatabase';
$username = 'myusername';
$password = 'mypassword';

// 创建 mysqli 连接对象
$conn = new mysqli($host, $username, $password, $dbname);

// 检查连接是否成功
if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
}

// 执行查询语句
$query = "SELECT * FROM users";
$result = $conn->query($query);

// 处理结果集
if ($result->num_rows > 0) {
    while ($row = $result->fetch_assoc()) {
        echo $row['username'] . "<br>";
    }
} else {
    echo "没有结果";
}

// 关闭数据库连接
$conn->close();

?>

4. Write and run PHP code in VS Code

 Demo:https://github.com/Gamin-fzym/php_test_demo

Note: When using Launch Built-in web server configuration to run, you need to change "localhost:0" to another port, otherwise the port number will be randomly generated every time it is run, which is very inconvenient.

{
    "name": "Launch Built-in web server",
    "type": "php",
    "request": "launch",
    "runtimeArgs": [
        "-dxdebug.mode=debug",
        "-dxdebug.start_with_request=yes",
        "-S",
        "localhost:8080"
    ],
    "program": "",
    "cwd": "${workspaceRoot}",
    "port": 9003,
    "serverReadyAction": {
        "pattern": "Development Server \\(http://localhost:([0-9]+)\\) started",
        "uriFormat": "http://localhost:%s/index.html",
        "action": "openExternally"
    }
}

index.html

City information form

<!DOCTYPE html>
<html>
<head>
    <title>城市信息表单</title>
</head>
<body>
    <h1>城市信息表单</h1>
    <form action="http://localhost:8080/city.php" method="post">
        <label for="cityName">城市名称:</label>
        <input type="text" id="name" name="name" required><br><br>

        <label for="cityCode">城市编码:</label>
        <input type="text" id="code" name="code" required><br><br>

        <label for="cityCode">增删改查:</label>
        <input type="text" id="mark" name="mark" required><br><br>

        <input type="submit" value="提交">
    </form>

    <p id="jsonResponse"></p>

    <script>
        document.querySelector('form').addEventListener('submit', function (event) {
            event.preventDefault();
            // 方式一:PHP 中使用这种方式获取 $name = $_POST['name'] ?? '';
            var form = event.target;
            var formData = new FormData(form);
            fetch(form.action, {
                method: 'POST',
                body: formData
            })
            .then(response => response.json())
            .then(data => {
                document.getElementById('jsonResponse').textContent = JSON.stringify(data);
            })
            .catch(error => console.error('请求接口失败', error));

            /*
            // 方式二:PHP中用这种方式获取 $data = json_decode(file_get_contents('php://input'), true);  $name = $data['name'] ?? '';
            var form = event.target;
            var name = form.elements.name.value;
            var code = form.elements.code.value;
            var mark = form.elements.mark.value;
            var requestData = {
                name: name,
                code: code,
                mark: parseInt(mark) // mark 1:增 2:删 3:改 4:查
            };

            var xhr = new XMLHttpRequest();
            xhr.open('POST', form.action);
            xhr.setRequestHeader('Content-Type', 'application/json');
            // xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.onload = function () {
                if (xhr.status === 200) {
                    var data = JSON.parse(xhr.responseText);
                    document.getElementById('jsonResponse').textContent = JSON.stringify(data);
                } else {
                    console.error('请求接口失败');
                }
            };
            xhr.send(JSON.stringify(requestData));
            */
        });
    </script>
</body>
</html>

pdoConnect.php

PDO connection MySQL package

<?php
$host = '127.0.0.1';
$port = 3306; // MySQL默认的是3306端口
$db = 'city_database';
$user = 'gamin';
$pass = '123456';
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;port=$port;dbname=$db;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

// 连接数据库
try {
    $pdo = new PDO($dsn, $user, $pass, $options);
    createCitiesTable();
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

// 创建城市表
function createCitiesTable() {
    $tb_name = "cities";
    // 检查表是否已存在
    $isTableExists = checkTableExists($tb_name);
    if (!$isTableExists) { 
        // 创建表
        $sql = "CREATE TABLE $tb_name (
            id INT AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(255) NOT NULL,
            code INT NOT NULL
        )";
        global $pdo;
        $pdo->exec($sql);
    } else {
         
    }
}

// 检查表是否存在
function checkTableExists($tableName) {
    global $pdo;
    $stmt = $pdo->query("SHOW TABLES LIKE '$tableName'");
    return $stmt->rowCount() > 0;
}

?>

output.php

Output package

<?php

class ErrorCode {
    const FAILURE = -1;
    const SUCCESS = 0;
    const INVALID_INPUT = 100;
    const MISSING_PARAMETER = 101;
    const DATABASE_ERROR = 200;
    const FILE_NOT_FOUND = 201;
    const METHOD_NOT_ALLOW = 405;
    const INTERNAL_SERVER_ERROR = 500;
    const DATA_NOT_FOUND = 1000;

    public static function getErrorMessage($errorCode) {
        switch ($errorCode) {
            case self::FAILURE:
                return "Operation failed.";
            case self::SUCCESS:
                return "Operation succeeded.";
            case self::INVALID_INPUT:
                return "Invalid input provided.";
            case self::MISSING_PARAMETER:
                return "Required parameter is missing.";
            case self::DATABASE_ERROR:
                return "Database error occurred.";
            case self::FILE_NOT_FOUND:
                return "File not found.";
            case self::METHOD_NOT_ALLOW:
                return "Method not allowed.";   
            case self::INTERNAL_SERVER_ERROR:
                return "Internal Server Error.";   
            case self::DATA_NOT_FOUND:
                return "No matching data found.";  
            default:
                return "Unknown error occurred.";
        }
    }
}

function outputJSON(int $errorCode, $data = []) {
    // 构建要返回的数据
    $response = [
        'code' => $errorCode,
        'message' => ErrorCode::getErrorMessage($errorCode),
        'data' => $data
     ];
    
    // 设置响应内容为 JSON 格式
    header('Content-Type: application/json');

    // 将数据转换为 JSON 字符串
    $json = json_encode($response);

    // 输出 JSON 字符串
    echo $json;
}

?>

city.php

Add, delete, modify and query cities

<?php
require "pdoConnect.php";
require "output.php";

$tb_name = "cities";

// 检查POST数据
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    /* 方式一: */
    // 获取数据并验证
    $name = $_POST['name'] ?? '';
    $code = $_POST['code'] ?? '';
    $mark = $_POST['mark'] ?? 0;

    /* 方式二:表单中Content-Type用'application/json'时,用这种方式获取传参 
    // 获取 JSON 数据并解析
    $data = json_decode(file_get_contents('php://input'), true);
    // 获取数据并验证
    $name = $data['name'] ?? '';
    $code = $data['code'] ?? '';
    $mark = $data['mark'] ?? 0;
    */

    if (empty($name) || empty($code) || $mark == 0) {
        outputJSON(ErrorCode::MISSING_PARAMETER);
        return;
    }

    // mark 1:增 2:删 3:改 4:查
    if ($mark == 1) {
        // 插入数据
        $result = changeData("INSERT INTO $tb_name (name, code) VALUES (:name, :code)", ['name' => $name, 'code' => $code]);
        if ($result) {
            outputJSON(errorCode::SUCCESS);
        } else {
            outputJSON(errorCode::FAILURE);
        }
    } else if ($mark == 2) {
        // 删除数据
        $result = changeData("DELETE FROM $tb_name WHERE code = :code", ['code' => $code]);
        if ($result) {
            outputJSON(errorCode::SUCCESS);
        } else {
            outputJSON(errorCode::FAILURE);
        }
    } else if ($mark == 3) {
        // 更新数据
        $result = changeData("UPDATE $tb_name SET name = :name WHERE code = :code", ['name' => $name, 'code' => $code]);
        if ($result) {
            outputJSON(errorCode::SUCCESS);
        } else {
            outputJSON(errorCode::FAILURE);
        }
    } else if ($mark == 4) {
        // 查询数据
        $result = findData("SELECT * FROM $tb_name WHERE code = :code", ['code' => $code]);
        if ($result) {
            // 查询成功,至少有一条匹配的数据
            outputJSON(errorCode::SUCCESS,$result);
        } else {
            // 查询失败,没有匹配的数据
            outputJSON(ErrorCode::DATA_NOT_FOUND);
        }
    }

}

// 改变数据 插入|更新|删除
function changeData(string $sql, array $arr) {
    global $pdo;
    $stmt = $pdo->prepare($sql);
    $result = $stmt->execute($arr);
    return $result;
}

// 查询数据
function findData(string $sql, array $arr) {
    global $pdo;
    $stmt = $pdo->prepare($sql);
    $stmt->execute($arr);
    $result = $stmt->fetch();
    return $result;
}

?>

cityList.php

Query city list by page

<?php
require("pdoConnect.php");
require("output.php");

// 检查POST数据
if ($_SERVER['REQUEST_METHOD'] === 'POST') { 
    try {
        // 获取数据并验证
        $page = isset($_POST['page']) ? intval($_POST['page']) : 1; // 当前页码,默认为第一页
        $pageSize = isset($_POST['pageSize']) ? intval($_POST['pageSize']) : 10; // 每页数据条数,默认为 10

        // 对页码进行有效性检查
        $page = max(1, intval($page)); ;
        // 确保每页记录数为正整数
        $pageSize = max(1, intval($pageSize)); ;

        // 表名
        $tb_name = "cities";

        // 查询总记录数
        $countSql = "SELECT COUNT(*) AS total FROM $tb_name";
        $countStmt = $pdo->prepare($countSql);
        $countStmt->execute();
        $totalItems = $countStmt->fetchColumn();
        // 计算总页数
        $totalPages = ceil($totalItems / $pageSize);

        // 对页码进行有效性检查
        $page = min($page, $totalPages);
        // 计算偏移量
        $offset = ($page - 1) * $pageSize;

        // 查询当前页的数据
        $sql = "SELECT * FROM $tb_name LIMIT :offset, :pageSize";
        $stmt = $pdo->prepare($sql);
        $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
        $stmt->bindValue(':pageSize', $pageSize, PDO::PARAM_INT);
        $stmt->execute();

        $pagedData = $stmt->fetchAll(PDO::FETCH_ASSOC);

        // 构建要返回的数据
        $response = [
            'page' => $page,
            'pageSize' => $pageSize,
            'totalPages' => $totalPages,
            'totalItems' => $totalItems,
            'data' => array_map(function ($item) {
                return $item;
            }, $pagedData)
        ];
        outputJSON(ErrorCode::SUCCESS, $response);
    } catch (Exception $e) {
        // 发生错误时返回错误响应
        outputJSON(ErrorCode::INTERNAL_SERVER_ERROR);
    }
} else {
    // 非 POST 请求返回错误响应
    outputJSON(ErrorCode::METHOD_NOT_ALLOW);
}

?>

5. Test the local development environment

Test your PHP script in a local development environment to make sure it interacts with the MySQL database correctly.

6. Deploy MySQL database to ECS

1).Create an ECS instance

Log in to the Alibaba Cloud Management Console and create an ECS instance.

2).Install MySQL

Connect to your ECS instance via SSH and install MySQL using the appropriate package manager.

3).Export local database

启动MySQL服务:
$ brew services start mysql
登录到MySQL:
$ mysql -u root -p
授予相应的权限:
$ GRANT PROCESS ON *.* TO 'gamin'@'localhost';
刷新权限:
$ FLUSH PRIVILEGES;
退出MySQL:
$ EXIT;

导出数据库:
格式
mysqldump -u [username] -p [database_name] > [filename].sql
示例
mysqldump -u gamin -p city_database > /Users/gamin/Desktop/files/city.sql

4).Import the database to online MySQL

Set user permissions, create a database, and import your local database data to the MySQL instance on ECS. You can also directly select "Management" of the database and enter the management page to import directly.

An error was reported during the import. This error was caused by MySQL not recognizing the character set collation rule utf8mb4_0900_ai_ci. This is usually because the MySQL version is older and does not support that particular character set collation.

Replace utf8mb4_0900_ai_ci with the character set collation supported by MySQL, such as utf8mb4_general_ci or utf8mb4_unicode_ci. Modify the create table statement in the import file and change the character set collation rules to appropriate values.

Import successful

5).Set database access permissions to the specified IP

7. Deploy PHP code to ECS

1).Configure the web server

Install and configure Nginx or Apache on ECS as a web server to handle PHP requests.

2).Update the database connection information in the PHP code

Make it point to MySQL on the ECS instance

<?php
$host = '121.43.232.240';
$port = 3306; // MySQL默认的是3306端口
$db = 'php_test_demo';
$user = 'php_test_demo';
$pass = 'iaTejKANGwWb6yLd';
$charset = 'utf8mb4';

$dsn = "mysql:host=$host;port=$port;dbname=$db;charset=$charset";
$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
];

// 连接数据库
try {
    $pdo = new PDO($dsn, $user, $pass, $options);
    createCitiesTable();
} catch (\PDOException $e) {
    throw new \PDOException($e->getMessage(), (int)$e->getCode());
}

// 创建城市表
function createCitiesTable() {
    $tb_name = "cities";
    // 检查表是否已存在
    $isTableExists = checkTableExists($tb_name);
    if (!$isTableExists) { 
        // 创建表
        $sql = "CREATE TABLE $tb_name (
            id INT AUTO_INCREMENT PRIMARY KEY,
            name VARCHAR(255) NOT NULL,
            code INT NOT NULL
        )";
        global $pdo;
        $pdo->exec($sql);
    } else {
         
    }
}

// 检查表是否存在
function checkTableExists($tableName) {
    global $pdo;
    $stmt = $pdo->query("SHOW TABLES LIKE '$tableName'");
    return $stmt->rowCount() > 0;
}

?>

3).Deploy PHP code to ECS

Here I upload the PHP file directly in the pagoda. Of course, it is not very scientific to upload it directly without version management. You can also use FTP, SCP or Git to transfer files.

4).Go to the ECS security group to release port 3306

8. Test the remote environment

In order to facilitate testing, I also deployed the form page I wrote earlier to the site.

After accessing the page, after testing, we can normally query the data imported from the local to MySQL, and can also normally connect to the online database to perform other operations.

https://www.lnktools.com/page/index.html

Make sure your application passes all necessary security and performance tests before deploying to production. Additionally, ensure that sensitive information (such as database credentials) is encrypted and appropriate security measures are configured on the ECS instance.

Guess you like

Origin blog.csdn.net/u012881779/article/details/134472774