PHP JSON

PHPJSON教程展示了如何在PHP中使用JSON。

$ php -v
php -v
PHP 8.1.2 (cli) (built: Aug  8 2022 07:28:23) (NTS)
...

我们使用PHP版本8.1.2。

JSON

JSON(JavaScript对象表示法)是一种轻量级数据交换格式。它很容易被人类阅读和编写,并被机器解析和生成。application/json是JSON的官方互联网媒体类型。JSON文件扩展名为.json

json_encode函数返回给定值的JSON表示形式。json_decode采用JSON编码的字符串并将其转换为PHP变量。

Symfony和Laravel等PHP框架具有使用JSON的内置方法。

PHPJSON编码

在下面的例子中,我们使用了json_encode函数。

<?php

$data = ["falcon", "sky", "cloud", "orange", "wood", "forest"];

header('Content-type:application/json;charset=utf-8');
echo json_encode($data);

该示例将PHP数组转换为JSON字符串。

$ php -S localhost:8000 encode.php

我们启动服务器并定位到localhost:8000

图:Firefox中的JSON视图

现代网络浏览器在响应标头中收到适当的内容类型时,会显示JSON数据的JSON视图。

PHPJSON解码

在下面的例子中,我们使用了json_decode函数。

<?php

$data = '{
    "name": "John Doe",
    "occupation": "gardener"
}';

$a = json_decode($data, true);

header('Content-type:text/html;charset=utf-8');
echo "{$a["name"]} is a {$a["occupation"]}";

该示例将JSON字符串转换为PHP变量。

$ php -S localhost:8000 decode.php

我们启动服务器。

$ curl localhost:8000
John Doe is a gardener

我们使用curl发送GET请求。

从文件中读取PHPJSON

在下面的示例中,我们从文件中读取JSON数据。

[
    {"name": "John Doe", "occupation": "gardener", "country": "USA"},
    {"name": "Richard Roe", "occupation": "driver", "country": "UK"},
    {"name": "Sibel Schumacher", "occupation": "architect", "country": "Germany"},
    {"name": "Manuella Navarro", "occupation": "teacher", "country": "Spain"},
    {"name": "Thomas Dawn", "occupation": "teacher", "country": "New Zealand"},
    {"name": "Morris Holmes", "occupation": "programmer", "country": "Ireland"}
]

这是JSON数据。

<?php

$filename = 'data.json';

$data = file_get_contents($filename);
$users = json_decode($data);
?>

<html>
<table>
    <tbody>
        <tr>
            <th>Name</th>
            <th>Occupation</th>
            <th>Country</th>
        </tr>
        <?php foreach ($users as $user) { ?>
        <tr>
            <td> <?= $user->name; ?> </td>
            <td> <?= $user->occupation; ?> </td>
            <td> <?= $user->country; ?> </td>
        </tr>
        <?php } ?>
    </tbody>
</table>
</html>

在代码示例中,我们使用file_get_contents读取文件并使用json_decode将其解码为PHP数组。稍后,我们使用PHPforeach循环将数据放入表中。

从数据库读取PHPJSON

在下面的示例中,我们从SQLite数据库中读取数据并以JSON格式返回。

BEGIN TRANSACTION;
DROP TABLE IF EXISTS cities;

CREATE TABLE cities(id INTEGER PRIMARY KEY, name TEXT, population INTEGER);
INSERT INTO cities(name, population) VALUES('Bratislava', 432000);
INSERT INTO cities(name, population) VALUES('Budapest', 1759000);
INSERT INTO cities(name, population) VALUES('Prague', 1280000);
INSERT INTO cities(name, population) VALUES('Warsaw', 1748000);
INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000);
INSERT INTO cities(name, population) VALUES('New York', 8550000);
INSERT INTO cities(name, population) VALUES('Edinburgh', 464000);
INSERT INTO cities(name, population) VALUES('Berlin', 3671000);
COMMIT;

此SQL代码在SQLite中创建一个cities表。

$ sqlite3 test.db
sqlite> .read cities.sql
sqlite> SELECT * FROM cities;
1|Bratislava|432000
2|Budapest|1759000
3|Prague|1280000
4|Warsaw|1748000
5|Los Angeles|3971000
6|New York|8550000
7|Edinburgh|464000
8|Berlin|3671000

使用sqlite3命令行工具,我们生成一个SQLite数据库并创建cities表。

<?php

$db = new SQLite3('test.db');
$res = $db->query('SELECT * FROM cities');
$cities = [];

while ($row = $res->fetchArray()) {
    $cities[] = $row;
}

header('Content-type:application/json;charset=utf-8');
echo json_encode(['cities' => $cities]);

在示例中,我们从数据库中检索数据并将其作为JSON返回。

PHPJSON和JS获取API

在下面的示例中,我们使用JavaScriptfetchAPI从PHP脚本中获取JSON数据。

[
    {"name": "John Doe", "occupation": "gardener", "country": "USA"},
    {"name": "Richard Roe", "occupation": "driver", "country": "UK"},
    {"name": "Sibel Schumacher", "occupation": "architect", "country": "Germany"},
    {"name": "Manuella Navarro", "occupation": "teacher", "country": "Spain"},
    {"name": "Thomas Dawn", "occupation": "teacher", "country": "New Zealand"},
    {"name": "Morris Holmes", "occupation": "programmer", "country": "Ireland"}
]

JSON数据存储在一个文件中。

<?php

$filename = 'data.json';

$data = file_get_contents($filename);
header('Content-type:application/json;charset=utf-8');
echo $data;

我们读取数据并将其返回给客户端。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home page</title>
    <style>
        th,
        td {
            font: 15px 'Segoe UI';
        }

        table,
        th,
        td {
            border: solid 1px #ddd;
            border-collapse: collapse;
            padding: 2px 3px;
            text-align: center;
        }
        tr:nth-child(odd) {background: #efefef}
        th {
            font-weight: bold;
        }
    </style>
</head>

<body>

    <button id="getData">Get data</button>
    <br>
    <br>
    <div id="output"></div>


    <script>

        const getBtn = document.getElementById('getData');
        const output = document.getElementById('output');
        const table = document.getElementById('table');

        getBtn.addEventListener('click', () => {

            fetch('/data.php')
                .then((res) => {
                    return res.json();
                })
                .then((data) => {
                    output.innerHTML = '';
                    let table = createTableAndHeader();
                    
                    output.appendChild(table);
                    appendRows(table, data);
                })
                .catch((err) => {
                    console.log("error fetching data");
                    console.log(err);
                })

        });

        function createTableAndHeader() {

            let table = document.createElement("table");

            let tr = table.insertRow(-1);
            let headers = ["Name", "Occupation", "Country"];

            for (let i = 0; i < 3; i++) {

                let th = document.createElement("th");
                th.innerHTML = headers[i];
                tr.appendChild(th);
            }

            return table;
        }

        function appendRows(table, data) {

            for (let i = 0; i < data.length; i++) {

                let tr = table.insertRow(-1);

                for (const [_, value] of Object.entries(data[i])) {

                    let cell = tr.insertCell(-1);
                    cell.innerHTML = value;
                }
            }
        }
    </script>
</body>

</html>

我们在文档中有一个按钮。当我们点击按钮时,fetch函数从data.php脚本中检索JSON数据。动态构建HTML表格并填充数据。

图:HTMLtablefilledwithJSONdatafromfetchAPI

Slim中的PHPJSON

在下面的示例中,我们从Slim应用程序返回JSON数据。

$ composer req slim/slim
$ composer req slim/psr7
$ composer req slim/http

我们安装了slim/slimslim/psr7slim/http包。

<?php

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__ . '/../vendor/autoload.php';

$app = AppFactory::create();

$app->get('/city', function (Request $request, Response $response): Response {

    $cities = [
        ["id" => 1, "name" => "Bratislava", "population" => 432000],
        ["id" => 2, "name" => "Budapest", "population" => 1759000],
        ["id" => 3, "name" => "Prague", "population" => 1280000],
        ["id" => 4, "name" => "Warsaw", "population" => 1748000],
        ["id" => 5, "name" => "Los Angeles", "population" => 3971000],
        ["id" => 6, "name" => "New York", "population" => 8550000],
        ["id" => 7, "name" => "Edinburgh", "population" => 464000],
        ["id" => 8, "name" => "Berlin", "population" => 3671000],
    ];

    return $response->withJson(["cities" => $cities]);
});

$app->run();

我们使用ResponsewithJson方法返回JSON数据。

Symfony中的PHPJSON

在下面的示例中,我们从Symfony应用程序发送一个JSON响应。

$ symfony new symjson
$ cd symjson

创建了一个新的应用程序。

$ composer req annot
$ composer req symfony/orm-pack
$ composer req symfony/console

我们安装了annotsymfony/orm-packsymfony/console组件。

...
DATABASE_URL=sqlite:///%kernel.project_dir%/var/ydb.db
...

我们为SQLite数据库设置了一个数据库URL。

$ php bin/console doctrine:database:create

我们创建数据库。

<?php

namespace App\Command;

use Doctrine\DBAL\Driver\Connection;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;


class CreateCityTable extends Command
{
    private $conn;

    public function __construct(Connection $conn)
    {
        $this->conn = $conn;

        parent::__construct();
    }

    protected function configure()
    {
        $this->setName('app:create-table')
            ->setDescription('Creates City table')
            ->setHelp('This command creates a City table');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $q1 = "CREATE TABLE cities(id INTEGER PRIMARY KEY, name TEXT, population INTEGER)";
        $this->conn->executeQuery($q1);

        $q2 = "INSERT INTO cities(name, population) VALUES('Bratislava', 432000)";
        $this->conn->executeQuery($q2);

        $q3 = "INSERT INTO cities(name, population) VALUES('Budapest', 1759000)";
        $this->conn->executeQuery($q3);

        $q4 = "INSERT INTO cities(name, population) VALUES('Prague', 1280000)";
        $this->conn->executeQuery($q4);

        $q5 = "INSERT INTO cities(name, population) VALUES('Warsaw', 1748000)";
        $this->conn->executeQuery($q5);

        $q6 = "INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000)";
        $this->conn->executeQuery($q6);

        $q7 = "INSERT INTO cities(name, population) VALUES('New York', 8550000)";
        $this->conn->executeQuery($q7);

        $q8 = "INSERT INTO cities(name, population) VALUES('Edinburgh', 464000)";
        $this->conn->executeQuery($q8);

        $q9 = "INSERT INTO cities(name, population) VALUES('Berlin', 3671000)";
        $this->conn->executeQuery($q9);

        $output->writeln('table successfully created');

        return Command::SUCCESS;
    }
}

这是在数据库中创建cities表的命令。

$ php bin/console app:create-table

命令被执行。

<?php

namespace App\Repository;

use Doctrine\DBAL\Driver\Connection;

class CityRepository
{
    protected $conn;

    public function __construct(Connection $conn)
    {
        $this->conn = $conn;
    }

    public function all(): array
    {
        $queryBuilder = $this->conn->createQueryBuilder();
        $queryBuilder->select('*')->from('cities');
        $stm = $queryBuilder->execute();

        return $stm->fetchAll();
    }
}

CityRepository中,我们有all方法来检索所有行。我们使用DoctrineDBAL来执行数据库查询。

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;
use App\Repository\CityRepository;

class CityController extends AbstractController
{
    /**
     * @Route("/city", name="city")
     * @param CityRepository $cityRepository
     * @return JsonResponse
     */
    public function index(CityRepository $cityRepository): JsonResponse
    {
        $cities = $cityRepository->all();

        return $this->json([
            'cities' => $cities
        ]);
    }
}

在控制器内部,我们使用CityRepository获取所有数据。使用json助手将数据转换为JSON。

$ symfony serve

我们启动Web服务器并定位到localhost:8000/city

Laravel中的PHPJSON

在下面的示例中,我们从Laravel应用程序发送JSON响应。

$ laravel new larajson
$ cd larajson

我们创建一个新的Laravel应用程序。

...
DB_CONNECTION=sqlite
DB_DATABASE=/tmp/ydb.db
...

我们定义连接和数据库文件。

$ touch /tmp/ydb.db

我们创建数据库文件。

$ php artisan make:migration create_cities_table
Created Migration: 2020_07_25_101535_create_cities_table

cities表的新迁移已创建。

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCitiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('cities', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->integer('population');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('cities');
    }
}

在迁移文件中,我们为cities表创建了一个模式。

$ php artisan migrate

我们运行迁移。

$ php artisan make:seeder CitySeeder

我们为我们的数据库创建了一个数据播种器。

<?php

use Illuminate\Database\Seeder;

class CitySeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('cities')->insert([
            ['name' => 'Bratislava', 'population' => 432000],
            ["name" => "Budapest", "population" => 1759000],
            ["name" => "Prague", "population" => 1280000],
            ["name" => "Warsaw", "population" => 1748000],
            ["name" => "Los Angeles", "population" => 3971000],
            ["name" => "New York", "population" => 8550000],
            ["name" => "Edinburgh", "population" => 464000],
            ["name" => "Berlin", "population" => 3671000]
        ]);
    }
}

播种器向表中插入八行。

$ php artisan db:seed --class=CitySeeder

我们执行播种机。

<?php

use Illuminate\Support\Facades\Route;
use Illuminate\Http\JsonResponse;

Route::get('/city', function (): JsonResponse {

    $cities = DB::table('cities')->get();

    return response()->json([
        'cities' => $cities
    ]);
});

在路由中,我们从数据库中选择所有数据,并使用json助手将其作为JSON返回。

$ php artisan serve

我们运行网络服务器。

$ curl localhost:8000/city
{"cities":[{"id":"1","name":"Bratislava","population":"432000"},
{"id":"2","name":"Budapest","population":"1759000"},
{"id":"3","name":"Prague","population":"1280000"},
{"id":"4","name":"Warsaw","population":"1748000"},
{"id":"5","name":"Los Angeles","population":"3971000"},
{"id":"6","name":"New York","population":"8550000"},
{"id":"7","name":"Edinburgh","population":"464000"},
{"id":"8","name":"Berlin","population":"3671000"}]}

我们使用curl工具获取数据。

来自客户端的PHPJSON

Symfony提供了HttpClient组件,它使我们能够在PHP中创建HTTP请求。我们还可以发送JSON数据。

$ composer req symfony/http-client

我们安装了symfony/http-client组件。

<?php

require('vendor/autoload.php');

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'http://localhost:8000/greet',  [
    'json' => [
        'name' => 'Lucia',
        'message' => 'Cau'
    ]
]);

$content = $response->getContent();
echo $content . "\n";

该示例发送带有JSON负载的GET请求。

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

class GreetController extends AbstractController
{
    /**
     * @Route("/greet", name="greet")
     */
    public function index(Request $request): Response
    {
        $params = [];
        if ($data = $request->getContent()) {
            $params = json_decode($data, true);
        }

        $msg = "{$params['name']} says {$params['message']}";

        $textResponse = new Response($msg , 200);
        $textResponse->headers->set('Content-Type', 'text/plain');

        return $textResponse;
    }
}

GreetController中,我们处理JSON数据并生成一条文本消息,返回给客户端。

$ php send_json_req.php 
Lucia says Cau

这是输出。

在本教程中,我们在纯PHP、Symfony、Slim和Laravel中处理了JSON数据。

列出所有PHP教程。

赞(0) 打赏

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏