ZetCode Symfony 教程(一)

原文:ZetCode

协议:CC BY-NC-SA 4.0

Symfony DBAL 教程

原文: http://zetcode.com/symfony/dbal/

Symfony DBAL 教程显示了如何使用 Doctrine DBAL 组件在 Symfony 应用中使用数据库。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Fabien Potencier 是 Symfony 的原始作者。 Symfony 的灵感来自 Ruby on Rails,Django 和 Spring 框架。

Symfony DBAL 组件

教义数据库抽象层(DBAL)是位于 PDO 之上的抽象层,并提供了一种直观且灵活的 API,可以与最受欢迎的关系数据库进行通信。 DBAL 库使执行查询和执行其他数据库操作变得容易。

Symfony DBAL 示例

在下面的示例中,我们创建一个简单的 Symfony 应用,该应用使用 DBAL 读取数据。 我们使用 MySQL 数据库。

$ composer create-project symfony/skeleton symdbal

使用composer,我们创建一个新的 Symfony 骨架项目。

$ cd symdbal

我们转到项目目录。

$ composer require symfony/orm-pack

我们安装symfony/orm-pack,其中包含 DBAL API。

$ composer require maker --dev

另外,我们安装了maker组件。 maker包提供了脚手架。

$ composer require server --dev

我们安装开发 Web 服务器。

countries_mysql.sql

CREATE TABLE countries(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT, 
    name VARCHAR(100), population INT);

INSERT INTO countries(name, population) VALUES('China', 1382050000);
INSERT INTO countries(name, population) VALUES('India', 1313210000);
INSERT INTO countries(name, population) VALUES('USA', 324666000);
INSERT INTO countries(name, population) VALUES('Indonesia', 260581000);
INSERT INTO countries(name, population) VALUES('Brazil', 207221000);
INSERT INTO countries(name, population) VALUES('Pakistan', 196626000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Bangladesh', 162099000);
INSERT INTO countries(name, population) VALUES('Nigeria', 186988000);
INSERT INTO countries(name, population) VALUES('Russia', 146838000);
INSERT INTO countries(name, population) VALUES('Japan', 126830000);
INSERT INTO countries(name, population) VALUES('Mexico', 122273000);
INSERT INTO countries(name, population) VALUES('Philippines', 103738000);

这是一些测试数据。 它在 MySQL 中创建一个小表。 我们可以使用source命令执行文件。

.env

...
DATABASE_URL=mysql://user12:s$cret@localhost:3306/mydb

.env文件中,我们配置数据库 URL。

$ php bin/console make:controller HomeController

HomeController由 Symfony 制造商创建。

src/Controller/HomeController.php

<?php

namespace App\Controller;

use Doctrine\DBAL\Connection;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class HomeController extends AbstractController
{
    /**
     * @Route("/home", name="home")
     */
    public function index(Connection $conn)
    {
        $queryBuilder = $conn->createQueryBuilder();
        $data = $queryBuilder->select('*')->from('countries')->execute()->fetchAll();

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

该控制器方法执行一个查询,该查询从countries表中获取所有行,并将其作为 JSON 数据返回。 请注意,出于简单原因,我们已将查询生成器放入控制器中。 在生产应用中,还应该有一个服务层和一个存储库。

public function index(Connection $conn)
{

DBAL Connection对象被注入到方法变量中。

$queryBuilder = $conn->createQueryBuilder();

我们从连接创建一个QueryBuilder

$data = $queryBuilder->select('*')->from('countries')->execute()->fetchAll();

我们执行查询并获取所有行。

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

数据以 JSON 格式返回。

$ php bin/console server:run

Web 服务器已启动。

$ curl localhost:8000/home
{"data":[{"id":"1","name":"China","population":"1382050000"},
{"id":"2","name":"India","population":"1313210000"},
{"id":"3","name":"USA","population":"324666000"},
{"id":"4","name":"Indonesia","population":"260581000"},
{"id":"5","name":"Brazil","population":"207221000"},
{"id":"6","name":"Pakistan","population":"196626000"},
{"id":"7","name":"Nigeria","population":"186988000"},
{"id":"8","name":"Bangladesh","population":"162099000"},
{"id":"9","name":"Nigeria","population":"186988000"},
{"id":"10","name":"Russia","population":"146838000"},
{"id":"11","name":"Japan","population":"126830000"},
{"id":"12","name":"Mexico","population":"122273000"},
{"id":"13","name":"Philippines","population":"103738000"}]}

我们使用curl工具执行 GET 请求。

在本教程中,我们在 Symfony 中使用了 Doctrine DBAL。

您可能也对以下相关教程感兴趣: Symfony 简介Doctrine DBAL QueryBuilder教程Symfony 表单教程Symfony 翻译教程PHP 教程

{% raw %}

Symfony 表单教程

原文: http://zetcode.com/symfony/form/

Symfony 表单教程展示了如何在 Symfony 中创建和处理表单。 在本教程中,我们不使用 Symfony 表单构建器。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 Symfony 受到 Spring 框架的极大启发。

HTML 表单

HTML 表单用于用户与网站或应用之间的交互。 它们允许用户将数据发送到网站。 HTML 表单由一个或多个小部件组成。 这些小部件可以是文本字段,选择框,按钮,复选框或单选按钮。 这些小部件通常与描述其用途的标签配对。

Symfony 表单示例

在下面的示例中,我们创建一个 HTML 表单。 表单中的数据由 Symfony 控制器处理。

$ composer create-project symfony/skeleton myform

使用composer,我们创建一个新的 Symfony 骨架项目。

$ cd myform

我们转到项目目录。

$ composer req annotations twig

我们安装了两个模块:annotationstwig

$ composer require server maker --dev

我们安装开发 Web 服务器和制造商。

$ php bin/console make:controller HomeController

我们创建一个HomeController

src/Controller/HomeController.php

<?php

namespace App\Controller;

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

class HomeController extends AbstractController
{
    /**
     * @Route("/", name="home")
     */
    public function index()
    {
        return $this->render('home/index.html.twig');
    }
}

HomeController返回包含 HTML 表单的主页。

templates/home/index.html.twig

{% extends 'base.html.twig' %}

{% block title %}Home page{% endblock %}

{% block body %}

<section class="ui container">

    <form class="ui form" action="message" method="get">

        <div class="field">
            <label>Name:</label>
            <input type="text" name="name">
        </div>

        <div class="field">
            <label>Message</label>
            <input type="text" name="message">
        </div>

        <button class="ui button" type="submit">Send</button>

    </form>

</section>

{% endblock %}

HomeController返回包含 HTML 表单的主页。 该表格包含两个输入字段。 这些字段的内容将通过两个请求属性传递到请求对象中。

{% extends 'base.html.twig' %}

该模板继承自base.html.twig文件,该文件具有要共享的基本标记。 例如,我们包括语义 UI CSS 框架的文件。

templates/base.html.twig

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        <link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.css"
            rel="stylesheet">
    </head>

    <body>
        {% block body %}{% endblock %}
    </body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.js"></script>
</html>

base.html.twig模板包含其他模板文件共享的代码。 它定义了将在子模板中替换的块。

$ php bin/console make:controller MessageController

创建了MessageController

src/Controller/MessageController.php

<?php

namespace App\Controller;

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

class MessageController extends AbstractController
{
    /**
     * @Route("/message", name="message", methods="GET")
     */
    public function index(Request $request)
    {
        $name = $request->query->get("name");
        $message = $request->query->get("message");

        return $this->render('message/index.html.twig', ["name" => $name,
            "message" => $message]);
    }
}

MessageController处理表格。

/**
 * @Route("/message", name="message", methods="POST")
 */

@Route注解将message路径映射到index()方法。 methods参数定义请求类型。

public function index(Request $request)

我们将Request对象注入该方法。

$name = $request->query->get("name");
$message = $request->query->get("message");

从请求对象中,我们获得两个请求参数。

return $this->render('message/index.html.twig', ["name" => $name,
    "message" => $message]);

我们渲染message/index.html.twig模板。 我们将两个变量传递给模板。

templates/message/index.html.twig

{% extends 'base.html.twig' %}

{% block title %}Show message{% endblock %}

{% block body %}

{{name}} says: {{message}}

{% endblock %}

最后,我们有向用户显示消息的模板文件。 变量以{{}}语法显示。

$ php bin/console server:run

我们运行该应用并导航到localhost:8000

在本教程中,我们在 Symfony 应用中创建并处理了一个简单的 HTML 表单。

您可能也对以下相关教程感兴趣: Symfony 保留表单值教程Symfony 简介Symfony 请求教程Symfony 验证教程Twig 教程Symfony DBAL 教程PHP 教程

列出所有 Symfony 教程

{% endraw %}

{% raw %}

Symfony CSRF 教程

原文: http://zetcode.com/symfony/csrf/

Symfony CSRF 教程展示了如何在 Symfony 应用中实现 CSRF 保护。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 Symfony 的灵感来自 Djanog,Spring 和 ROR 框架。

CSRF

跨站点请求伪造(CSRF)是一种攻击,其中恶意用户试图使合法用户在不知情的情况下提交他们不打算提交的数据。 CSRF 攻击专门针对状态更改请求,而不是数据盗窃。 成功的 CSRF 攻击可以迫使用户执行状态更改请求,例如转移资金或更改其个人数据详细信息。

CSRF 保护的工作原理是在表单中添加一个隐藏字段,该字段包含仅应用和用户知道的值(令牌)。 这样可以确保用户(而非其他实体)正在提交给定的数据。

symfony/security-csrf组件提供CsrfTokenManager用于生成和验证 CSRF 令牌。 默认情况下,使用 Symfony 表单组件创建的表单包括 CSRF 令牌,Symfony 会自动检查它们,因此我们无需采取任何措施来防止 CSRF 攻击。 csrf_token() Twig 函数为用户呈现 CSRF 令牌。

Symfony CSRF 保护示例

在下面的示例中,我们手动创建一个表单,为其实现 CSRF 保护。 在此应用中,我们在routes.yaml文件中定义路由。

$ composer create-project symfony/skeleton csrf-app
$ cd csrf-app

使用composer,我们创建一个新的 Symfony 框架项目并定位到项目目录。

$ composer require symfony/security-csrf

我们安装security-csrf包。

$ composer require server --dev

我们安装开发 Web 服务器。

config/routes.yaml

index:
    path: /
    controller: App\Controller\AppController::index

process-form:
    path: /process
    controller: App\Controller\AppController::processForm

我们为应用定义了两个路由。 index路由显示带有表单的主页。 process-form处理提交的表单并检查 CSRF 令牌。

src/Controller/AppController.php

<?php

namespace App\Controller;

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

class AppController extends AbstractController
{
    public function index()
    {
        return $this->render('home/index.html.twig');
    }

    public function processForm(Request $request)
    {
        $token = $request->request->get("token");

        if (!$this->isCsrfTokenValid('myform', $token))
        {
            return new Response('Operation not allowed', Response::HTTP_BAD_REQUEST,
                ['content-type' => 'text/plain']);
        }

        $name = $request->request->get("name");
        $email = $request->request->get("email");

        $msg = "$name with $email saved";

        return new Response($msg, Response::HTTP_CREATED, ['content-type' => 'text/plain']);
    }
}

AppController具有两个动作:index()processForm()

public function index()
{
    return $this->render('home/index.html.twig');
}

index()函数呈现主页。 主页包含 HTML 表单。

$token = $request->request->get("token");

我们从请求中使用get()方法检索 CSRF 令牌。

if (!$this->isCsrfTokenValid('myform', $token))
{
    return new Response('Operation not allowed', Response::HTTP_BAD_REQUEST,
        ['content-type' => 'text/plain']);
}

我们使用isCsrfTokenValid()方法检查令牌的有效性。 如果令牌无效,我们将返回带有Response::HTTP_BAD_REQUEST代码的响应。 令牌myform的名称在模板的 HTML 表单中指定。

templates/home/index.html.twig

{% extends 'base.html.twig' %}

{% block title %}Home page{% endblock %}

{% block body %}

    <section class="ui container">

        <form class="ui form" action="{{ path('process-form') }}" method="post">

            <input type="hidden" name="token" value="{{ csrf_token('myform') }}" />

            <div class="field">
                <label>Name:</label>
                <input name="name" type="text">
            </div>

            <div class="field">
                <label>Email</label>
                <input name="email" type="text">
            </div>

            <button class="ui button" type="submit">Send</button>

        </form>

    </section>

{% endblock %}

这是带有表单的主页的 Twig 模板。 表单使用语义 UI 库进行样式设置。

<form class="ui form" action="{{ path('process-form') }}" method="post">

表单动作指向process-form路径。 表单的方法是 POST,这意味着必须进行 CSRF 保护。

<input type="hidden" name="token" value="{{ csrf_token('myform') }}" />

我们使用 CSRF 令牌添加隐藏的输入。 令牌是使用csrf_token()生成的。

templates/base.html.twig

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %}Welcome!
        {% endblock %}
    </title>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" 
        rel="stylesheet">
</head>

<body>
    {% block body %}{% endblock %}
</body>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.js"></script>
</html>

这是基本模板文件。 它加载语义 UI 库。

$ php bin/console server:run

我们运行该应用。

$ curl -d "name=Peter&email=peter@example.com" -X POST http://localhost:8000/process
Operation not allowed

如果我们尝试绕过表单并尝试使用curl工具访问控制器操作,则会收到错误消息。

在本教程中,我们在 Symfony 应用中实现了 CSRF 保护。

您可能也对以下相关教程感兴趣: Symfony 验证教程Symfony 表单教程PHP 教程或列出所有 Symfony 教程

{% endraw %}

{% raw %}

Symfony Vue 教程

原文: http://zetcode.com/symfony/vue/

Symfony Vue 教程展示了如何使用 Vue 前端创建一个简单的 Symfony 应用。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Fabien Potencier 是 Symfony 的原始作者。 Symfony 的灵感来自 Ruby on Rails,Django 和 Spring 框架。

Symfony Encore 是 JavaScript 库,用于在 Symfony 应用中管理 CSS 和 JavaScript。 Encore 使将 Webpack 集成到 Symfony 应用中变得更加容易。 它包装了 Webpack,并提供了一个干净而强大的 API,用于捆绑 JavaScript 模块,预处理 CSS 和 JavaScript 以及编译和缩小项目。

Vue

Vue 是用于构建用户界面和单页应用的开源 JavaScript 框架。 它是 Angular 和 React 的替代方案。

Symfony Vue 示例

在下面的示例中,我们创建了一个简单的 Symfony 应用,该应用在模板中发送数据。 数据由 Vue 处理并显示在组件中。

除了 PHP,我们还需要安装 Node.js。 看看 ZetCode 的 Node.js 教程了解更多详细信息。

设置项目

我们展示了如何使用 Vue 设置 Symfony。

$ composer create-project symfony/skeleton symvue

使用composer,我们创建一个新的 Symfony 骨架项目。

$ cd symvue

我们转到项目目录。

$ composer require maker --dev

另外,我们安装了 maker 组件。 maker包提供了脚手架。

$ composer require server --dev

我们安装开发 Web 服务器。

$ composer require encore 
$ npm install

我们安装了 Symfony Encore。 这将安装并启用 WebpackEncoreBundle,添加assets目录,创建webpack.config.js文件,并将node_modules添加到.gitignore

$ npm i vue vue-loader vue-template-compiler

我们安装 Vue 及其库。

项目文件

我们显示了重要的项目文件。

webpack.config.js

var Encore = require('@symfony/webpack-encore');

Encore
    .setOutputPath('public/build/')
    .setPublicPath('/build')

    .enableVueLoader()

    .addEntry('app', './assets/js/app.js')

    .splitEntryChunks()

    .enableSingleRuntimeChunk()

    .cleanupOutputBeforeBuild()
    .enableBuildNotifications()
    .enableSourceMaps(!Encore.isProduction())
    .enableVersioning(Encore.isProduction())

;

module.exports = Encore.getWebpackConfig();

webpack.config.js文件中,我们启用 Vue 加载程序并设置公共路径和构建路径。

assets/js/app.js

import Vue from 'vue';
import App from './components/App';

new Vue({
    el: '#app',
    render: h => h(App)
});

这是启动 Vue 的主要 Vue 文件。

Symfony 将静态文件(如 CSS 和 JavaScript)存储在assets目录中。

assets/js/components/App.vue

<template>
  <div>
    <h2 class="center">My Application</h2>
    <div v-text="message"></div>
    {{ message }}
    <ul>
      <li :key="word.id" v-for="word in words">{{ word }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "A list of words",
      words: []
    };
  },
  mounted() {

    let el = document.querySelector("div[data-words]");
    let mywords = el.dataset.words.split(",");

    this.words.push.apply(this.words, mywords);
  }
};
</script>

<style>
.center {
  text-align: center;
}
</style>

这是 Vue 组件。 Vue 应用由组件组成。 一个组件由三部分组成:模板,脚本和样式。

<div v-text="message"></div>
{{ message }}

在 Vue 中有两种输出变量的方法: 第二个与 Twig 相同。

<ul>
    <li :key="word.id" v-for="word in words">{{ word }}</li>
</ul>

使用v-for指令,我们遍历words数组并显示列表项中的每个元素。 :key指令可帮助 Vue 渲染列表。 它包含元素的 ID。

数据来自 Symfony Twig 模板; 它由 JavaScript 处理,最后在 Vue 组件中与v-for输出。

data() {
    return {
        message: "A list of words",
        words: []
    };
},

data()函数中,我们启动一个消息变量和words数组。

mounted() {

    let el = document.querySelector("div[data-words]");
    let mywords = el.dataset.words.split(",");

    this.words.push.apply(this.words, mywords);
}

words数组在mounted()函数中填充了数据,该函数解析元素数据集中的数据。 它以字符串形式存储在此; 我们将字符串分成单词。 数据将插入 Symfony 的 Twig 模板内的数据集中。

assets/css/style.css

body {
    background-color: lightgray;
}

style.css中有一些基本的 CSS。

$ php bin/console make:controller HomeController

HomeController由 Symfony 制造商创建。

src/Controller/HomeController.php

<?php

namespace App\Controller;

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

class HomeController extends AbstractController
{
    /**
     * @Route("/home", name="home")
     */
    public function index()
    {
        $words = ['sky', 'cloud', 'wood', 'rock', 'forest', 
            'mountain', 'breeze'];

        return $this->render('home/index.html.twig', [
            'words' => $words
        ]);
    }
}

控制器方法将单词列表发送给客户端。

return $this->render('home/index.html.twig', [
    'words' => $words
]);

我们渲染向其发送单词的index.html.twig模板。

templates/home/index.html.twig

{% extends 'base.html.twig' %}

{% block title %}Home page{% endblock %}

{% block body %}

<div ref="words" data-words="{{ words|join(',') }}">

</div>

<div id="app">
    <app></app>
</div>
{% endblock %}

在模板中,我们将单词数组添加到data-words属性。 使用 Twig join过滤器将数组连接成字符串。 HTMLElement接口上的dataset属性提供对在元素上设置的所有自定义数据属性(data-*)的读/写访问。

<div id="app">
    <app></app>
</div>

这是主要 Vue 组件的入口点。

templates/base.html.twig

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        {% block stylesheets %}
            {{ encore_entry_link_tags('app') }}
        {% endblock %}
    </head>
    <body>

        {% block body %}{% endblock %}

        {% block javascripts %}
            {{ encore_entry_script_tags('app') }}
        {% endblock %}
    </body>
</html>

这是基本模板文件。

{{ encore_entry_link_tags('app') }}

CSS 文件加载有encore_entry_link_tags

{{ encore_entry_script_tags('app') }}

JavaScript 文件加载有encore_entry_script_tags

构建项目

我们需要构建项目。

$ npm run dev

使用npm run dev命令为开发环境构建项目。

运行应用

我们启动开发服务器并找到应用页面。

$ php bin/console server:run

我们启动开发服务器。 然后我们找到localhost:8000/home页面。

在本教程中,我们创建了一个在前端使用 Vue 的 Symfony 应用。

您可能也对以下相关教程感兴趣: Symfony 简介Doctrine DBAL QueryBuilder教程Symfony 表单教程Symfony 翻译教程PHP 教程

{% endraw %}

{% raw %}

Symfony 简介

原文: http://zetcode.com/symfony/intro/

这是 Symfony 的入门教程。 它展示了 Symfony PHP 框架,并展示了如何创建简单的示例。 本教程介绍了 Symfony 版本 4。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 Symfony 受到 Spring 框架的极大启发。

Symfony 使用了几个 PHP 开源项目,例如 Doctrine 对象关系映射库,PDO 数据库抽象层,PHPUnit 测试框架,Twig 模板引擎和 Swift Mailer 电子邮件库。

Symfony 创建了自己的组件,包括 Symfony 依赖注入器和 Symfony YAML 解析器。

设置 Symfony 项目

为了创建一个 Symfony 4 项目,我们需要 PHP 7(以及相关的库,例如 php-xml 或 php-mcrypt)和composer。 项目相关性将写入composer.json文件。

$ composer create-project symfony/skeleton symfirst

使用composer,我们创建了一个名为first的新 Symfony 骨架项目。 Symfony 框架等效于微型框架,在微型框架中,我们需要自己安装所有模块。 我们决定要安装什么模块。 这对学习有好处。

$ cd symfirst

不要忘记去项目目录。

Symfony 项目结构

作曲家创建了一个 Symfony 应用结构。

$ ls -p
bin/           composer.lock  public/  symfony.lock  vendor/
composer.json  config/        src/     var/

bin目录包含console工具,该工具是用于执行各种类型命令的命令行工具。 public目录包含 Web 文件。 在 Symfony 骨架应用中,它包含一个文件:index.php,它是一个 Symfony 前端控制器。

第三方依存关系存储在vendor目录中。 config目录包含配置文件。 源代码写在src目录中。 var目录包含临时文件,例如缓存数据。

composer.json中定义了 Composer 依赖项。 composer.lock记录已安装的确切版本,以便以后可以重新安装。 它可以确保每个在项目上工作的人都具有相同的确切版本的库。 symfony.lock文件是 Symfony 配方的正确锁定文件。

还有两个特定的隐藏文件:.env.env.dist.env的内容成为环境变量。 环境变量由各种工具(例如 ORM 库)使用。 .env可能包含敏感或计算机特定的数据; 因此,不应将其提交到存储库。 相反,.env.dist带有一些伪值。

安装 Symfony 项目依赖项

接下来,我们将安装一些项目依赖项。

$ composer require server maker --dev

我们安装了开发服务器和 maker 组件,该组件用于生成命令,控制器,表单类或事件订阅者。

$ composer require annotations twig

我们将安装两个附加的 Symfony 模块。 annotations提供了一种使用注解配置控制器的方法。 twig允许在 Symfony 应用中使用 Twig 模板引擎。

Symfony 创建控制器

Symfony 控制器是一个 PHP 函数,它从Request对象读取信息,并创建并返回Response对象。 响应可能是 HTML 页面,JSON,XML,文件下载,重定向,404 错误等等。

$ php bin/console make:controller HelloController

使用console工具,创建HelloController。 在src/Controller/目录中创建控制器。

src/Controller/HelloController.php

<?php

namespace App\Controller;

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

class HelloController extends AbstractController
{
    /**
     * @Route("/plain", name="plain")
     */
    public function helloPlain(): Response
    {
        return new Response("Hello there", Response::HTTP_OK,
            ['content-type' => 'text/plain']);
    }
}

这是HelloController。 它位于src/Controller/HelloController.php文件中。

/**
 * @Route("/plain", name="plain")
 */
public function helloPlain()
{

路由是从 URL 路径到控制器方法的映射。 @Route注解将/plain URL 路径映射到helloPlain()函数。

return new Response("Hello there",  Response::HTTP_OK,
  ['content-type' => 'text/plain']);

该函数返回一个Response对象。 Response对象保存需要从给定请求发送回客户端的所有信息。 构造器最多包含三个参数:响应内容,状态代码和 HTTP 标头数组。 默认状态码为Response::HTTP_OK,内容类型为text/html

$ php bin/console server:run

使用bin/console server:run命令启动 Web 服务器。 要停止服务器,我们使用bin/console server:stop命令。

$ curl localhost:8000/plain
Hello there

我们向普通路由发出 GET 请求,并查看文本响应。

Symfony 与 Twig 模板

当我们使用composer require twig命令时,将 Twig 模板引擎安装到项目目录中。 还创建了一个templates目录。 在该目录中,我们放置模板文件。 模板文件具有html.twig扩展名。

src/Controller/HelloController.php

<?php

namespace App\Controller;

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

class HelloController extends AbstractController
{
    /**
     * @Route("/plain", name="plain")
     */
    public function helloPlain(): Response
    {
        return new Response("Hello there", Response::HTTP_OK,
            ['content-type' => 'text/plain']);
    }

    /**
     * @Route("/twig", name="twig")
     */
    public function helloTwig(): Response
    {
        $message = "Hello from Twig";
        return $this->render('hello/index.html.twig', ["message" => $message]);
    }
}

我们已经更新了HelloController.php文件; 我们添加了一条新路由。 这次,该函数呈现了一个 Twig 模板。

/**
 * @Route("/twig", name="twig")
 */
public function helloTwig(): Response
{

helloTwig()函数映射到twig路径。

$message = "Hello from Twig";
return $this->render('hello/index.html.twig', ["message" => $message]);

Twig 渲染位于templates目录中的'hello/index.html.twig文件。 render()方法也接受数据; 在我们的例子中,它是一个消息变量。 模板引擎将数据与 HTML 结构合并。

templates/hello/index.html.twig

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello</title>
  </head>
  <body>
    {{ message }}
  </body>
</html>

这是 Twig 模板文件。

{{ message }}

{{ }}是一种特殊的 Twig 语法,它显示变量的内容。

$ curl localhost:8000/twig
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Hello</title>
  </head>
  <body>
    Hello from Twig
  </body>
</html>

当我们连接到树枝路径时,我们将获得此 HTML 输出。

在本教程中,我们介绍了 Symfony 框架。

您可能也对以下相关教程感兴趣: Symfony 表单教程Symfony 请求教程Twig 教程PHP 教程

列出所有 Symfony 教程

{% endraw %}

{% raw %}

Symfony 请求教程

原文: http://zetcode.com/symfony/request/

Symfony 请求教程展示了如何在 Symfony 中使用请求对象。 我们展示了几种在 Symfony 中创建请求对象的方法。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 该框架的开发由 Frech 公司 Sensio Labs 赞助。

Symfony HttpFoundation组件

Symfony HttpFoundation组件为 HTTP 规范定义了一个面向对象的层。 该组件以面向对象的方式表示请求/响应过程。 在最低级别上,我们具有 PHP 全局变量,例如$_GET$_POST$_FILES。 这些由Request对象表示。 响应由Response对象表示。

Symfony 请求示例

在下面的示例中,我们使用链接创建三个不同的请求。

$ composer create-project symfony/skeleton symreq

使用composer,我们创建一个新的 Symfony 骨架项目。

$ cd symreq

我们转到项目目录。

$ composer req annotations twig

我们安装模块annotationstwig

$ composer req maker server --dev

我们安装制造商组件和开发 Web 服务器。

$ php bin/console make:controller HomeController

创建了HomeController

src/Controller/HomeController.php

<?php

namespace App\Controller;

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

class HomeController extends AbstractController
{
    /**
     * @Route("/", name="home")
     */
    public function index()
    {
        return $this->render('home/index.html.twig');
    }
}

HomeController返回一个包含锚标记的主页。

templates/home/index.html.twig

{% extends 'base.html.twig' %}

{% block title %}Home page{% endblock %}

{% block body %}

<ul>
<li><a href="/myapp?colour=yellow&day=Saturday">First request</a></li>
<li><a href="/myapp2?colour=green&day=Sunday">Second request</a></li>

<li><a href="/myapp3?colour=red&day=Monday">Third request</a></li>
</ul>

{% endblock %}

HomeController返回一个包含三个链接的主页。 每个链接都有两个查询参数。 它们指向不同的控制器方法。

{% extends 'base.html.twig' %}

该模板继承自base.html.twig文件,该文件具有要共享的基本标记。

templates/base.html.twig

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        {% block stylesheets %}{% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>

base.html.twig模板包含其他模板文件共享的代码。 它定义了将在子模板中替换的块。

$ php bin/console make:controller MyappController

创建了MyappController

src/Controller/MyappController.php

<?php

namespace App\Controller;

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

class MyappController extends AbstractController
{
   /**
     * @Route("/myapp", name="myapp")
     */
    public function process()
    {
        $request = Request::createFromGlobals();
        $col = $request->query->get("colour");
        $day = $request->query->get("day");

        $content = "Colour: $col, day: $day";

        return new Response($content);
    }

    /**
     * @Route("/myapp2", name="myapp2")
     */
    public function process2()
    {
        $request = new Request(
            $_GET,
            $_POST,
            array(),
            $_COOKIE,
            $_FILES,
            $_SERVER
        );

        $col = $request->query->get("colour");
        $day = $request->query->get("day");

        $content = "Colour: $col, day: $day";

        return new Response($content);
    }    

    /**
     * @Route("/myapp3", name="myapp3")
     */
    public function process3(Request $request)
    {
        $data = $request->query->all();

        $col = $data["colour"];
        $day = $data["day"];

        $content = "Colour: $col, day: $day";

        return new Response($content);        
    }    
}

MyappController处理由链接创建的三个 GET 请求。

$request = Request::createFromGlobals();
$col = $request->query->get("colour");
$day = $request->query->get("day");

使用Request::createFromGlobals()创建请求对象。 使用get()方法检索 GET 参数。

$request = new Request(
    $_GET,
    $_POST,
    array(),
    $_COOKIE,
    $_FILES,
    $_SERVER
);

在第二种情况下,使用new关键字创建请求。 它通过 PHP 全局变量传递。

public function process3(Request $request)
{
    $data = $request->query->all();
...    

在第三种情况下,使用 Symfony 的依赖项注入来注入请求对象。 我们使用all()方法从请求中获取所有参数。

$col = $data["colour"];
$day = $data["day"];

从数组中,我们得到值。

$content = "Colour: $col, day: $day";

return new Response($content);  

我们构建内容并返回Response对象。

在本教程中,我们处理了 Symfony 中的请求。

您可能也对以下相关教程感兴趣: Symfony 简介Symfony 邮件教程Symfony 创建路由Symfony 表单教程PHP 教程

{% endraw %}

Symfony HttpClient教程

原文: http://zetcode.com/symfony/httpclient/

Symfony HttpClient教程展示了如何使用HttpClient组件在 Symfony 中创建 HTTP 请求。 该组件提供使用 API​​ 的工具,并支持同步和异步操作。

有关更多信息,请阅读官方 HttpComponent 文档。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 Symfony 受到 Spring 框架的极大启发。

在示例中,我们将使用httpbin.orghttp://jsonplaceholder.typicode.com/在线服务。

$ composer require symfony/http-client
$ composer require symfony/var-dumper

我们安装了HttpClientvar-dumper组件。

HttpClient GET 请求

HTTP 定义了一组请求方法,以指示要对给定资源执行的所需操作。 GET 请求用于从指定资源请求数据。 使用 GET 的请求应仅检索数据,而对数据没有其他影响。

注意:建议使用 HTTP 方法的目的和影响; 这些不是严格的规则。 这就是我们前面说过 GET 方法不应对数据产生影响的原因。 实际上,这并不总是遵循的。

get_request.php

<?php

require('vendor/autoload.php');

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'http://webcode.me');

$statusCode = $response->getStatusCode();
echo $statusCode . "\n";

$contentType = $response->getHeaders()['content-type'][0];
echo $contentType . "\n";

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

该示例创建HttpClient,并向指定的网页发出 GET 请求。

注意:响应始终是异步的,因此对方法的调用将立即返回,而不是等待接收响应。 有诸如getStatusCode()getContent()之类的阻塞方法,它们会等到接收到完整的响应内容为止。

$httpClient = HttpClient::create();
$response = $httpClient->request('GET', 'http://webcode.me');

我们用HttpClient::create()创建一个HttpClient。 使用request()方法生成 GET 请求。

$statusCode = $response->getStatusCode();
echo $statusCode . "\n";

我们使用getStatusCode()方法获取状态代码。

$contentType = $response->getHeaders()['content-type'][0];
echo $contentType . "\n";

从响应的标题中,我们获得内容类型。

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

最后,我们使用getContent()方法获得页面的内容。

$ php get_request.php
200
text/html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My html page</title>
</head>
<body>

    <p>
        Today is a beautiful day. We go swimming and fishing.
    </p>

    <p>
          Hello there. How are you?
    </p>

</body>
</html>

这是输出。

HttpClient用户代理

创建HttpClient时,我们可以传递一些选项,例如标头值。

user_agent.php

<?php

require('vendor/autoload.php');

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create(['headers' => [
    'User-Agent' => 'PHP console app',
]]);

$response = $httpClient->request('GET', 'https://httpbin.org/user-agent');

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

我们连接到httpbin.org网站,该网站是用于测试 HTTP 请求&响应的在线工具。

$httpClient = HttpClient::create(['headers' => [
    'User-Agent' => 'PHP console app',
]]);

在标题数组中,我们添加User-Agent选项。

$response = $httpClient->request('GET', 'https://httpbin.org/user-agent');

我们将 GET 请求发送到https://httpbin.org/user-agent URL,该 URL 返回请求的用户代理选项。

HttpClient toArray()

toArray()方法通常将响应主体解码为数组,并从 JSON 有效负载解码为数组。

content_array.php

<?php

require('vendor/autoload.php');

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();

$response = $httpClient->request('GET', 
        'https://jsonplaceholder.typicode.com/posts/2/');

dump($response->toArray());

该示例向jsonplaceholder.typicode.com在线服务网站发出 GET 请求,该网站以 JSON 格式返回 ID 为 2 的帖子。

dump($response->toArray());

我们转储toArray()方法的输出。

$ php content_array.php
array:4 [
  "userId" => 1
  "id" => 2
  "title" => "qui est esse"
  "body" => """
    est rerum tempore vitae\n
    sequi sint nihil reprehenderit dolor beatae ea dolores neque\n
    fugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\n
    qui aperiam non debitis possimus qui neque nisi nulla
    """
]

这是输出。

HttpClient POST 数据

发布请求用于将数据发送到服务器。 数据位于 HTTP 请求的请求正文中。

发布请求永远不会被缓存,它们不会保留在浏览器历史记录中,也无法被添加书签,并且数据长度没有限制。

post_data.php

<?php

require('vendor/autoload.php');

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();

$response = $httpClient->request('POST', 'https://httpbin.org/post', [
    'body' => ['msg' => 'Hello there']
]);

echo $response->getContent();

在示例中,我们在 POST 请求中将消息变量发送到指定的 URL。 在响应对象中,我们找到了 POST 请求中发送的数据。

$ php post_data.php
{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "msg": "Hello there"
  },
  ...
}

这是输出。

HttpClient重定向

URL 重定向是将请求从一页转发到另一页的过程。 当 Web 浏览器尝试打开已重定向的 URL 时,将打开一个具有其他 URL 的页面。 一个 URL 可能有多个重定向。

使用重定向的原因:

  • URL 缩短
  • 防止在移动网页时断开链接
  • 允许属于同一所有者的多个域名引用一个网站
  • 隐私保护
  • HTTP 到 HTTP 的过渡
  • 恶意目的,例如网络钓鱼攻击或恶意软件分发

发出请求时,HttpClient遵循重定向,最多 20 个。 max_redirects属性用于配置此行为。 值 0 表示不遵循任何重定向。

redirect.php

<?php

require 'vendor/autoload.php';

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();

$response = $httpClient->request('GET', 'https://httpbin.org/redirect/4', [
    'max_redirects' => 3,
]);

echo $response->getStatusCode();

我们将 GET 请求发送到重定向四次的 URL,同时将max_redirects属性设置为三。 这意味着我们获得 302 重定向状态代码。 如果我们增加max_redirects值,我们应该得到 200。

HttpClient查询参数

查询参数是统一资源定位器(URL)的一部分,该 URL 将值分配给指定的参数。 这是将数据发送到目标服务器的一种方法。

http://example.com/api/users?name=John%20Doe&occupation=gardener

查询参数在?字符之后指定。&分隔了多个字段。 特殊字符(例如空格)被编码。 在上面的字符串中,空格用%20值编码。

Symfony HttpClient在将值包含在 URL 中之前会自动对其进行编码。

query_params.php

<?php

require('vendor/autoload.php');

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();

$response = $httpClient->request('GET', 'https://httpbin.org/get', [

    'query' => [
        'name' => 'John Doe',
    ],
]);

echo $response->getContent();

我们将name字段发送到https://httpbin.org/get URL。 在响应中,我们返回了 URL 参数。

$ php query_params.php
{
  "args": {
    "name": "John Doe"
  },
  "headers": {
    "Accept-Encoding": "deflate, gzip",
    "Host": "httpbin.org",
    "User-Agent": "Symfony HttpClient/Curl"
  },
  ...
}

这是输出。

使用 httpbin 的 Docker 容器

httpbin.org还提供了一个用于测试的 Docker 容器。

$ docker run -p 80:80 kennethreitz/httpbin

我们运行容器。

docker_ex.php

<?php

require 'vendor/autoload.php';

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();

$response = $httpClient->request('GET', 'http://localhost:80/anything',
    [
        'json' => ['message' => 'Hello there'],
    ]);

dump($response->toArray());

在示例中,我们使用 httpbin 的服务连接到容器。 localhost:80/anything返回传递给请求的任何内容。

HTTP 基本认证

HTTP 基本认证是一种简单的质询和响应机制,其中服务器从客户端请求凭据。 客户端在授权标头中将凭据传递给服务器。 认证信息不以任何方式加密或哈希。 它使用 Base64 算法编码。 因此,仅将 HTTP 基本认证与HTTPS一起使用才被认为是安全的。

HTTP 基本认证使用 HTTP 标头中的标准字段,从而无需握手。

authenticate.php

<?php

require('vendor/autoload.php');

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create([
    'auth_basic' => ['user7', 'passwd']
]);

$response = $httpClient->request('GET', 
    'https://httpbin.org/basic-auth/user7/passwd');

echo $response->getStatusCode();

dump($response);

在示例中,我们使用 HTTP 基本认证。

$httpClient = HttpClient::create([
    'auth_basic' => ['user7', 'passwd']
]);

HTTP 基本认证通过auth_basic选项指定。 所有请求将使用相同的凭据。

$response = $httpClient->request('GET', 
  'https://httpbin.org/basic-auth/user7/passwd');

不要与 URL 中的用户名和密码混淆; 这仅用于在 httpbin 的服务中进行测试。

HttpClient流数据

自 HTTP 1.1 以来,块传输编码是一种流数据传输机制。 在分块传输编码中,数据流被分为一系列不重叠的块。

块彼此独立地发送和接收。 每个块之前都有其大小(以字节为单位)。

在 Symfony HttpClient中,流传输是通过stream()完成的。

streaming.php

<?php

require 'vendor/autoload.php';

use Symfony\Component\HttpClient\HttpClient;

$httpClient = HttpClient::create();

$url = 'https://download.freebsd.org/ftp/releases/amd64/amd64/ISO-IMAGES/12.0/FreeBSD-12.0-RELEASE-amd64-mini-memstick.img';
$response = $httpClient->request('GET', $url, [
    'buffer' => false,
]);

if (200 !== $response->getStatusCode()) {
    throw new \Exception('Failed to create a request');
}

$fileHandler = fopen('freebsd-12.0-amd64-mini-memstick.iso', 'w');
foreach ($httpClient->stream($response) as $chunk) {
    fwrite($fileHandler, $chunk->getContent());
}

在示例中,我们下载了 FreeBSD ISO 映像。

$response = $httpClient->request('GET', $url, [
  'buffer' => false,
]);

我们创建一个对指定 URL 的 GET 请求; (可选)我们可以关闭内存缓冲。

$fileHandler = fopen('freebsd-12.0-amd64-mini-memstick.iso', 'w');
foreach ($httpClient->stream($response) as $chunk) {
    fwrite($fileHandler, $chunk->getContent());
}

我们以块的形式获取响应内容,并将其保存在文件中。

Symfony HttClient Webapp 示例

在下面的示例中,我们创建一个 Symfony Web 应用,该应用使用HttpClient生成请求。 我们使用HttpClientInterface注入HttpClient

该应用向https://jsonplaceholder.typicode.com/users发出 GET 请求,该请求返回十个用户。

$ composer create-project symfony/skeleton symfapp
$ cd symfapp
$ composer require annotations
$ composer require maker server --dev
$ composer require symfony/http-client

我们创建一个新的 Symfony 框架应用并安装一些依赖项。

config/packages/framework.yaml

framework:
...
  http_client:
      max_host_connections: 5
      default_options:
          max_redirects: 3

framework.yaml文件中,我们可以配置HttpClient

$ php bin/console make:controller DataController

我们创建一个新的控制器。

src/Controller/DataController.php

<?php

namespace App\Controller;

use App\Service\UserService;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class DataController extends AbstractController
{
    /**
     * @Route("/data", name="data")
     */
    public function index(UserService $userService): Response
    {
        $data = $userService->getUsers();

        return $this->json($data);
    }
}

DataController注入UserService,调用其getUsers()方法以检索数据。 数据作为 JSON 返回给调用方。

src/Service/UserService.php

<?php

namespace App\Service;

use Symfony\Contracts\HttpClient\HttpClientInterface;

class UserService
{
    private $httpClient;

    public function __construct(HttpClientInterface $httpClient)
    {
        $this->httpClient = $httpClient;
    }

    public function getUsers(): Array
    {
        $response = $this->httpClient->request('GET', 
            'https://jsonplaceholder.typicode.com/users');

        $data = $response->getContent();

        $decoded = json_decode($data);

        return $decoded;
    }
}

这是UserService.

public function __construct(HttpClientInterface $httpClient)
{
    $this->httpClient = $httpClient;
}

我们用HttpClientInterface注入 HttpClient。

public function getUsers(): Array
{
    $response = $this->httpClient->request('GET', 
        'https://jsonplaceholder.typicode.com/users');

    $data = $response->getContent();

    $decoded = json_decode($data);

    return $decoded;
}

我们生成一个 GET 请求,解码数据并返回它。

$ php bin/console server:run

我们运行该应用并导航到localhost:8000/data

在本教程中,我们使用了 Symfony HttpClient组件。

您可能也对以下相关教程感兴趣: Symfony 简介Symfony 验证教程Symfony 服务教程Symfony 表单教程PHP 教程或列出所有 Symfony 教程

{% raw %}

Symfony Flash 消息

原文: http://zetcode.com/symfony/flash/

Symfony Flash 消息教程展示了如何在 Symfony 中创建 Flash 消息。 Flash 消息是用于用户通知的临时消息。 它们存储在一个会话中,并且一旦检索就消失。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 于 2005 年发布为免费软件。Symfony 的原始作者是 Fabien Potencier。 Symfony 受到 Spring 框架的极大启发。

Symfony Flash 示例

在下面的示例中,我们有一个简单的表单,其中有一个输入框用于输入用户名。 如果用户输入的名称无效(空或仅包含空格),则应用将在表单上方显示一个闪烁通知。

注意:在我们的应用中,我们有一个 GET 表单。 GET 方法被认为是安全,因此我们未实现 CSRF 保护。 Symfony CSRF 教程涵盖了 Symfony 中的 CSRF 保护。

$ composer create-project symfony/skeleton flashmsg

使用composer,我们创建一个新的 Symfony 骨架项目。

$ cd flashmsg

我们转到项目目录。

$ composer require annotations twig

我们安装了两个包:annotationstwig

$ composer require server maker --dev

我们安装了开发 Web 服务器和 Symfony maker

src/Service/Validate.php

<?php

namespace App\Service;

class Validate
{
    public function isValid(?string $name): bool
    {
        if (!isset($name) || trim($name) === '') {

            return false;
        } else {

            return true;
        }
    }
}

Validate服务检查提供的字符串是否为空或仅包含空格。

注意:在生产应用中,我们使用一些验证库,例如 Symfony 的symfony/validator或 PHP Rackit 或 Respect。

$ php bin/console make:controller FormController

创建了FormController

src/Controller/FormController.php

<?php

namespace App\Controller;

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

class FormController extends AbstractController
{
    /**
     * @Route("/", name="index")
     */
    public function index()
    {
        return $this->render('form/index.html.twig');
    }

    /**
     * @Route("/form", name="form")
     */
    public function doForm(Request $request, Validate $valService)
    {
        $name = $request->query->get("name");

        $validated = $valService->isValid($name);

        if ($validated) {

            $msg = sprintf("Hello %s!", $name);

            return new Response($msg,  Response::HTTP_OK,
               ['content-type' => 'text/plain']);
        } else {

            $this->addFlash(
                'notice', 'Invalid name entered'
            );

            return $this->redirectToRoute("index");
        }
    }    
}

FormController响应根路径和形式路径。

/**
 * @Route("/", name="index")
 */
public function index()
{
    return $this->render('form/index.html.twig');
}

根路径返回 HTML 表单。

/**
 * @Route("/form", name="form")
 */
public function doForm(Request $request, Validate $valService)
{

doForm()方法中,我们注入了Request对象和Validate服务。

$name = $request->get("name");
$validated = $valService->isValid($name);

我们检索名称输入并对其进行验证。

$this->addFlash(
    'notice', 'Invalid name entered'
);

return $this->redirectToRoute("index");

如果输入无效,我们将添加带有addFlash()的 Flash 消息,并在index路径上添加确定。

templates/form/index.html.twig

{% extends 'base.html.twig' %}

{% block title %}Home page{% endblock %}

{% block stylesheets %}
<style> .flash-notice { color: red } </style>
{% endblock %}

{% block body %}

{% for message in app.flashes('notice') %}
    <div class="flash-notice">
        {{ message }}
    </div>
{% endfor %}

<form action="/form">

    <div>
        <label>Enter your name:</label>
        <input type="text" name="name">
    </div>

    <button type="submit">Send</button>

</form>

{% endblock %}

FormController返回一个表单页面。 它包含用户名的输入。

{% for message in app.flashes('notice') %}
    <div class="flash-notice">
        {{ message }}
    </div>
{% endfor %}

当应用重定向到此页面时,我们浏览 Flash 消息并将其显示在表单上方的div标签中。

templates/base.html.twig

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        {% block stylesheets %}{% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>

base.html.twig模板包含其他模板文件共享的代码。 它定义了将在子模板中替换的块。

$ php bin/console server:run

我们运行该应用。

在本教程中,我们在 Symfony 中处理了 Flash 消息。

您可能也对以下相关教程感兴趣: Symfony 简介Symfony 验证教程Symfony 服务教程Symfony 表单教程PHP 教程或列出所有 Symfony 教程

{% endraw %}

{% raw %}

在 Symfony 中发送邮件

原文: http://zetcode.com/symfony/mail/

Symfony 邮件教程显示了如何在 Symfony 中发送简单邮件。 Symfony 使用 SwiftMailer 发送电子邮件。

Symfony

Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。 Symfony 是带有一些商业附加组件的免费软件。 Symfony 的灵感来自 Ruby on Rails,Django 和 Spring Framework。

SwiftMailer

SwiftMailer 是免费的功能丰富的 PHP 邮件程序。 Symfony 通过其symfony/swiftmailer-bundle集成了 SwiftMailer。

Symfony 发送邮件示例

在示例中,我们发送了一封简单的电子邮件。 我们使用 Twig 创建电子邮件模板。

建立应用

我们首先使用composer建立应用。

$ composer create-project symfony/skeleton mail 
$ cd mail

我们创建一个新的 Symfony 骨架项目,然后进入新创建的项目目录。

$ composer req twig annotations monolog

我们安装了 Web 应用所需的三个基本 Symfony 包。

$ composer req symfony/swiftmailer-bundle 

我们安装symfony/swiftmailer-bundle

$ composer req maker server --dev     

我们安装了用于开发的包:makerserver

.env

... 
MAILER_URL=smtp://smtp.example.com:465?encryption=ssl&auth_mode=login&username=admin@example.com&password=s$cret

.env文件中,设置MAILER_URL变量。 它包含将要发送电子邮件的 SMTP 服务器。 如果您是初学者,请避免使用 Gmail,因为由于 Gmail 的高度安全性,因此正确设置 Gmail 是一项复杂的任务。

而是使用托管服务提供商提供的 SMTP 服务器或诸如 mailgun 或 mailtrap 之类的服务。 必需的选项(例如端口号和加密)由提供商/服务提供。

$ php bin/console make:controller TestMailController 

我们创建一个TestMailController,其中包含一个用于发送电子邮件的简单链接。

src/Controller/TestMailController.php

<?php

namespace App\Controller;

use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class TestMailController extends AbstractController
{
    /**
     * @Route("/test/mail", name="test_mail")
     */
    public function index(Request $request, \Swift_Mailer $mailer, 
        LoggerInterface $logger)
    {
        $name = $request->query->get('name');

        $message = new \Swift_Message('Test email');
        $message->setFrom('admin@zetcode.com');
        $message->setTo('admin2@zetcode.com');
        $message->setBody(
            $this->renderView(
                'emails/mymail.html.twig',
                ['name' => $name]
            ),
            'text/html'
        );

        $mailer->send($message);

        $logger->info('email sent');
        $this->addFlash('notice', 'Email sent');

        return $this->redirectToRoute('home');
    }
}

TestMailControllerindex()方法中,我们发送电子邮件。 请注意,发送电子邮件的代码不应在生产应用的控制器中。 它应该在某种服务。 但是出于简单原因,我们将其保留在此处。

public function index(Request $request, \Swift_Mailer $mailer, 
    LoggerInterface $logger)
{

我们注入RequestSwift_Mailer和记录器。

$name = $request->query->get('name');

我们获取在 GET 请求中使用的名称。

$message = new \Swift_Message('Test email');
$message->setFrom('example@example.com');
$message->setTo('example2@example.com');

创建了Swift_Messagefromto电子邮件值经过硬编码,以简化此示例。 您可以删除硬编码的值作为练习。 (将源电子邮件设置为参数,从表单中获取目标电子邮件。)

$message->setBody(
    $this->renderView(
        'emails/mymail.html.twig',
        ['name' => $name]
    ),
    'text/html'
);

使用setBody(),我们设置电子邮件的正文。 renderView()方法从提供的 Twig 模板渲染视图。 我们将$name变量传递给模板。

$mailer->send($message);

电子邮件带有send()发送。

$logger->info('email sent');
$this->addFlash('notice', 'Email sent');

我们登录&闪烁一条消息。 成功发送电子邮件后,将显示即显消息。

return $this->redirectToRoute('home');

我们重定向到显示 Flash 消息的主页。

templates/emails/myemail.html.twig

Hi {{ name }}! You've got a test email.

Thanks!

这是电子邮件的简单模板。

$ php bin/console make:controller HomeController 

我们创建一个HomeController。 它包含一个用于发送电子邮件的简单链接。

src/Controller/HomeController.php

<?php

namespace App\Controller;

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

class HomeController extends AbstractController
{
    /**
    * @Route("/", name="home")
    */
    public function index()
    {
        return $this->render('home/index.html.twig');
    }
}

HomeController呈现主页。

templates/home/index.html

{% extends 'base.html.twig' %}

{% block title %}Home page{% endblock %}

{% block stylesheets %}
<style>
    .flash-notice {
        margin: 8px;
        padding-left: 8px;
        width: 150px;
        background-color: rgb(113, 241, 113)
    }

    .hide {
        opacity: 0;
        transition: opacity 1000ms;
    }
</style>
{% endblock %}

{% block body %}

<a href="/test/mail?name=Peter Novak">Send a test mail</a>

{% for message in app.flashes('notice') %}
<div id="flash-notice" class="flash-notice">
    {{ message }}
</div>
{% endfor %}

{% block javascripts %}
<script src="main.js"></script>
{% endblock %}

{% endblock %}

主页包含用于发送电子邮件的链接。 如果发送了电子邮件,我们会显示一条通知。 单击此通知可以将其隐藏。

<style>
    .flash-notice {
        margin: 8px;
        padding-left: 8px;
        width: 150px;
        background-color: rgb(113, 241, 113)
    }

    .hide {
        opacity: 0;
        transition: opacity 1000ms;
    }
</style>    

我们为通知设置了一些样式。 同样,hide类提供了一个简单的淡出动画。 通过将此类插入通知元素,可以在 JavaScript 中启动动画。

<a href="/test/mail?name=Peter Novak">Send a test mail</a>

此链接发出触发电子邮件的 GET 请求。 我们随请求发送一个name属性。 名称是硬编码的; 作为练习,您可以创建一个表单,该表单将指定名称和目标电子邮件。

{% for message in app.flashes('notice') %}
<div id="flash-notice" class="flash-notice">
    {{ message }}
</div>
{% endfor %}

如果有即时消息,我们将其显示。

<script src="main.js"></script>

动画由位于main.js文件中的 JavaScript 代码控制。

public/main.js

const flash = document.getElementById('flash-notice');

flash.addEventListener('click', function () {

    flash.classList.add('hide');
});

当我们单击 Flash 消息时,事件回调将hide类添加到元素的类列表中,从而启动淡出动画。

templates/base.html.twig

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>{% block title %}Welcome!{% endblock %}</title>
    {% block stylesheets %}

    {% endblock %}
</head>

<body>
    {% block body %}{% endblock %}
    {% block javascripts %}{% endblock %}
</body>

</html>

这是基本的 Twig 模板。

在本教程中,我们展示了如何在 Symfony 中发送简单的电子邮件。

您可能也对以下相关教程感兴趣: Symfony 简介Symfony 服务教程Symfony 请求教程Symfony Flash 消息Symfony 表单教程PHP 教程

请参阅 Mailtrap 的如何在 Symfony 中发送电子邮件的示例

{% endraw %}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值