0% found this document useful (0 votes)
71 views81 pages

Symfony 6 The Fast Track Fabien Potencier PDF Download

The document is a guide for learning Symfony 6, authored by Fabien Potencier, and covers various topics from setting up the work environment to deploying applications. It includes detailed steps for building a web application, managing databases, and implementing features like user interfaces, security, and testing. The book is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license.

Uploaded by

mnwerswn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views81 pages

Symfony 6 The Fast Track Fabien Potencier PDF Download

The document is a guide for learning Symfony 6, authored by Fabien Potencier, and covers various topics from setting up the work environment to deploying applications. It includes detailed steps for building a web application, managing databases, and implementing features like user interfaces, security, and testing. The book is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International license.

Uploaded by

mnwerswn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Symfony 6 The Fast Track Fabien Potencier

download

https://ebookbell.com/product/symfony-6-the-fast-track-fabien-
potencier-47644076

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

The Definitive Guide To Symfony Francois Zaninotto And Fabien


Potencier

https://ebookbell.com/product/the-definitive-guide-to-symfony-
francois-zaninotto-and-fabien-potencier-5551804

Symfony2 Essentials Wojciech Bancer

https://ebookbell.com/product/symfony2-essentials-wojciech-
bancer-6852966

Symfony 13 Web Application Development Tim Bowler Wojciech Bancer

https://ebookbell.com/product/symfony-13-web-application-development-
tim-bowler-wojciech-bancer-1232848

Extending Symfony2 Web Application Framework Sebastien Armand

https://ebookbell.com/product/extending-symfony2-web-application-
framework-sebastien-armand-34415944
Mastering Symfony Sohail Salehi

https://ebookbell.com/product/mastering-symfony-sohail-salehi-5753830

A Year With Symfony Writing Healthy Reusable Symfony2 Matthias Noback

https://ebookbell.com/product/a-year-with-symfony-writing-healthy-
reusable-symfony2-matthias-noback-5498662

A Year With Symfony Writing Healthy Reusable Symfony2 Code Noback

https://ebookbell.com/product/a-year-with-symfony-writing-healthy-
reusable-symfony2-code-noback-11723322

A Gentle Introduction To Symfony 14 Franois Zaninotto Fabien Potencier

https://ebookbell.com/product/a-gentle-introduction-to-
symfony-14-franois-zaninotto-fabien-potencier-2148262

Building Php Applications With Symfony Cakephp And Zend Framework 1st
Edition Bartosz Porbski

https://ebookbell.com/product/building-php-applications-with-symfony-
cakephp-and-zend-framework-1st-edition-bartosz-porbski-2324834
Symfony: The Fast Track
Fabien Potencier
https://fabien.potencier.org/

@fabpot
@fabpot
Symfony: The Fast Track
ISBN-13: 978-2-918390-37-4
Symfony SAS
6, rue des bateliers
92 110 Clichy
France

This work is licensed under the Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
license (https://creativecommons.org/licenses/by-nc-sa/4.0/).
Below is a human-readable summary of (and not a substitute for) the license (https://creativecommons.org/
licenses/by-nc-sa/4.0/legalcode).
You are free to
Share — copy and redistribute the material in any medium or format
Adapt — remix, transform, and build upon the material

• Attribution: You must give appropriate credit, provide a link to the license, and indicate if changes were
made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses
you or your use.

• Non Commercial: You may not use the material for commercial purposes.

• Share Alike: If you remix, transform, or build upon the material, you must distribute your contributions
under the same license as the original.

The information in this book is distributed on an “as is” basis, without warranty. Although every precaution
has been taken in the preparation of this work, neither the author(s) nor Symfony shall have any liability to
any person or entity with respect to any loss or damage caused or alleged to be caused directly or indirectly by
the information contained in this work.
If you find typos or errors, feel free to report them at support@symfony.com. This book is continuously
updated based on user feedback.

Locale en

Original English Text Version v6.2.0

Text Translation Version current

Generated Code Version 6.2-1

Book Generated Date December 20, 2022


Contents at a Glance
Step 0: What is it about?.................................................................................. 21
Step 1: Checking your Work Environment ........................................................ 25
Step 2: Introducing the Project ......................................................................... 31
Step 3: Going from Zero to Production ............................................................. 37
Step 4: Adopting a Methodology ...................................................................... 45
Step 5: Troubleshooting Problems .................................................................... 47
Step 6: Creating a Controller ........................................................................... 53
Step 7: Setting up a Database........................................................................... 61
Step 8: Describing the Data Structure............................................................... 69
Step 9: Setting up an Admin Backend ............................................................... 83
Step 10: Building the User Interface ................................................................. 95
Step 11: Branching the Code.......................................................................... 107
Step 12: Listening to Events ........................................................................... 115
Step 13: Managing the Lifecycle of Doctrine Objects ....................................... 121
Step 14: Accepting Feedback with Forms ........................................................ 131
Step 15: Securing the Admin Backend............................................................. 147
Step 16: Preventing Spam with an API ........................................................... 155
Step 17: Testing ............................................................................................ 163
Step 18: Going Async .................................................................................... 181
Step 19: Making Decisions with a Workflow................................................... 193
Step 20: Emailing Admins ............................................................................. 199
Step 21: Caching for Performance.................................................................. 211
Step 22: Styling the User Interface with Webpack............................................ 227
Step 23: Resizing Images ............................................................................... 233
Step 24: Running Crons................................................................................. 239
Step 25: Notifying by all Means ..................................................................... 245
Step 26: Exposing an API with API Platform .................................................. 261

v
Step 27: Building an SPA............................................................................... 269
Step 28: Localizing an Application ................................................................. 287
Step 29: Managing Performance .................................................................... 301
Step 30: Discovering Symfony Internals.......................................................... 311
Step 31: Using Redis to Store Sessions ............................................................ 321
Step 32: Using RabbitMQ as a Message Broker............................................... 325
Step 33: What’s Next? ................................................................................... 331

vi
Table of Contents
Step 0: What is it about?.................................................................................. 21

Step 1: Checking your Work Environment ........................................................ 25


1.1: A Computer ......................................................................................... 25
1.2: Opinionated Choices............................................................................. 26
1.3: IDE ..................................................................................................... 26
1.4: Terminal.............................................................................................. 26
1.5: Git ...................................................................................................... 27
1.6: PHP .................................................................................................... 27
1.7: Composer ............................................................................................ 27
1.8: NodeJS ................................................................................................ 28
1.9: Docker and Docker Compose ................................................................ 28
1.10: Symfony CLI ...................................................................................... 28

Step 2: Introducing the Project ......................................................................... 31


2.1: Revealing the Project ............................................................................ 31
2.2: Learning is Doing ................................................................................. 32
2.3: Looking at the Final Infrastructure Diagram .......................................... 32
2.4: Getting the Project Source Code............................................................. 34
2.5: Navigating the Source Code .................................................................. 35

Step 3: Going from Zero to Production ............................................................. 37


3.1: Initializing the Project........................................................................... 38
3.2: Creating some Public Resources............................................................. 40
3.3: Launching a Local Web Server .............................................................. 40
3.4: Preparing for Production....................................................................... 41
3.5: Going to Production ............................................................................. 42

ix
Step 4: Adopting a Methodology ...................................................................... 45
4.1: Implementing a Git Strategy.................................................................. 45
4.2: Deploying to Production Continuously................................................... 46

Step 5: Troubleshooting Problems .................................................................... 47


5.1: Discovering the Symfony Debugging Tools ............................................. 47
5.2: Understanding Symfony Environments................................................... 49
5.3: Managing Environment Configurations.................................................. 50
5.4: Configuring your IDE ........................................................................... 51
5.5: Debugging Production .......................................................................... 51

Step 6: Creating a Controller ........................................................................... 53


6.1: Being Lazy with the Maker Bundle ........................................................ 53
6.2: Choosing a Configuration Format.......................................................... 54
6.3: Generating a Controller ........................................................................ 54
6.4: Adding an Easter Egg............................................................................ 57
6.5: Debugging Variables............................................................................. 58

Step 7: Setting up a Database........................................................................... 61


7.1: Adding PostgreSQL to Docker Compose ................................................ 61
7.2: Starting Docker Compose...................................................................... 62
7.3: Accessing the Local Database ................................................................ 63
7.4: Dumping and Restoring Database Data ................................................. 64
7.5: Adding PostgreSQL to Platform.sh ........................................................ 64
7.6: Accessing the Platform.sh Database ....................................................... 65
7.7: Exposing Environment Variables ........................................................... 66
7.8: Describing your Infrastructure .............................................................. 66

Step 8: Describing the Data Structure............................................................... 69


8.1: Configuring Doctrine ORM................................................................... 69
8.2: Understanding Symfony Environment Variable Conventions ................... 70
8.3: Changing the Default DATABASE_URL Value in .env ........................... 70
8.4: Creating Entity Classes ......................................................................... 71
8.5: Linking Entities .................................................................................... 74
8.6: Adding more Properties......................................................................... 78

x
8.7: Migrating the Database ........................................................................ 79
8.8: Updating the Local Database ................................................................ 80
8.9: Updating the Production Database ........................................................ 80

Step 9: Setting up an Admin Backend ............................................................... 83


9.1: Installing more Dependencies ................................................................ 83
9.2: Configuring EasyAdmin ........................................................................ 84
9.3: Customizing EasyAdmin ....................................................................... 90

Step 10: Building the User Interface ................................................................. 95


10.1: Using Twig for the Templates .............................................................. 95
10.2: Using Twig in a Controller .................................................................. 97
10.3: Creating the Page for a Conference ...................................................... 98
10.4: Linking Pages Together..................................................................... 100
10.5: Paginating the Comments.................................................................. 101
10.6: Refactoring the Controller................................................................. 105

Step 11: Branching the Code.......................................................................... 107


11.1: Adopting a Git Workflow .................................................................. 107
11.2: Creating Branches ............................................................................ 108
11.3: Storing Sessions in the Database ........................................................ 108
11.4: Deploying a Branch .......................................................................... 110
11.5: Debugging Production Deployments before Deploying ........................ 112
11.6: Testing Production Deployments before Deploying.............................. 112
11.7: Merging to Production ...................................................................... 113
11.8: Cleaning up...................................................................................... 113

Step 12: Listening to Events ........................................................................... 115


12.1: Adding a Website Header .................................................................. 115
12.2: Discovering Symfony Events.............................................................. 117
12.3: Implementing a Subscriber ................................................................ 117
12.4: Sorting Conferences by Year and City ................................................ 119

Step 13: Managing the Lifecycle of Doctrine Objects ....................................... 121


13.1: Defining Lifecycle Callbacks.............................................................. 121
13.2: Adding Slugs to Conferences .............................................................. 122

xi
13.3: Generating Slugs .............................................................................. 124
13.4: Defining a Complex Lifecycle Callback .............................................. 125
13.5: Configuring a Service in the Container ............................................... 126
13.6: Using Slugs in the Application ........................................................... 127

Step 14: Accepting Feedback with Forms ........................................................ 131


14.1: Generating a Form Type ................................................................... 131
14.2: Displaying a Form ............................................................................ 132
14.3: Customizing a Form Type ................................................................. 134
14.4: Validating Models............................................................................. 136
14.5: Handling a Form .............................................................................. 138
14.6: Uploading Files ................................................................................ 139
14.7: Debugging Forms ............................................................................. 141
14.8: Displaying Uploaded Photos in the Admin Backend ............................ 143
14.9: Excluding Uploaded Photos from Git ................................................. 144
14.10: Storing Uploaded Files on Production Servers ................................... 144

Step 15: Securing the Admin Backend............................................................. 147


15.1: Defining a User Entity ...................................................................... 147
15.2: Generating a Password for the Admin User ........................................ 149
15.3: Creating an Admin ........................................................................... 150
15.4: Configuring the Security Authentication ............................................. 150
15.5: Adding Authorization Access Control Rules ........................................ 152
15.6: Authenticating via the Login Form..................................................... 152

Step 16: Preventing Spam with an API ........................................................... 155


16.1: Signing up on Akismet....................................................................... 155
16.2: Depending on Symfony HTTPClient Component ................................ 155
16.3: Designing a Spam Checker Class ....................................................... 156
16.4: Using Environment Variables ............................................................ 157
16.5: Storing Secrets.................................................................................. 158
16.6: Checking Comments for Spam........................................................... 159
16.7: Managing Secrets in Production......................................................... 160

Step 17: Testing ............................................................................................ 163


17.1: Writing Unit Tests ............................................................................ 163

xii
17.2: Writing Functional Tests for Controllers ............................................ 165
17.3: Configuring the Test Environment ..................................................... 167
17.4: Working with a Test Database .......................................................... 167
17.5: Defining Fixtures.............................................................................. 168
17.6: Loading Fixtures .............................................................................. 170
17.7: Crawling a Website in Functional Tests.............................................. 171
17.8: Submitting a Form in a Functional Test.............................................. 172
17.9: Reloading the Fixtures ...................................................................... 174
17.10: Automating your Workflow with a Makefile ..................................... 174
17.11: Resetting the Database after each Test ............................................. 175
17.12: Using a real Browser for Functional Tests......................................... 177
17.13: Choosing the Right Test Type .......................................................... 178
17.14: Running Black Box Functional Tests with Blackfire........................... 178

Step 18: Going Async .................................................................................... 181


18.1: Flagging Comments .......................................................................... 181
18.2: Understanding Messenger.................................................................. 184
18.3: Coding a Message Handler ................................................................ 185
18.4: Going Async for Real ........................................................................ 188
18.5: Consuming Messages ........................................................................ 189
18.6: Running Workers in the Background.................................................. 190
18.7: Retrying Failed Messages .................................................................. 191
18.8: Running Workers on Platform.sh....................................................... 192

Step 19: Making Decisions with a Workflow................................................... 193


19.1: Describing Workflows....................................................................... 194
19.2: Using a Workflow............................................................................. 195
19.3: Finding Services from the Dependency Injection Container .................. 197

Step 20: Emailing Admins ............................................................................. 199


20.1: Setting an Email for the Admin.......................................................... 199
20.2: Sending a Notification Email ............................................................. 200
20.3: Extending the Notification Email Template ........................................ 201
20.4: Generating Absolute URLs in a Symfony Command ........................... 202
20.5: Wiring a Route to a Controller .......................................................... 203
20.6: Using a Mail Catcher ........................................................................ 205

xiii
20.7: Accessing the Webmail...................................................................... 205
20.8: Managing Long-Running Scripts........................................................ 207
20.9: Sending Emails Asynchronously......................................................... 207
20.10: Testing Emails ................................................................................ 208
20.11: Sending Emails on Platform.sh ........................................................ 209

Step 21: Caching for Performance.................................................................. 211


21.1: Adding HTTP Cache Headers............................................................ 211
21.2: Activating the Symfony HTTP Cache Kernel ...................................... 212
21.3: Avoiding SQL Requests with ESI ....................................................... 213
21.4: Purging the HTTP Cache for Testing.................................................. 218
21.5: Grouping similar Routes with a Prefix ............................................... 219
21.6: Caching CPU/Memory Intensive Operations ...................................... 220
21.7: Profiling and Comparing Performance ............................................... 222
21.8: Configuring a Reverse Proxy Cache on Production.............................. 222
21.9: Enabling ESI Support on Varnish....................................................... 223
21.10: Purging the Varnish Cache .............................................................. 224

Step 22: Styling the User Interface with Webpack............................................ 227


22.1: Using Sass........................................................................................ 228
22.2: Leveraging Bootstrap ........................................................................ 229
22.3: Styling the HTML............................................................................. 230
22.4: Building Assets ................................................................................. 230

Step 23: Resizing Images ............................................................................... 233


23.1: Optimizing Images with Imagine ....................................................... 234
23.2: Adding a new Step in the Workflow ................................................... 235
23.3: Storing Uploaded Data in Production................................................. 237

Step 24: Running Crons................................................................................. 239


24.1: Cleaning up Comments ..................................................................... 239
24.2: Using Class Constants, Container Parameters, and Environment
Variables .................................................................................................. 241
24.3: Creating a CLI Command ................................................................. 241
24.4: Setting up a Cron on Platform.sh ....................................................... 243

xiv
Step 25: Notifying by all Means ..................................................................... 245
25.1: Sending Web Application Notifications in the Browser ........................ 245
25.2: Notifying Admins by Email ............................................................... 249
25.3: Chatting with Admins ....................................................................... 252
25.4: Going Asynchronous across the Board ............................................... 258
25.5: Notifying Users by Email .................................................................. 259

Step 26: Exposing an API with API Platform .................................................. 261


26.1: Installing API Platform ..................................................................... 261
26.2: Exposing an API for Conferences....................................................... 262
26.3: Exposing an API for Comments ......................................................... 265
26.4: Restricting Comments exposed by the API .......................................... 267
26.5: Configuring CORS............................................................................ 268

Step 27: Building an SPA............................................................................... 269


27.1: Creating the Application ................................................................... 269
27.2: Creating the SPA Main Template....................................................... 271
27.3: Running an SPA in the Browser ......................................................... 272
27.4: Adding a Router to handle States ....................................................... 273
27.5: Styling the SPA................................................................................. 275
27.6: Fetching Data from the API............................................................... 277
27.7: Deploying the SPA in Production ....................................................... 283
27.8: Configuring CORS for the SPA.......................................................... 284
27.9: Using Cordova to build a Smartphone Application .............................. 285

Step 28: Localizing an Application ................................................................. 287


28.1: Internationalizing URLs.................................................................... 287
28.2: Adding a Locale Switcher .................................................................. 290
28.3: Translating the Interface ................................................................... 292
28.4: Providing Translations ...................................................................... 295
28.5: Translating Forms ............................................................................ 296
28.6: Localizing Dates............................................................................... 297
28.7: Translating Plurals ........................................................................... 297
28.8: Updating Functional Tests................................................................. 299

Step 29: Managing Performance .................................................................... 301

xv
29.1: Introducing Blackfire ........................................................................ 302
29.2: Setting Up the Blackfire Agent on Docker........................................... 303
29.3: Fixing a non-working Blackfire Installation ........................................ 304
29.4: Configuring Blackfire in Production ................................................... 304
29.5: Configuring Varnish for Blackfire ...................................................... 305
29.6: Profiling Web Pages.......................................................................... 306
29.7: Profiling API Resources..................................................................... 307
29.8: Comparing Performance ................................................................... 307
29.9: Writing Black Box Functional Tests ................................................... 307
29.10: Automating Performance Checks ..................................................... 309

Step 30: Discovering Symfony Internals.......................................................... 311


30.1: Understanding Symfony Internals with Blackfire................................. 311
30.2: Using the Blackfire Debug Addon ...................................................... 315
30.3: Using a Step Debugger with Xdebug................................................... 316

Step 31: Using Redis to Store Sessions ............................................................ 321

Step 32: Using RabbitMQ as a Message Broker............................................... 325


32.1: Switching from PostgreSQL to RabbitMQ .......................................... 325
32.2: Adding RabbitMQ to the Docker Stack .............................................. 326
32.3: Restarting Docker Services ................................................................ 326
32.4: Exploring the RabbitMQ Web Management Interface ......................... 327
32.5: Deploying RabbitMQ........................................................................ 328

Step 33: What’s Next? ................................................................................... 331

xvi
Acknowledgments

I love books. Books that I can hold in hands.

The last time I wrote a book about Symfony was exactly 10 years ago. It
was about Symfony 1.4. I have never written about Symfony since then!

I was so excited to write again about Symfony that I finished the first draft
in a week. But the version you are reading took way more time. Writing
a book takes a lot of time and energy. From the cover design to the page
layout. From code tweaks to peer reviews. It is almost never finished.
You can always improve a section, enhance some piece of code, fix some
typos, or rewrite an explanation to make it shorter and better.

Writing a book is a journey that you don’t want to do alone. Many people
contributed directly or indirectly. Thank you all!

I want to sincerely thank all the great people who spent a lot of time
reviewing the content to spot typos and improve the content; some even
helped me write some of the code snippets:

Javier Eguiluz Kévin Dunglas


Ryan Weaver Tugdual Saunier
Titouan Galopin Grégoire Pineau
Nicolas Grekas Alexandre Salomé

xvii
Translators
The official Symfony documentation is only available in English. We had
some translations in the past but we decided to stop providing them as
they were always out of sync. And outdated documentation is probably
worse than no documentation at all.

The main issue with translations is maintenance. The Symfony


documentation is updated every single day by dozens of contributors.
Having a team of volunteers translating all changes in near real time is
almost impossible.

However, translating a book like the one you are currently reading is
more manageable as I tried to write about features that won’t change
much over time. This is why the book contents should stay quite stable
over time.

But why would we ever want non-English documentation in a tech world


where English is the de facto default language? Symfony is used by
developers everywhere in the world. And some of them are less
comfortable reading English material. Translating some “getting started”
documentation is part of the Symfony diversity initiative in which we
strive to find ways to make Symfony as inclusive as possible.

As you can imagine, translating more than 300 pages is a huge amount
of work, and I want to thank all the people who helped translating this
book:

xviii
Company Backers

https://sensiolabs.com/

https://platform.sh/

https://qossmic.com/

https://blackfire.io/ https://les-tilleuls.coop/

xix
Family Love
Family support is everything. A big thank-you to my wife, Hélène and
my two wonderful children, Thomas and Lucas, for their continuous
support.

Enjoy Thomas’s illustration… and the book!

xx
Step 0
What is it about?

Symfony is one of the most successful PHP projects. It is both a strong


full-stack framework and a popular set of reusable components.
Since the release of Symfony 2.0 in 2011, the project has now reached
maturity. I can feel that everything we have done in the past few years
come together nicely. New low-level components, high-level integrations
with other software, tools helping developers improve their productivity.
The developer experience has improved substantially without sacrificing
flexibility. It has never been so fun to use Symfony for a project.
If you are new to Symfony, this book shows the power of the framework
and how it can improve your productivity by developing an application,
step by step.
If you are already a Symfony developer, you should rediscover it. The
framework has evolved dramatically during the last few years and the
developer experience has improved significantly. I have the feeling that
many Symfony developers are still “stuck” with old habits and that they
have a hard time embracing the new ways of developing applications with
Symfony. I can understand some of the reasons. The pace of evolution is
staggering. When working full-time on a project, developers do not have

21
time to follow everything happening in the community. I know first hand
as I would not pretend that I can follow everything myself. Far from it.
And it is not just about new ways of doing things. It is also about
new components: HTTP client, Mailer, Workflow, Messenger. They are
game changers. They should change the way you think about a Symfony
application.
I also feel the need for a new book as the Web has evolved a lot. Topics
like APIs, SPAs, containerization, Continuous Deployment, and many
others should be discussed now.
Your time is precious. Don’t expect long paragraphs, nor long
explanations about core concepts. The book is more about the journey.
Where to start. Which code to write. When. How. I will try to generate
some interest on important topics and let you decide if you want to learn
more and dig further.
I don’t want to replicate the existing documentation either. Its quality
is excellent. I will reference the documentation copiously in the “Going
Further” section at the end of each step/chapter. Consider this book as a
list of pointers to more resources.
The book describes the creation of an application, from scratch to
production. We won’t develop everything to make it production ready
though. The result won’t be perfect. We will take shortcuts. We might
even skip some edge-case handling, validation or tests. Best practices
won’t be respected all the time. But we are going to touch on almost every
aspect of a modern Symfony project.
While starting to work on this book, the very first thing I did was code
the final application. I was impressed with the result and the velocity I
was able to sustain while adding features, with very little effort. That’s
thanks to the documentation and the fact that Symfony knows how to get
out of your way. I am sure that Symfony can still be improved in many
ways (and I have taken some notes about possible improvements), but the
developer experience is way better than a few years ago. I want to tell the
world about it.
The book is divided into steps. Each step is sub-divided into sub-steps.
They should be fast to read. But more importantly, I invite you to code as
you read. Write the code, test it, deploy it, tweak it.

22
Last, but not least, don’t hesitate to ask for help if you get stuck. You
might hit an edge case or a typo in the code you wrote might be difficult
to find and fix. Ask questions. We have a wonderful community on Slack
and GitHub.
Ready to code? Enjoy!

23
Step 1
Checking your Work
Environment

Before starting to work on the project, we need to check that you have
a good working environment. It is very important. The developers tools
we have at our disposal today are very different from the ones we had 10
years ago. They have evolved a lot, for the better. It would be a shame to
not leverage them. Good tools can get you a long way.
Please, don’t skip this step. Or at least, read the last section about the
Symfony CLI.

1.1 A Computer
You need a computer. The good news is that it can run on any popular
OS: macOS, Windows, or Linux. Symfony and all the tools we are going
to use are compatible with each of these.

25
1.2 Opinionated Choices
I want to move fast with the best options out there. I made opinionated
choices for this book.
PostgreSQL is going to be our choice for everything: from database to
queues, from cache to session storage. For most projects, PostgreSQL is
the best solution, scale well, and allows to simplify the infrastructure with
only one service to manage.
At the end of the book, we will learn how to use RabbitMQ for queues
and Redis for sessions.

1.3 IDE
You can use Notepad if you want to. I would not recommend it though.
I used to work with Textmate. Not anymore. The comfort of using
a “real” IDE is priceless. Auto-completion, use statements added and
sorted automatically, jumping from one file to another are a few features
that will boost your productivity.
I would recommend using Visual Studio Code or PhpStorm. The former is
free, the latter is not but has a better integration with Symfony (thanks to
the Symfony Support Plugin). It is up to you. I know you want to know
which IDE I am using. I am writing this book in Visual Studio Code.

1.4 Terminal
We will switch from the IDE to the command line all the time. You can
use your IDE’s built-in terminal, but I prefer to use a real one to have
more space.
Linux comes built-in with Terminal. Use iTerm2 on macOS. On
Windows, Hyper works well.

26
1.5 Git
For version control, we will use Git as everybody is using it now.
On Windows, install Git bash.
Be sure you know how to do the common operations like running git
clone, git log, git show, git diff, git checkout, …

1.6 PHP
We will use Docker for services, but I like to have PHP installed on my
local computer for performance, stability, and simplicity reasons. Call me
old school if you like, but the combination of a local PHP and Docker
services is the perfect combo for me.
Use PHP 8.1 and check that the following PHP extensions are installed
or install them now: intl, pdo_pgsql, xsl, amqp, gd, openssl, sodium.
Optionally install redis, curl, and zip as well.
You can check the extensions currently enabled via php -m.
We also need php-fpm if your platform supports it, php-cgi works as well.

1.7 Composer
Managing dependencies is everything nowadays with a Symfony project.
Get the latest version of Composer, the package management tool for
PHP.
If you are not familiar with Composer, take some time to read about it.

You don’t need to type the full command names: composer req does
the same as composer require, use composer rem instead of composer
remove, …

27
1.8 NodeJS
We won’t write much JavaScript code, but we will use JavaScript/NodeJS
tools to manage our assets. Check that you have the NodeJS installed.

1.9 Docker and Docker Compose


Services are going to be managed by Docker and Docker Compose. Install
them and start Docker. If you are a first time user, get familiar with the
tool. Don’t panic though, our usage will be very straightforward. No
fancy configurations, no complex setup.

1.10 Symfony CLI


Last, but not least, we will use the symfony CLI to boost our productivity.
From the local web server it provides, to full Docker integration and
cloud support through Platform.sh, it will be a great time saver.
Install the Symfony CLI now.
To use HTTPS locally, we also need to install a certificate authority (CA)
to enable TLS support. Run the following command:
$ symfony server:ca:install

Check that your computer has all needed requirements by running the
following command:
$ symfony book:check-requirements

If you want to get fancy, you can also run the Symfony proxy. It is optional
but it allows you to get a local domain name ending with .wip for your
project.
When executing a command in a terminal, we will almost always prefix it
with symfony like in symfony composer instead of just composer, or symfony
console instead of ./bin/console.

28
The main reason is that the Symfony CLI automatically sets some
environment variables based on the services running on your machine
via Docker. These environment variables are available for HTTP requests
because the local web server injects them automatically. So, using symfony
on the CLI ensures that you have the same behavior across the board.
Moreover, the Symfony CLI automatically selects the “best” possible PHP
version for the project.

29
Step 2
Introducing the Project

We need to find a project to work on. It is quite a challenge as we need


to find a project large enough to cover Symfony thoroughly, but at the
same time, it should be small enough; I don’t want you to get bored
implementing similar features more than once.

2.1 Revealing the Project


It might be nice if the project was somehow related to Symfony and its
community. As we organize quite a few online and in-person conferences
every year, what about a guestbook? A livre d’or as we say in French. I like
the old-fashioned and outdated feeling of developing a guestbook in the
21st century!
We have it. The project is all about getting feedback on conferences: a list
of conferences on the homepage, a page for each conference, full of nice
comments. A comment is composed of some small text and an optional
photo taken during the conference. I suppose I have just written down all
the specifications we need to get started.

31
The project will contain several applications. A traditional web application
with an HTML frontend, an API, and an SPA for mobile phones. How
does that sound?

2.2 Learning is Doing


Learning is doing. Period. Reading a book about Symfony is nice. Coding
an application on your personal computer while reading a book about
Symfony is even better. This book is very special as everything has been
done to let you follow along, code, and be sure to get the same results as
I had locally on my machine when I coded it initially.
The book contains all the code you need to write and all the commands
you need to execute to get the final result. No code is missing. All
commands are written down. This is possible because modern Symfony
applications have very little boilerplate code. Most of the code we will
write together is about the project’s business logic. Everything else is
mostly automated or generated automatically for us.

2.3 Looking at the Final Infrastructure Diagram


Even if the project idea seems simple, we are not going to build an “Hello
World”-like project. We won’t only use PHP and a database.
The goal is to create a project with some of the complexities you might
find in real-life. Want a proof? Have a look at the final infrastructure of
the project:

32
One of the great benefit of using a framework is the small amount of code
needed to develop such a project:
• 20 PHP classes under src/ for the website;
• 550 PHP Logical Lines of Code (LLOC) as reported by PHPLOC;
• 40 lines of configuration tweaks in 3 files (via attributes and YAML),
mainly to configure the backend design;
• 20 lines of development infrastructure configuration (Docker);
• 100 lines of production infrastructure configuration (Platform.sh);
• 5 explicit environment variables.

Ready for the challenge?

2.4 Getting the Project Source Code


To continue on the old-fashioned theme, I could have created a CD
containing the source code, right? But what about a Git repository
companion instead?
Clone the guestbook repository somewhere on your local machine:
$ symfony new --version=6.2-1 --book guestbook

This repository contains all the code of the book.


Note that we are using symfony new instead of git clone as the command
does more than just cloning the repository (hosted on Github under
the the-fast-track organization: https://github.com/the-fast-track/
book-6.2-1). It also starts the web server, the containers, migrates the
database, loads fixtures, … After running the command, the website
should be up and running, ready to be used.
The code is 100% guaranteed to be synchronized with the code in the
book (use the exact repository URL listed above). Trying to manually
synchronize changes from the book with the source code in the repository
is almost impossible. I tried in the past. I failed. It is just impossible.
Especially for books like the ones I write: books that tells you a story

34
about developing a website. As each chapter depends on the previous
ones, a change might have consequences in all following chapters.
The good news is that the Git repository for this book is automatically
generated from the book content. You read that right. I like to automate
everything, so there is a script whose job is to read the book and create
the Git repository. There is a nice side-effect: when updating the book,
the script will fail if the changes are inconsistent or if I forget to update
some instructions. That’s BDD, Book Driven Development!

2.5 Navigating the Source Code


Even better, the repository is not just about the final version of the code
on the main branch. The script executes each action explained in the book
and it commits its work at the end of each section. It also tags each step
and substep to ease browsing the code. Nice, isn’t it?
If you are lazy, you can get the state of the code at the end of a step by
checking out the right tag. For instance, if you’d like to read and test the
code at the end of step 10, execute the following:
$ symfony book:checkout 10

Like for cloning the repository, we are not using git checkout but symfony
book:checkout. The command ensures that whatever the state you are
currently in, you end up with a functional website for the step you ask for.
Be warned that all data, code, and containers are removed by this
operation.
You can also check out any substep:
$ symfony book:checkout 10.2

Again, I highly recommend you code yourself. But if you get stuck, you
can always compare what you have with the content of the book.
Not sure that you got everything right in substep 10.2? Get the diff:
$ git diff step-10-1...step-10-2

35
# And for the very first substep of a step:
$ git diff step-9...step-10-1

Want to know when a file has been created or modified?


$ git log -- src/Controller/ConferenceController.php

You can also browse diffs, tags, and commits directly on GitHub. This is
a great way to copy/paste code if you are reading a paper book!

36
Step 3
Going from Zero to Production

I like to go fast. I want our little project to be live as fast as possible. Like
now. In production. As we haven’t developed anything yet, we will start
by deploying a nice and simple “Under construction” page. You will love
it!
Spend some time trying to find the ideal, old fashioned, and animated
“Under construction” GIF on the Internet. Here is the one I’m going to
use:

I told you, it is going to be a lot of fun.

37
3.1 Initializing the Project
Create a new Symfony project with the symfony CLI tool we have
previously installed together:
$ symfony new guestbook --version=6.2 --php=8.1 --webapp --docker --cloud
$ cd guestbook

This command is a thin wrapper on top of Composer that eases the creation
of Symfony projects. It uses a project skeleton that includes the bare
minimum dependencies; the Symfony components that are needed for
almost any project: a console tool and the HTTP abstraction needed to
create Web applications.
As we are creating a fully-featured web application, we have added a few
options that will make our life easier:
• --webapp: By default, an application with the fewest possible
dependencies is created. For most web projects, it is recommended
to use the webapp package on top. It contains most of the packages
needed for “modern” web applications. The webapp package adds a lot
of Symfony packages, including Symfony Messenger and PostgreSQL
via Doctrine.
• --docker: On your local machine, we will use Docker to manage
services like PostgreSQL. This option enables Docker so that Symfony
will automatically add Docker services based on the required
packages (a PostgreSQL service when adding the ORM or a mail
catcher when adding Symfony Mailer for instance).
• --cloud: If you want to deploy your project on Platform.sh, this
option automatically generates a sensible Platform.sh configuration.
Platform.sh is the preferred and simplest way to deploy testing,
staging, and production Symfony environments in the cloud.

If you have a look at the GitHub repository for the skeleton, you will
notice that it is almost empty. Just a composer.json file. But the guestbook
directory is full of files. How is that even possible? The answer lies in
the symfony/flex package. Symfony Flex is a Composer plugin that hooks
into the installation process. When it detects a package for which it has a

38
recipe, it executes it.
The main entry point of a Symfony Recipe is a manifest file that describes
the operations that need to be done to automatically register the package
in a Symfony application. You never have to read a README file to
install a package with Symfony. Automation is a key feature of Symfony.
As Git is installed on our machine, symfony new also created a Git
repository for us and it added the very first commit.
Have a look at the directory structure:
├── bin/
├── composer.json
├── composer.lock
├── config/
├── public/
├── src/
├── symfony.lock
├── var/
└── vendor/

The bin/ directory contains the main CLI entry point: console. You will
use it all the time.
The config/ directory is made of a set of default and sensible
configuration files. One file per package. You will barely change them,
trusting the defaults is almost always a good idea.
The public/ directory is the web root directory, and the index.php script
is the main entry point for all dynamic HTTP resources.
The src/ directory hosts all the code you will write; that’s where you will
spend most of your time. By default, all classes under this directory use
the App PHP namespace. It is your home. Your code. Your domain logic.
Symfony has very little to say there.
The var/ directory contains caches, logs, and files generated at runtime by
the application. You can leave it alone. It is the only directory that needs
to be writable in production.
The vendor/ directory contains all packages installed by Composer,
including Symfony itself. That’s our secret weapon to be more
productive. Let’s not reinvent the wheel. You will rely on existing libraries
to do the hard work. The directory is managed by Composer. Never

39
touch it.
That’s all you need to know for now.

3.2 Creating some Public Resources


Anything under public/ is accessible via a browser. For instance, if you
move your animated GIF file (name it under-construction.gif) into a
new public/images/ directory, it will be available at a URL like
https://localhost/images/under-construction.gif.
Download my GIF image here:
$ mkdir public/images/
$ php -r "copy('http://clipartmag.com/images/website-under-construction-
image-6.gif', 'public/images/under-construction.gif');"

3.3 Launching a Local Web Server


The symfony CLI comes with a Web Server that is optimized for
development work. You won’t be surprised if I tell you that it works
nicely with Symfony. Never use it in production though.
From the project directory, start the web server in the background (-d
flag):
$ symfony server:start -d

The server started on the first available port, starting with 8000. As a
shortcut, open the website in a browser from the CLI:
$ symfony open:local

Your favorite browser should take the focus and open a new tab that
displays something similar to the following:

40
••• /

To troubleshoot problems, run symfony server:log; it tails the logs


from the web server, PHP, and your application.

Browse to /images/under-construction.gif. Does it look like this?

••• /images/under-construction.gif

Satisfied? Let’s commit our work:


$ git add public/images
$ git commit -m'Add the under construction image'

3.4 Preparing for Production


What about deploying our work to production? I know, we don’t even
have a proper HTML page yet to welcome our users. But being able to see
the little “under construction” image on a production server would be a

41
great step forward. And you know the motto: deploy early and often.
You can host this application on any provider supporting PHP… which
means almost all hosting providers out there. Check a few things though:
we want the latest PHP version and the possibility to host services like a
database, a queue, and some more.
I have made my choice, it’s going to be Platform.sh. It provides everything
we need and it helps fund the development of Symfony.
As we used the --cloud option when we created the project, Platform.sh
has already been initialized with a few files needed by Platform.sh, namely
.platform/services.yaml, .platform/routes.yaml, and
.platform.app.yaml.

3.5 Going to Production


Deploy time?
Create a new remote Platform.sh project:
$ symfony cloud:project:create --title="Guestbook" --plan=development

This command does a lot:


• The first time you launch this command, authenticate with your
Platform.sh credentials if not done already.
• It provisions a new project on Platform.sh (you get 30 days for free on
the first project you create).

Then, deploy:
$ symfony cloud:deploy

The code is deployed by pushing the Git repository. At the end of the
command, the project will have a specific domain name you can use to
access it.
Check that everything worked fine:

42
$ symfony cloud:url -1

You should get a 404, but browsing to /images/under-construction.gif


should reveal our work.
Note that you don’t get the beautiful default Symfony page on
Platform.sh. Why? You will learn soon that Symfony supports several
environments and Platform.sh automatically deployed the code in the
production environment.

If you want to delete the project on Platform.sh, use the


cloud:project:delete command.

Going Further
• The repositories for the official Symfony recipes and for the recipes
contributed by the community, where you can submit your own
recipes;
• The Symfony Local Web Server;
• The Platform.sh documentation.

43
Step 4
Adopting a Methodology

Teaching is about repeating the same thing again and again. I won’t do
that. I promise. At the end of each step, you should do a little dance and
save your work. It is like Ctrl+S but for a website.

4.1 Implementing a Git Strategy


At the end of each step, don’t forget to commit your changes:
$ git add .
$ git commit -m'Add some new feature'

You can safely add “everything” as Symfony manages a .gitignore file for
you. And each package can add more configuration. Have a look at the
current content:

.gitignore
###> symfony/framework-bundle ###
/.env.local
/.env.local.php

45
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
###< symfony/framework-bundle ###

The funny strings are markers added by Symfony Flex so that it knows
what to remove if you decide to uninstall a dependency. I told you, all the
tedious work is done by Symfony, not you.
It could be nice to push your repository to a server somewhere. GitHub,
GitLab, or Bitbucket are good choices.

If you are deploying on Platform.sh, you already have a copy of the


Git repository as Platform.sh uses Git behind the scenes when you are
using cloud:deploy. But you should not rely on the Platform.sh Git
repository. It is only for deployment usage. It is not a backup.

4.2 Deploying to Production Continuously


Another good habit is to deploy frequently. Deploying at the end of each
step is a good pace:
$ symfony cloud:deploy

46
Step 5
Troubleshooting Problems

Setting up a project is also about having the right tools to debug


problems. Fortunately, many nice helpers are already included as part of
the webapp package.

5.1 Discovering the Symfony Debugging Tools


To begin with, the Symfony Profiler is a time saver when you need to find
the root cause of a problem.
If you have a look at the homepage, you should see a toolbar at the
bottom of the screen:

47
••• /

The first thing you might notice is the 404 in red. Remember that this
page is a placeholder as we have not defined a homepage yet. Even if the
default page that welcomes you is beautiful, it is still an error page. So
the correct HTTP status code is 404, not 200. Thanks to the web debug
toolbar, you have the information right away.
If you click on the small exclamation point, you get the “real” exception
message as part of the logs in the Symfony profiler. If you want to see the
stack trace, click on the “Exception” link on the left menu.
Whenever there is an issue with your code, you will see an exception page
like the following that gives you everything you need to understand the
issue and where it comes from:

48
••• //

Take some time to explore the information inside the Symfony profiler by
clicking around.
Logs are also quite useful in debugging sessions. Symfony has a
convenient command to tail all the logs (from the web server, PHP, and
your application):
$ symfony server:log

Let’s do a small experiment. Open public/index.php and break the PHP


code there (add foobar in the middle of the code for instance). Refresh the
page in the browser and observe the log stream:
Dec 21 10:04:59 |DEBUG| PHP PHP Parse error: syntax error, unexpected 'use'
(T_USE) in public/index.php on line 5 path="/usr/bin/php7.42" php="7.42.0"
Dec 21 10:04:59 |ERROR| SERVER GET (500) / ip="127.0.0.1"

The output is beautifully colored to get your attention on errors.

5.2 Understanding Symfony Environments


As the Symfony Profiler is only useful during development, we want to
avoid it being installed in production. By default, Symfony automatically
installed it only for the dev and test environments.
Symfony supports the notion of environments. By default, it has built-in

49
support for three, but you can add as many as you like: dev, prod, and
test. All environments share the same code, but they represent different
configurations.
For instance, all debugging tools are enabled in the dev environment. In
the prod one, the application is optimized for performance.
Switching from one environment to another can be done by changing the
APP_ENV environment variable.
When you deployed to Platform.sh, the environment (stored in APP_ENV)
was automatically switched to prod.

5.3 Managing Environment Configurations


APP_ENV can be set by using “real” environment variables in your terminal:

$ export APP_ENV=dev

Using real environment variables is the preferred way to set values like
APP_ENV on production servers. But on development machines, having to
define many environment variables can be cumbersome. Instead, define
them in a .env file.
A sensible .env file was generated automatically for you when the project
was created:

.env
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=c2927f273163f7225a358e3a1bbbed8a
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
#TRUSTED_HOSTS='^localhost|example\.com$'
###< symfony/framework-bundle ###

Any package can add more environment variables to this file thanks to
their recipe used by Symfony Flex.

The .env file is committed to the repository and describes the default
values from production. You can override these values by creating a

50
Random documents with unrelated
content Scribd suggests to you:
Long therefore, may English men and women play together, since
thereby they will know one another, respect one another and help
one another more thoroughly.
CHAPTER XII
THE ENGLISHWOMAN IN PARLIAMENT

On December 1st, 1919, in London deep darkness covered the


land. A dull morning gave place to a mid-day of Stygian gloom, and
the members of the House of Commons, as they ate their lunch,
looked out on to an inky stream reflecting an inky sky. Had the
citizens of London been intellectually as benighted as they were
atmospherically, they might have run to bow themselves in frenzy
before the images of Gog and Magog, beseeching them, amid the
smoke of sacrifice, to turn away their wrath. And had some wily and
reactionary priest of these divinities arisen to harangue the people,
saying: "Brethren, wherefore do you beat your breasts and offer
sacrifices rather than seek out the cause of your offence? The gods
indeed are wroth, seeing that ye set at nought the divine laws. Even
now at Westminster the unlawful thing is being done: the distinction
which they in their wisdom have set between man and woman is
being impiously flouted. For this the gods frown, for this the sun’s
light is put out, giving promise of greater evils to come"—if he had
said such words as these, a crowd of primitive citizens might have
rushed from the city to Westminster and prevented, had they been
strong enough, the reception of a woman into the assembly of the
people.
As it was, no such thing happened. The atmospheric gloom was
accepted philosophically as evidence of a deep depression, not on
the part of the gods, but of the barometer in the Atlantic, a peaceful
crowd gathered in Whitehall to witness what the evening papers
would describe as “the scenes” at Westminster, and the Members of
the House of Commons finished their lunches and asked their
questions undisturbed. Even though the attendance in the House
was large, to an unprejudiced observer in the gallery what occurred
seemed, as I have been told, quite ordinary. It was almost
impossible, at the moment when Mr Lloyd George and Mr Balfour—
after a false start—walked to the table with Lady Astor in their midst,
to focus the mind upon the revolution in thought and feeling which
this event, divided by so few years from that distressing siege of St
Stephen’s by wild and dishevelled women, really represented. The
first lady member took her seat, and it appeared the most natural
thing in the world, particularly as she had so cleverly devised her
parliamentary costume as to blend completely with the hundreds of
dark coats and white collars that surrounded her. Had she arrived in
a “confection,” the contrast, the new element, would have been
immeasurably accentuated.
The contrast, the new element, was there, however, though not
where people were looking for it. It was faint, almost imperceptible,
fleeting as a thought: yet, to the mind of my philosophic informant,
it stood for more than the previous old-fashioned ceremony. After
her formal introduction, the new member passed round the division
lobby to the door of the House opposite the Speaker. My
parliamentary philosopher, coming down at this moment from the
gallery, was met, all suddenly, by the new thing for which he had
vainly looked five minutes earlier. The new element, or rather its
symbol, was there in that lobby, but so attenuated that at first it
eluded description; but the philosopher’s nose followed its clue as
surely as the First Secretary’s in the last act of “Diplomacy.” It was
the faintest breath of a perfume, just the thinnest ghost of a delicate
scent, but a scent quite beyond the inspiration of a masculine
barber. Thus the air of the division lobby, which, sucked as it is from
the river, had borne many strange odours wafted from passing
barges, knew an element to which, of all the lobbies, this innermost
one had ever been a stranger. This was the symbol which truly
represented the revolution, though on its actual physical essence he
laid no stress: it may have been a sheer illusion. The ceremony of
“taking her seat” was only an old formula applied without alteration
to a new phenomenon: this elusive breath was the symbol of a new
thing applied to an old institution.
From this symbol I take my point of departure in this chapter. The
newspapers spent at the time much space and ingenuity in
commenting on chance incongruities which might arise if the old
rules of parliamentary procedure were applied rigidly to a woman
member: this was amusing matter enough for gossip, but of no
importance. The only question of interest is in what really consists
the novelty at Westminster and in all the political life of our country
which has been begun by the presence of a woman on the green
benches. It is not, in the narrow sense, a political novelty, but
something far wider which affects, or may affect, all English men
and women.
There are women who seem now as anxious to obscure the fact of
the novelty as they were to bring it to pass. If I might believe a lady
novelist with whom I discussed the matter not long ago, the thing to
rejoice over is that Lady Astor was adopted and elected as an
ordinary party candidate, not primarily as a woman, as a nominee of
some women’s party or as champion of some women’s programme.
On this view, as I understand it, the winning of full political rights for
women, having removed the greatest and most unfair of all the
differentiations between the two sexes, leaves them now blended
into one both as electors and potential candidates, as if this were a
possible, natural or desirable consummation. It is, of course, a quite
intelligible point of view, when the mass of stupidity against which it
is a protest is considered. Women have suffered so much from the
fact of their sex—though they have been inclined to underestimate
its privileges and its powers even in the unregenerate days—that
they may be excused if the last thing that they wish is to insist on it
in the field of politics. Nobody can blame Englishwomen for wishing
to come into the arena, as far as possible, unprejudiced, and to be
regarded just as citizens, and not, in any sense, as freaks. Obviously,
too, it would be impolitic on their part, at the first moment of the
innovation, before they have found themselves or gained experience
in the new sphere of action, to lay any stress on any kind of
antagonism which might exist between them and the sex which has
hitherto been in exclusive possession of that sphere. They would
rather slip in unobtrusively in their dark coats and skirts and white
collars, as not too conspicuous political animals, evading reporters
and writers of paragraphs, making no parade of their special
feminine experience, but trusting to opportunity to use it; making,
also, no special appeal that a man could not equally make, until the
novelty has so worn off that their candidature and their election shall
become too common to provoke comment.
Let them do so by all means, but that elusive symbol in the
division lobby cannot be ignored. Their idea, so long as it is
protective of their best interests is legitimate: it will be impossible for
them to take their proper share in politics so long as they are
regarded as freaks, and, whether or no a time will ever come when
a women’s party must of necessity arise, it would be foolish now to
forestall necessity. A party crystallises common ideals, which, at this
moment, the women of England have not got either by tradition or
conviction. Yet the fact remains that women are women, and not
men. Is it right, is it even possible, that this should be ignored or
disregarded in politics, when it is patent,—usefully, inexorably, so—in
all other social activities? With all respect to ladies who take another
view, I submit that it is neither possible nor desirable: perhaps I may
persuade them that my view, where it is not supported by plain
facts, is not a fruit of masculine prejudice and does not aim at
nullifying the good of their well-earned enfranchisement, but is really
a greater tribute to the value of their appearance in politics than
they seem ready to pay themselves.
In all probability, men being more active, more politically
ambitious and more in a position by their public activities to gain
suffrages than women, the proportion of women to men among
members of Parliament will always be small. For this very reason it
seems important that this small proportion should get the best out of
itself, which it will not do by disregarding its sex. Perhaps it is not
the sex so much that matters as the special experience and outlook
which are incidental to it. The woman’s point of view may not always
be the most just or the most comprehensive, but it will always be
valuable when clearly stated. A woman, even from her earliest years,
learns to penetrate into recesses of life which defy the penetration of
the less supple man: she sees into other minds from a different
angle and, where the minds are women’s, from a much more
advantageous one. In the ordinary course of life in England the
woman’s path begins to diverge from the man’s immediately the
confines of babyhood are passed, and, though women will be right
to annex for themselves anything that is valuable in masculine
upbringing and to press for complete equality of opportunity with
men, it is hardly possible that the two paths will ever coincide. It is
scarcely conceivable that the mind of a woman should ever take on
so completely masculine a form that she will not, by feminine
contacts and sympathies, have gathered some experiences beyond
the reach of a man. I cannot see why political should differ from
social life in this respect. Each of a normal married couple brings
some special contribution to the common household: every sensible
man leaves some things to his wife as she leaves others to him: and
though members of Parliament cannot so absolutely divide the range
of their activities, there is no reason why any special qualifications
should be left in the cloakroom because they were not specifically
included in the issue of a particular election. We want the woman’s
point of view in politics, for men will be saved from many grave
mistakes by the knowledge of it. That it should always be paramount
is not to be expected, but, seeing the English talent for compromise,
its recognition would not fail to affect the consideration of any
question which brought it forth. The whole of our social life is now
undergoing a profound process of modification: it is not easy to
realise the depth of this process as it goes on its slow, uneven
course from day to day. Now, if ever, there is a great part for women
to play as women, not only as members of a political party: women
should be watching, advising, and taking an interest, so that the
result of the process may be as successful as the best wills and
minds of this country can make it.
Therefore, women as electors should be as little deterred from
expressing their own point of view as women members. They need
not found a women’s party to do this. They have only to take
advantage of their voting power and to make it a real force in every
constituency. They will not do this in a moment, for the
Englishwoman is more apathetic politically even than the man, and
her opinion less educated. She will have to learn to scrutinise public
questions as carefully as she does domestic ones and to make her
conclusions heard as clearly out of the home as in it. The addition of
so many million women to the parliamentary register should be
something more than the addition of so many million electors. It is
not an unmixed blessing, for women have their special faults as well
as men, but these faults can be compensated for if the valuable
qualities of women are also put into the scale. If Englishwomen are
to have political power, it is well that they should learn how to use it,
and if women members are a valuable leaven at Westminster, the
quantity of that leaven depends largely upon the women electors.
We need not be too afraid, I think, that political activity of this kind
would bring about a regrettable conflict between the sexes. One
might as well be asked to believe that husband and wife inevitably
come into regrettable conflict over the colour of the drawing room
carpet or the best place for the summer holiday. Here, though there
may be a difference of opinion, discussion usually throws up a
satisfactory solution which does justice to two different, but not in
the least antagonistic, interests. In the larger political life of the
nation the same happy solution may be as confidently expected,
even if, in rare cases, the argument reaches the emotional acuteness
of a domestic “scene.” In normal households “scenes,” if they occur,
clear the air; a few tears and a few hard words are better than the
silence of apathy: there seems no reason why the analogy should
not hold collectively. Hope for the best in this matter is all the more
justified in that Englishwomen are by nature peculiarly loyal to their
men: they are far more apt to refrain out of motherliness from
opposing them than to thwart them out of perversity, and more
ready to propitiate their Bills and Toms when they come home tired
from work than to expect a similar attention on their part. If the
privilege of the franchise was conferred on women as a recognition,
the privilege implies duties also, especially the duty of rendering the
privilege valuable to the State. The degree to which Englishwomen,
as political beings, cultivate a tactful independence will be the
measure of the value which they are extracting from the privilege.
Besides, women in public life will protect themselves far more
successfully against the gapes of idle curiosity by developing a large
bulk of political capacity than by trying to merge themselves
inconspicuously, but ignominiously, with the men.
In any case, whether they are convinced or not, they will not
succeed in what lawyers might call the “merger” of the two sexes.
My symbol of the division lobby here tickles the brain conclusively: it
may stand, to the philosopher, for all the emotional current which
runs as inevitably between the two sexes as electricity between the
two poles of a magnet. The granting of full political rights to women
has truly introduced a new element into politics which even the most
heartfelt wish cannot possibly conjure away. This element is the
appeal of woman to man and man to woman which in every degree,
from starkest crudity to most refined subtlety, is present in all human
relations of the two sexes. That force of attraction, on which Henry
Adams so brilliantly and whimsically reflected, is part of that
persistent “nature” which the most assiduous application of the
pitchfork will never drive out. A constituency is but a collection of
human beings who bring to all their preoccupations, politics
included, the mental and moral habits which they have acquired,
and members of Parliament, as an observer at Westminster has
infinite opportunity of noticing, are human beings with all the holes
in their logical armour and all the susceptibility to moral influence
and emotional suggestion which is a quality of the species however
civilised. Until they argue by mathematical symbols, pure thinking in
their debates will always be diluted by other influences. If the
influence of women be added, this cannot fail to have its effect. Why
should anyone expect it to be otherwise? Politics cannot be
separated artificially from the rest of life even by the most sedulous
endeavour. Political and social elements in existence are inextricably
mingled. Queen Elizabeth was an effective ruler, but she showed
herself a woman too; the great Empress Catherine and Maria
Theresa did not act politically by the dry light of reason alone; and
who can deny the influence of the current which runs between man
and woman in the political dealings of Queen Victoria, especially with
Lords Melbourne and Beaconsfield? If these great women could not
avoid the influence, it is hardly to be expected that women
politicians and the men with whom they deal politically will avoid it
more successfully.
The inevitable introduction, or accentuation in a sphere where it
had hitherto been less marked, of this new element was the one
consideration on which a fair-minded man might have seriously
pondered before making up his mind on the question of votes for
women. No professions or good intentions on women’s part could
conjure it away, and it was to be admitted that it would make for evil
as well as for good. The mutual influence of the sexes may produce
the highest devotion and the loftiest endeavour. Men and women will
do for one another, both individually and in the mass, greater and
finer things than they will do for their own sex alone: they can
appeal to each other’s highest feelings. On the other hand, they can
appeal to the lowest feelings, and the flow of the current, either by
attraction or repulsion, can easily work in such a way as to cause
distraction rather than concentration, irrelevancy rather than logical
conclusion. It might well have seemed, on dispassionate reflection,
that there was already irrelevancy enough in the political life of
England. Appeals to prejudice or mere personalities were common
enough without increasing the strength and range of their appeal.
With every recognition of the logic of the women’s claim, there
remained the fear that the woman’s tendency to take an intensely
personal view of questions, her ready affection by emotional side-
issues, the sway which personal antipathies and repulsions exercise,
almost unconsciously, over her mind, and the quite notorious
unscrupulousness with which she will use every possible feminine
appeal to gain over a man against his better judgment, might be as
unfortunate as the influence of her higher qualities would be
valuable. The march of events and of political thought triumphantly
overbore objections of this kind: they could not possibly stem the
tide of great historic necessity. But this tide has not swept facts
away: what was true in such objections remains true still, nor will
retorts on the nature of corresponding masculine failings destroy
them. Men, let it be admitted, are as frail in their way as women,
and then let it be recognised that the influence against which they
are most frail has burst into a region where they were comparatively
exempt from it. There is no disrespect, I feel sure, in reminding
Englishwomen, who are not at all averse from criticising other
members of their sex, of these things. Those of them who recognise
the dangers will have the opportunity of guarding against them by
educating the ignorant. It will be for them, the political leaders of
the women, to see that women’s influence is used to clarify, not to
obscure, judgment, to deprecate the undue intrusion of personal
emotions, and to broaden the range of the woman’s political views
beyond her own immediate environment. The power which they hold
in their hands is enormous: they have not yet learned to use it fully,
but they cannot divest themselves of it. The political future of
England depends largely on the manner in which they handle it.
There is now a lady members’ room in the Palace of Westminster,
which at present has only one occupant. When it has many—and the
time may not be long distant—will it not be a dynamo for the
storage of the feminine current? Its very existence cuts for the first
time across the purely political differences of members within the
precincts of the House, typifying a distinction never before drawn
between one member and another—that of sex. Its effects may not
be immediate and resounding, but there are dormant possibilities
there which it would be absurd to overlook, possibilities of a new
energy let loose, of drama, even of romance. The collective
consciousness of the House or of a committee is extremely
susceptible to emotional appeal: it is easily exasperated, readily
smoothed by tact, quickly moved to laughter. It would hardly be
impervious to an appeal, even tacit, to its chivalry. If a man with a
fine appearance and a good voice immediately prepossesses such an
audience in his favour, may we not imagine the case of a beautiful
woman with a melodious voice rising, let us say, from the Treasury
or the front Opposition bench to plead a cause with passion? A
crowded House is an effective background for a speaker from such a
position: a woman, with her sex’s unerring eye for effective pose,
would make full use of it. Would she not project from her whole
personality a force infinitely exceeding that of her mere words and
arguments, a force of which no man would be capable, given a
similar audience? There might be a radiance, a pathos—suppose she
ventured a telling sob—an enthusiasm which, though absent from
the pages of the morrow’s Hansard, might tell strongly enough upon
the night’s division. At ordinary times, it is true, party prepossessions
and party whips, as well as logical convictions, are sufficient
safeguards against the effect of irrelevant appeal: but, when the
point is critical, opinions evenly divided, feeling high, or a
government shaking, the smallest thing may turn the scale. The
appeal of a woman to men, used consciously or unconsciously, at
such a time would not be a small thing. It might be so momentary
as to vanish from the ken of history, but it might be decisive. The
requisite combination of circumstances may be long in making its
appearance, but no one can deny its possibility. The oratorical power
of a Fox, a Pitt and a Burke are remembered even now, when their
personalities have vanished and the effect of their very words is no
longer overpowering. If their emotional mastery over a gathering of
men was so great as to outlive their bodies for over a century, surely
the history of future centuries may have to tell of women whose
mastery was transcendent, of some female Pitt, who led a
Parliament, or some new Joan of Arc, who led a nation.
Englishwomen and Englishmen may well ponder all that the future
may bring out of that lady members’ room with its now solitary
occupant. For good and for ill there is a new force at Westminster
which, like all new forces, looks innocent enough at the experimental
stage, but may yet contain the energy to revolutionise a world.

FOOTNOTES:
1 See The Education of Henry Adams, p. 442
2 Even M. Marcel Proust’s remarkable picture of modern
“jeunes filles” in his masterpiece of discursion “A l’ombre des
jeunes filles en fleurs” does not convince me that flappers exist in
France.
*** END OF THE PROJECT GUTENBERG EBOOK THE GOOD
ENGLISHWOMAN ***

Updated editions will replace the previous one—the old editions


will be renamed.

Creating the works from print editions not protected by U.S.


copyright law means that no one owns a United States
copyright in these works, so the Foundation (and you!) can copy
and distribute it in the United States without permission and
without paying copyright royalties. Special rules, set forth in the
General Terms of Use part of this license, apply to copying and
distributing Project Gutenberg™ electronic works to protect the
PROJECT GUTENBERG™ concept and trademark. Project
Gutenberg is a registered trademark, and may not be used if
you charge for an eBook, except by following the terms of the
trademark license, including paying royalties for use of the
Project Gutenberg trademark. If you do not charge anything for
copies of this eBook, complying with the trademark license is
very easy. You may use this eBook for nearly any purpose such
as creation of derivative works, reports, performances and
research. Project Gutenberg eBooks may be modified and
printed and given away—you may do practically ANYTHING in
the United States with eBooks not protected by U.S. copyright
law. Redistribution is subject to the trademark license, especially
commercial redistribution.

START: FULL LICENSE


THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the


free distribution of electronic works, by using or distributing this
work (or any other work associated in any way with the phrase
“Project Gutenberg”), you agree to comply with all the terms of
the Full Project Gutenberg™ License available with this file or
online at www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand,
agree to and accept all the terms of this license and intellectual
property (trademark/copyright) agreement. If you do not agree
to abide by all the terms of this agreement, you must cease
using and return or destroy all copies of Project Gutenberg™
electronic works in your possession. If you paid a fee for
obtaining a copy of or access to a Project Gutenberg™
electronic work and you do not agree to be bound by the terms
of this agreement, you may obtain a refund from the person or
entity to whom you paid the fee as set forth in paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only


be used on or associated in any way with an electronic work by
people who agree to be bound by the terms of this agreement.
There are a few things that you can do with most Project
Gutenberg™ electronic works even without complying with the
full terms of this agreement. See paragraph 1.C below. There
are a lot of things you can do with Project Gutenberg™
electronic works if you follow the terms of this agreement and
help preserve free future access to Project Gutenberg™
electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright
law in the United States and you are located in the United
States, we do not claim a right to prevent you from copying,
distributing, performing, displaying or creating derivative works
based on the work as long as all references to Project
Gutenberg are removed. Of course, we hope that you will
support the Project Gutenberg™ mission of promoting free
access to electronic works by freely sharing Project Gutenberg™
works in compliance with the terms of this agreement for
keeping the Project Gutenberg™ name associated with the
work. You can easily comply with the terms of this agreement
by keeping this work in the same format with its attached full
Project Gutenberg™ License when you share it without charge
with others.

1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside
the United States, check the laws of your country in addition to
the terms of this agreement before downloading, copying,
displaying, performing, distributing or creating derivative works
based on this work or any other Project Gutenberg™ work. The
Foundation makes no representations concerning the copyright
status of any work in any country other than the United States.

1.E. Unless you have removed all references to Project


Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project
Gutenberg™ work (any work on which the phrase “Project
Gutenberg” appears, or with which the phrase “Project
Gutenberg” is associated) is accessed, displayed, performed,
viewed, copied or distributed:

This eBook is for the use of anyone anywhere in the United


States and most other parts of the world at no cost and
with almost no restrictions whatsoever. You may copy it,
give it away or re-use it under the terms of the Project
Gutenberg License included with this eBook or online at
www.gutenberg.org. If you are not located in the United
States, you will have to check the laws of the country
where you are located before using this eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is


derived from texts not protected by U.S. copyright law (does not
contain a notice indicating that it is posted with permission of
the copyright holder), the work can be copied and distributed to
anyone in the United States without paying any fees or charges.
If you are redistributing or providing access to a work with the
phrase “Project Gutenberg” associated with or appearing on the
work, you must comply either with the requirements of
paragraphs 1.E.1 through 1.E.7 or obtain permission for the use
of the work and the Project Gutenberg™ trademark as set forth
in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is


posted with the permission of the copyright holder, your use and
distribution must comply with both paragraphs 1.E.1 through
1.E.7 and any additional terms imposed by the copyright holder.
Additional terms will be linked to the Project Gutenberg™
License for all works posted with the permission of the copyright
holder found at the beginning of this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files
containing a part of this work or any other work associated with
Project Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute


this electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the
Project Gutenberg™ License.

1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if
you provide access to or distribute copies of a Project
Gutenberg™ work in a format other than “Plain Vanilla ASCII” or
other format used in the official version posted on the official
Project Gutenberg™ website (www.gutenberg.org), you must,
at no additional cost, fee or expense to the user, provide a copy,
a means of exporting a copy, or a means of obtaining a copy
upon request, of the work in its original “Plain Vanilla ASCII” or
other form. Any alternate format must include the full Project
Gutenberg™ License as specified in paragraph 1.E.1.

1.E.7. Do not charge a fee for access to, viewing, displaying,


performing, copying or distributing any Project Gutenberg™
works unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or


providing access to or distributing Project Gutenberg™
electronic works provided that:

• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”

• You provide a full refund of any money paid by a user who


notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.

• You provide, in accordance with paragraph 1.F.3, a full refund of


any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.

• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project


Gutenberg™ electronic work or group of works on different
terms than are set forth in this agreement, you must obtain
permission in writing from the Project Gutenberg Literary
Archive Foundation, the manager of the Project Gutenberg™
trademark. Contact the Foundation as set forth in Section 3
below.

1.F.

1.F.1. Project Gutenberg volunteers and employees expend


considerable effort to identify, do copyright research on,
transcribe and proofread works not protected by U.S. copyright
law in creating the Project Gutenberg™ collection. Despite these
efforts, Project Gutenberg™ electronic works, and the medium
on which they may be stored, may contain “Defects,” such as,
but not limited to, incomplete, inaccurate or corrupt data,
transcription errors, a copyright or other intellectual property
infringement, a defective or damaged disk or other medium, a
computer virus, or computer codes that damage or cannot be
read by your equipment.

1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except


for the “Right of Replacement or Refund” described in
paragraph 1.F.3, the Project Gutenberg Literary Archive
Foundation, the owner of the Project Gutenberg™ trademark,
and any other party distributing a Project Gutenberg™ electronic
work under this agreement, disclaim all liability to you for
damages, costs and expenses, including legal fees. YOU AGREE
THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT
EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE
THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY
DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE
TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL,
PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE
NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.

1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you


discover a defect in this electronic work within 90 days of
receiving it, you can receive a refund of the money (if any) you
paid for it by sending a written explanation to the person you
received the work from. If you received the work on a physical
medium, you must return the medium with your written
explanation. The person or entity that provided you with the
defective work may elect to provide a replacement copy in lieu
of a refund. If you received the work electronically, the person
or entity providing it to you may choose to give you a second
opportunity to receive the work electronically in lieu of a refund.
If the second copy is also defective, you may demand a refund
in writing without further opportunities to fix the problem.

1.F.4. Except for the limited right of replacement or refund set


forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’,
WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.

1.F.5. Some states do not allow disclaimers of certain implied


warranties or the exclusion or limitation of certain types of
damages. If any disclaimer or limitation set forth in this
agreement violates the law of the state applicable to this
agreement, the agreement shall be interpreted to make the
maximum disclaimer or limitation permitted by the applicable
state law. The invalidity or unenforceability of any provision of
this agreement shall not void the remaining provisions.

1.F.6. INDEMNITY - You agree to indemnify and hold the


Foundation, the trademark owner, any agent or employee of the
Foundation, anyone providing copies of Project Gutenberg™
electronic works in accordance with this agreement, and any
volunteers associated with the production, promotion and
distribution of Project Gutenberg™ electronic works, harmless
from all liability, costs and expenses, including legal fees, that
arise directly or indirectly from any of the following which you
do or cause to occur: (a) distribution of this or any Project
Gutenberg™ work, (b) alteration, modification, or additions or
deletions to any Project Gutenberg™ work, and (c) any Defect
you cause.

Section 2. Information about the Mission


of Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new
computers. It exists because of the efforts of hundreds of
volunteers and donations from people in all walks of life.

Volunteers and financial support to provide volunteers with the


assistance they need are critical to reaching Project
Gutenberg™’s goals and ensuring that the Project Gutenberg™
collection will remain freely available for generations to come. In
2001, the Project Gutenberg Literary Archive Foundation was
created to provide a secure and permanent future for Project
Gutenberg™ and future generations. To learn more about the
Project Gutenberg Literary Archive Foundation and how your
efforts and donations can help, see Sections 3 and 4 and the
Foundation information page at www.gutenberg.org.

Section 3. Information about the Project


Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-
profit 501(c)(3) educational corporation organized under the
laws of the state of Mississippi and granted tax exempt status
by the Internal Revenue Service. The Foundation’s EIN or
federal tax identification number is 64-6221541. Contributions
to the Project Gutenberg Literary Archive Foundation are tax
deductible to the full extent permitted by U.S. federal laws and
your state’s laws.

The Foundation’s business office is located at 809 North 1500


West, Salt Lake City, UT 84116, (801) 596-1887. Email contact
links and up to date contact information can be found at the
Foundation’s website and official page at
www.gutenberg.org/contact
Section 4. Information about Donations to
the Project Gutenberg Literary Archive
Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission
of increasing the number of public domain and licensed works
that can be freely distributed in machine-readable form
accessible by the widest array of equipment including outdated
equipment. Many small donations ($1 to $5,000) are particularly
important to maintaining tax exempt status with the IRS.

The Foundation is committed to complying with the laws


regulating charities and charitable donations in all 50 states of
the United States. Compliance requirements are not uniform
and it takes a considerable effort, much paperwork and many
fees to meet and keep up with these requirements. We do not
solicit donations in locations where we have not received written
confirmation of compliance. To SEND DONATIONS or determine
the status of compliance for any particular state visit
www.gutenberg.org/donate.

While we cannot and do not solicit contributions from states


where we have not met the solicitation requirements, we know
of no prohibition against accepting unsolicited donations from
donors in such states who approach us with offers to donate.

International donations are gratefully accepted, but we cannot


make any statements concerning tax treatment of donations
received from outside the United States. U.S. laws alone swamp
our small staff.

Please check the Project Gutenberg web pages for current


donation methods and addresses. Donations are accepted in a
number of other ways including checks, online payments and
credit card donations. To donate, please visit:
www.gutenberg.org/donate.

Section 5. General Information About


Project Gutenberg™ electronic works
Professor Michael S. Hart was the originator of the Project
Gutenberg™ concept of a library of electronic works that could
be freely shared with anyone. For forty years, he produced and
distributed Project Gutenberg™ eBooks with only a loose
network of volunteer support.

Project Gutenberg™ eBooks are often created from several


printed editions, all of which are confirmed as not protected by
copyright in the U.S. unless a copyright notice is included. Thus,
we do not necessarily keep eBooks in compliance with any
particular paper edition.

Most people start at our website which has the main PG search
facility: www.gutenberg.org.

This website includes information about Project Gutenberg™,


including how to make donations to the Project Gutenberg
Literary Archive Foundation, how to help produce our new
eBooks, and how to subscribe to our email newsletter to hear
about new eBooks.
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy