Categories
Software Development Web Development

Symfony 5+ how to create a Maker

The docs do not mention how to create your own maker bundle. It gives a link to some of the Github code of the existing maker bundles for you to view as an example.

you need to figure it out meme
Here is a link, you figure it out. LOL

So when I dug deeper into the subject, I figured out what you are actually doing with a maker is creating a console app. You will know these “Makers” from typing commands on the command line like the following:

php bin/console cache:clear  or 
php bin/console list make

So step 1 is to create a new class in a directory in your “src” directory. I call mine… “Makers”

Then inside your class you need to add some use statements for the classes you intend to use like so.


use Symfony\Bundle\MakerBundle\ConsoleStyle;
use Symfony\Bundle\MakerBundle\DependencyBuilder;
use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\InputConfiguration;
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
use Symfony\Bundle\MakerBundle\Validator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;

Here is a link to the Console classes so you can find out what is available.
For the other classes you see e.g. “Symfony\Bundle\MakerBundle\ConsoleStyle  It appears these are located in “maker-bundle/src/class-name/ now. Here is a link to the related classes source code.

Once you have decided what classes you will need, via trial and error based on your project idea, you next need to extend the AbstractMaker interface and add the methods like this.

Below is an example of a maker that extracts table information from a database and creates classes with it. I use these classes for creating custom queries. It is easier than remembering all the fields of a table and what values they can contain etc. The only downside is when changes to a table are made and the column name you used no longer exists, you have to find it in your code. But a good IDE will help you find this. I might add this code to a repo or maybe Symfony one day. This is useful for writing custom queries where you need to know the column names and types etc. You can use this with Doctrine CRUD classes or your own etc.

I made notes on what I think the methods do since there is absolutely 0 documentation that I can find.


<?php


namespace App\Maker;


use App\DbUtils\MysqlConnection;
use App\Schema\SchemaMaker;
use Symfony\Bundle\MakerBundle\ConsoleStyle;
use Symfony\Bundle\MakerBundle\DependencyBuilder;
use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\InputConfiguration;
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
use Symfony\Bundle\MakerBundle\Validator;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;

class TableMetaMaker extends AbstractMaker
{

    /**
     * Return the command name for your maker (e.g. make:report).
     */
    public static function getCommandName(): string
    {
        return 'make:table-meta';
    }

    /**
     * Configure the command: set description, input arguments, options, etc.
     *
     * By default, all arguments will be asked interactively. If you want
     * to avoid that, use the §inputConfig->setArgumentAsNonInteractive() method.
     * @param Command §command
     * @param InputConfiguration §inputConfig
     */
    public function configureCommand(Command §command, InputConfiguration §inputConfig)
    {
        §command->setDescription('Creates classes with table data')
            ->addArgument('schema', InputArgument::REQUIRED, sprintf('The name of database schema to model '));
    }

    /**
     * Configure any library dependencies that your maker requires.
     * @param DependencyBuilder §dependencies
     */
    public function configureDependencies(DependencyBuilder §dependencies)
    {
        // TODO: Implement configureDependencies() method.
    }

    /**
     * Called after normal code generation: allows you to do anything.
     * @param InputInterface §input
     * @param ConsoleStyle §io
     * @param Generator §generator
     */
    public function generate(InputInterface §input, ConsoleStyle §io, Generator §generator)
    {
        §schema = §input->getArgument('schema');
        §io->success("Now generating Table classes for schema " . §schema);
        §userName = §_SERVER['DATABASE_USER'];
        §pass = §_SERVER['DATABASE_PASSWORD'];

        §mysql = new MysqlConnection(§userName,§pass, §schema);
        §schemaMaker = new SchemaMaker(§mysql,§schema);
        §schemaMaker->setSchemaTableList();
        §schemaMaker->createAllSchemaClasses();

        foreach (§schemaMaker->getTablesList() as §table){
            §io->success("Created Class for table " . implode('-', §table));
        }

    }

    public function interact(InputInterface §input, ConsoleStyle §io, Command §command)
    {
        §io->title('Create the database table classes...');
        §value = '';

        if (null === §input->getArgument('schema')) {
            §argument = §command->getDefinition()->getArgument('schema');
            §question = new Question(§argument->getDescription());
            §value = §io->askQuestion(§question);
            §input->setArgument('schema', §value);

        }
        §value = §input->getArgument('schema');
        §io->success("Table classes were made from schema " . §value);

        /*§input->setArgument('schema', §io->ask(
            'What is the name of the database schema',
            null,
            [Validator::class, 'notBlank']
        )
        );*/
    }
}

As you can see there are some custom classes I am using too. I don’t have the time right now to cleanup and publish all the code. Maybe one day though. I have several other Makers I use. One clones Entities, another creates Repositories based on Entities. Those two I may publish sooner as they are the most useful and would require the least effort to share.

Since all you are doing with a Maker is creating a console app. I’d recommend reading all the links below about that. When you extend

AbstractMaker

Here is an absolute basic class with the basic methods you must have for your maker to work.


<?php

namespace App\Maker;

use Symfony\Bundle\MakerBundle\ConsoleStyle;
use Symfony\Bundle\MakerBundle\DependencyBuilder;
use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\InputConfiguration;
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;

/**
 * @method string getCommandDescription()
 */
class TestMaker extends AbstractMaker
{

    public static function getCommandName(): string
    {
        // TODO: Implement getCommandName() method.
    }

    public function configureCommand(Command $command, InputConfiguration $inputConfig)
    {
        // TODO: Implement configureCommand() method.
    }

    public function configureDependencies(DependencyBuilder $dependencies)
    {
        // TODO: Implement configureDependencies() method.
    }

    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
    {
        // TODO: Implement generate() method.
    }

    public function __call($name, $arguments)
    {
        // TODO: Implement @method string getCommandDescription()
    }
}

I don’t work on Symfony core and there is no documentation so I can’t tell you what these methods do. However, you can look at all of the code for the makers and see what is done in them.

I do most of my work in the generate method. For getCommandDescription() method I do this

public static function getCommandDescription(): string
{
    return 'Clones a Doctrine Entity class.';
}

Additional info and links

I had to google and dig to find this  which explains the console command arguments and options.

Here is another link to the docs for the console commands you can use with Makers.

Here is yet another link to more information about the console and how to use it. This is to the console component itself. This link has most of the other helpful console related links to the bottom of the article. There looks to be about 20 links at this time. These are the most helpful links so I won’t repost every one of them here.

Here is yet another link about the console arguments and options.

And here is a link that explains the QuestionHelper class you use to ask questions.

Here is a link explaining the FormatHelper class used to format console output. This one is useful if you want to print messages in blocks with background colors.  If you want to change the color of the actual text you need to read this.

You can even display a clickable link to the user in the command line.

Categories
Software Development Web Development

Symfony 5+ using the command line and listing commands

Symfony has useful command line commands. But what are the available commands and how do you get a list?

To get started type the following in the command line in your projects main/root folder. This is the directory that contains the directories src,assets, bin, public, node_modules etc.
php bin/console -help
That command will output the following

bin console help
Output of php bin/console -help command

This shows we can use bin/console list and a few more. Now try the command and see what the list shows.


Available commands:
  about                                      Displays information about the current project
  help                                       Displays help for a command
  list                                       Lists commands
 assets
  assets:install                             Installs bundles web assets under a public directory
 cache
  cache:clear                                Clears the cache
  cache:pool:clear                           Clears cache pools
  cache:pool:delete                          Deletes an item from a cache pool
  cache:pool:list                            List available cache pools
  cache:pool:prune                           Prunes cache pools
  cache:warmup                               Warms up an empty cache
 config
  config:dump-reference                      Dumps the default configuration for an extension
 dbal
  dbal:run-sql                               Executes arbitrary SQL directly from the command line.
 debug
  debug:autowiring                           Lists classes/interfaces you can use for autowiring
  debug:config                               Dumps the current configuration for an extension
  debug:container                            Displays current services for an application
  debug:event-dispatcher                     Displays configured listeners for an application
  debug:form                                 Displays form type information
  debug:router                               Displays current routes for an application
  debug:translation                          Displays translation messages information
  debug:twig                                 Shows a list of twig functions, filters, globals and tests
  debug:validator                            Displays validation constraints for classes
 doctrine
  doctrine:cache:clear-collection-region     Clear a second-level cache collection region
  doctrine:cache:clear-entity-region         Clear a second-level cache entity region
  doctrine:cache:clear-metadata              Clears all metadata cache for an entity manager
  doctrine:cache:clear-query                 Clears all query cache for an entity manager
  doctrine:cache:clear-query-region          Clear a second-level cache query region
  doctrine:cache:clear-result                Clears result cache for an entity manager
  doctrine:database:create                   Creates the configured database
  doctrine:database:drop                     Drops the configured database
  doctrine:database:import                   Import SQL file(s) directly to Database.
  doctrine:ensure-production-settings        Verify that Doctrine is properly configured for a production environment
  doctrine:fixtures:load                     Load data fixtures to your database
  doctrine:mapping:convert                   [orm:convert:mapping] Convert mapping information between supported formats
  doctrine:mapping:import                    Imports mapping information from an existing database
  doctrine:mapping:info                      
  doctrine:migrations:current                [current] Outputs the current version
  doctrine:migrations:diff                   [diff] Generate a migration by comparing your current database to your mapping information.
  doctrine:migrations:dump-schema            [dump-schema] Dump the schema for your database to a migration.
  doctrine:migrations:execute                [execute] Execute one or more migration versions up or down manually.
  doctrine:migrations:generate               [generate] Generate a blank migration class.
  doctrine:migrations:latest                 [latest] Outputs the latest version
  doctrine:migrations:list                   [list-migrations] Display a list of all available migrations and their status.
  doctrine:migrations:migrate                [migrate] Execute a migration to a specified version or the latest available version.
  doctrine:migrations:rollup                 [rollup] Rollup migrations by deleting all tracked versions and insert the one version that exists.
  doctrine:migrations:status                 [status] View the status of a set of migrations.
  doctrine:migrations:sync-metadata-storage  [sync-metadata-storage] Ensures that the metadata storage is at the latest version.
  doctrine:migrations:up-to-date             [up-to-date] Tells you if your schema is up-to-date.
  doctrine:migrations:version                [version] Manually add and delete migration versions from the version table.
  doctrine:query:dql                         Executes arbitrary DQL directly from the command line
  doctrine:query:sql                         Executes arbitrary SQL directly from the command line.
  doctrine:schema:create                     Executes (or dumps) the SQL needed to generate the database schema
  doctrine:schema:drop                       Executes (or dumps) the SQL needed to drop the current database schema
  doctrine:schema:update                     Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata
  doctrine:schema:validate                   Validate the mapping files
 fos
  fos:js-routing:debug                       Displays currently exposed routes for an application
  fos:js-routing:dump                        Dumps exposed routes to the filesystem
 lint
  lint:container                             Ensures that arguments injected into services match type declarations
  lint:twig                                  Lints a template and outputs encountered errors
  lint:xliff                                 Lints a XLIFF file and outputs encountered errors
  lint:yaml                                  Lints a file and outputs encountered errors
 make
  make:auth                                  Creates a Guard authenticator of different flavors
  make:command                               Creates a new console command class
  make:controller                            Creates a new controller class
  make:crud                                  Creates CRUD for Doctrine entity class
  make:docker:database                       Adds a database container to your docker-compose.yaml file
  make:entity                                Creates or updates a Doctrine entity class, and optionally an API Platform resource
  make:fixtures                              Creates a new class to load Doctrine fixtures
  make:form                                  Creates a new form class
  make:message                               Creates a new message and handler
  make:messenger-middleware                  Creates a new messenger middleware
  make:migration                             Creates a new migration based on database changes
  make:registration-form                     Creates a new registration form system
  make:reset-password                        Create controller, entity, and repositories for use with symfonycasts/reset-password-bundle
  make:serializer:encoder                    Creates a new serializer encoder class
  make:serializer:normalizer                 Creates a new serializer normalizer class
  make:subscriber                            Creates a new event subscriber class
  make:table-meta                            Creates classes with table data
  make:test                                  [make:unit-test|make:functional-test] Creates a new test class
  make:twig-extension                        Creates a new Twig extension class
  make:user                                  Creates a new security user class
  make:validator                             Creates a new validator and constraint class
  make:voter                                 Creates a new security voter class
 reset-password
  reset-password:remove-expired              Remove expired reset password requests from persistence.
 router
  router:match                               Helps debug routes by simulating a path info match
 secrets
  secrets:decrypt-to-local                   Decrypts all secrets and stores them in the local vault
  secrets:encrypt-from-local                 Encrypts all local secrets to the vault
  secrets:generate-keys                      Generates new encryption keys
  secrets:list                               Lists all secrets
  secrets:remove                             Removes a secret from the vault
  secrets:set                                Sets a secret in the vault security
  security:encode-password                   Encodes a password
  server
  server:dump                                Starts a dump server that collects and displays dumps in a single place
  server:log                                 Starts a log server that displays logs in real time
 translation
  translation:update                         Updates the translation file

Wow that is a lot of commands. Enter the list command in your terminal to get a better view.

mr rodgers how it is done meme
And that is how it is done!!!
Categories
Web Development

How fix doctrine error : You are missing a “cli-config.php” or “config/cli-config.php” file in your project, which is required to get the Doctrine Console working.

So while following this guide in the documentation to try to reverse engineer my database with Doctrine, I got the following 100% absolutely nonsensical error

Importing mapping information from "default" entity manager
 writing src/Entity/AffiliateArticleViews.php
 writing src/Entity/AffiliateJoinCounts.php
 writing src/Entity/AffiliateRegistration.php
 writing src/Entity/BlogMedia.php
 writing src/Entity/CommentReplyConclusionOptions.php
 writing src/Entity/CommentReplyReportReasons.php
 writing src/Entity/DoctrineMigrationVersions.php
 writing src/Entity/FavoredImages.phP

In DebugClassLoader.php line 346:

Warning: include(/var/www/sogi/sogizmo/vendor/composer/../../src/Entity/FavoredImages.php): failed to
open stream: No such file or directory

To someone who doesn’t work on the Symfony core that might as well say “boasdfkajsdfiioaysdfiuasdfiouasdfiouasdiofu”

So I had to research this issue.

Doing Research!!!

Ok so I found this link with a little more info and I ran the following line of code.

php vendor/bin/doctrine orm:generate-entities --help

Which barfed out these lines of more mysteries to be solved.

You are missing a "cli-config.php" or "config/cli-config.php" file in your project, which is required to get the Doctrine Console working. You can use the following sample as a template:

<?php use Doctrine\ORM\Tools\Console\ConsoleRunner; // replace with file to your own project bootstrap require_once 'bootstrap.php'; // replace with mechanism to retrieve EntityManager in your app $entityManager = GetEntityManager(); return ConsoleRunner::createHelperSet($entityManager); </code

Leaving me wondering WTF is this even talking about like…

Who comes up with this?

Google and dig as I may I only found one Stack answer that explained how to created the mess of files required. Sure would be nice if that was in the Doctrine docs…

But I kept digging, trying, failing… and it turns out that the first error I got means…. wait for it…. MY USER DOCTRINE IS RUNNING AS CAN’T WRITE TO THE DIRECTORY.  Now wouldn’t it make much more sense to give that as an error message?

MAKES PERFECT SENSE
MAKES ABSOLUTE PERFECT SENSE

So I changed the Entity directory permissions to 775 since my server www-data was already a member of a group which was the group owner of that directory. And the first command finally worked like it had before. Some how somewhere along the way I set permissions on the Entity and all folders to 755.

The error messages were no help. I just randomly decided to try creating another test folder with 775 and ran the first command again. I accidentally guessed what the problem was from a nonsensical error message. Desperation wins in the problem solving game. LOL

That wasn’t the end though. When I tried to run the second command I got another nonsensical error about my Entity classes already exist. I was like I know the first command created them WTF. Kept googling and searching and scratching my head. Then I remembered I created the test folder so I deleted it and BOOM BANG POW. Everything was working fine.

i m stupid meme
Im is stupid
Categories
Software Development Web Development

How to get URL Routes in your Javascript in Symfony 5+

In the Symfony docs it shows you how to get a URL to your javascript in your template. Basically what this is good for is it gives your Javascript code access to a url that you store in a javascript variable. You would place this at the bottom of your Twig template page, then you can access it with other Javascript code within that script tag area.

Another way to do it is to hide an element with an id in the template then use Javascript to fetch it.

Another way to get the routes is also mentioned in the Symfony Documentation, FosJsRoutingBundle. This allows you to skip the other ways and be able to just get the routes in your Javascript. For example if your frontend is React, Vue etc. or you have a Javascript component that needs to use AJAX to interact with the backend.

The docs say something about app/appKernel.php that file no longer exists.  It has been replaced with just kernel.php and you do pretty much nothing to that file. What you do need to do is make sure that you add this line or it exists, the bundle system should add it.

This goes inside (should be inside) app\config\bundles.php file, you will see a list of the bundles your app is using in this file too.

FOS\JsRoutingBundle\FOSJsRoutingBundle::class => ['all' => true],

I am not sure what version Symfony started this but I know in 5+ you don’t have to register the bundle like step 2 of the old docs shows. This is done automatically for you in a new file named config/bundles.php which is where all bundles are automatically registered when you install them.

So all you do is this command now in the terminal

composer require friendsofsymfony/jsrouting-bundle

inside your apps root level. It is auto registered for you and you will see it listed inside composer.json file too.

You don’t have to do step 3 of the old docs either as the config system has changed. There is no

app/config/routing.yml

file anymore. When you install the bundle the new system creates a new file named app/config/routes/fos_js_routing.yaml for you and the required code is inside. NICE!!!

borat nice meme
Very nice!!!

For step 4 the required code is the same for version 5 as for version 4.

$ php bin/console assets:install --symlink public

Basically to install the bundle you just use the composer command and most of the stuff is now done for you.

Don’t forget to expose routes

expose routes meme
Don’t forget to expose your routes.

In order for the routes to work you must add something new to every single route definition that you want to be able to generate a route for in your Javascript.

You must add this to the annotation or where ever you define your routes. I use annotations so I can just look to the controllers.

options={"expose"=true}

So for my menu route the definition in the controller looks like this.

@Route("/menu", name="menu", options={"expose"=true}, methods={"GET"})
</code.

Now how to use it?

yoda use the routes meme
Use the routes Luke.

So now that it is installed how do you use it? One more step. Now you must include the needed Javascript in your page with these tags. If you are not using Webpack with Symfony you can use these lines.

<script src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
<script src="{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}"></script>

Place those anywhere you want.

If you are using Webpack with Symfony these lines are easier. Place these at the top of the file where you need to access routes.

const routes = require('../../public/js/fos_js_routes.json');
import Routing from '../../vendor/friendsofsymfony/jsrouting-bundle/Resources/public/js/router.min.js';

What I did is put them in my base twig template in a section where I include my Javascript this way it is available on every page because I will probably be needing access to routes as I build the app.

If you don’t know, if you are using webpack then there will be an app.js file in your app\assets\js\app.js

Learn how to install webpack here in the Symfony Docs. Learn more about how to use Webpack with Symfony here.

You include this in your base template. Then anything you add to it will be included for other Javascript code you use with import statements. You must be using Webpack for this to work though. This is where I have included JQuery and Bootstrap and now FosJsRouting for example.

Once you have all of the above done you can use it like this


//set the routes for the Routing object
Routing.setRoutingData(routes);
//create a url
let testUrl = Routing.generate( 'menu');
//check to see it is working
console.log(testUrl); //outputs /menu

Read a lot more about generating URLs in the FosJsRouting documentation.

Route not found errors?

more errors meme
And.. Errors

Yes I got these too. You must call this setRoutingData() method first with the routes constant created above. I was like WTF too.

Routing.setRoutingData(routes);

Links

Here is the link to the FosJsRoutingBundle installation documentation on github which this blog basically explains.

 

Here is a link to my favorite HTMLEntities converter if you write articles about programming you will need this.

 

Categories
Web Development

Symfony 5+ how to import or link to javascript and css files with webpack encore

Symfony has a handy way of importing your css and javascript files into your templates/pages to use them. You can find the full info in the docs link here.

This was a little confusing to me at first.  Mostly due to my lack of knowledge of some of the Webpack and  modern JS features like importing.
Basically when you update the webpack configuration to add another entry point for a separate Javascript file, it also creates a matching CSS file if your javascript file imports any CSS.  Many 3rd party packages will have imports, as I found out with SunEditor(totally awesome wysiwyg html editor). So when you try to create a script that relies on a CSS file of it’s own like suneditor you need to import like this inside the file.

//edit-about-user.js
import 'suneditor/dist/css/suneditor.min.css'
import suneditor from 'suneditor'
import plugins from 'suneditor/src/plugins'
let aboutInput = 'about-input';
suneditor.create(aboutInput, {
    plugins: plugins,
    buttonList: [
        ['undo', 'redo'],
        ['font', 'fontSize', 'formatBlock'],
        ['paragraphStyle', 'blockquote'],
        ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
        ['fontColor', 'hiliteColor', 'textStyle'],
        ['removeFormat'],
        '/', // Line break
        ['outdent', 'indent'],
        ['align', 'horizontalRule', 'list', 'lineHeight'],
        ['table', 'link', 'image', 'video', 'audio' /** ,'math' */], // You must add the 'katex' library at options to use the 'math' plugin.
        /** ['imageGallery'] */ // You must add the "imageGalleryUrl".
        ['fullScreen', 'showBlocks', 'codeView'],
        ['preview', 'print'],
        ['save', 'template']
    ]
})

This is what confused me I thought the Javascript code would automatically include the CSS file when I included the Javascript in the page with a tag like this

//inside edit-about-user.html.twig
{% block javascript_extra %}
{{ encore_entry_script_tags('editAboutUser') }}
{% endblock %}

block javascipt is my custom twig section, encore_entry_script_tags includes the javascript. This is where I falsely assumed that the import statement above would include the CSS in the page along with the Javascript. The above encore_entry_script_tags function only includes the Javascript. To include the CSS which is the same from the import statement above you must use another tag.

//inside edit-about-user.html.twig
{% block stylesheets %}
{# 'app' must match the first argument to addEntry() in webpack.config.js #}
{{ parent() }}
{{ encore_entry_link_tags('editAboutUser') }}
{% endblock %}

Again block stylesheets is just my custom twig block section. encore_entry_link_tags is the magic needed to include the CSS on the page that the import statement included above. This is what confused me I thought Webpack was bundling the CSS somehow with the JS. What it does is create two files one CSS and one Javascript. You must use the encore_entry functions to include both to get what ever project you are using functioning.

So as I found out you must include both the CSS and JS with encore_entry_ tag functions.

Categories
Web Development

How to get the user id in a service in Symfony 5

I’m no Symfony expert, I write what I find as I find it. Nothing in the documentation really covers this subject, so I am not sure what the correct way is of if there even is one.

There are a few ways I have found to get a user id. None of the classes you can inject such as UserInterface, SessionInterface, TokenInterface, Security etc. contain an actual getUserId() method.

You can  get a user object from the Security class, as seen in the documentation here. To do so you type hint aka Dependency Inject your service constructor with Security but not just any Security will do there is also one by Sensio labs and another. You want this Security

use Symfony\Component\Security\Core\Security;

Then your ide wont show it or will warn something about a polymorphic call blah blah, but apparently there is a getId() method of the user returned from Security and you can get a user id like this.


/** @var User $user */
$user = $this->security->getUser()->getId();
if(!empty($user){
$userId = $user->getId();
}

This method may return null if the user is not logged in so you need to check for that. The @var syntax tells the IDE what is going on so it knows there is a getId() method, you will also need to import that class. The User object it refers to is your App/Entity/User class.

Forgive me if anything is wrong.
Link to a Symfony cast with a little more info but not much.

Categories
Resources Web Development

How does login and authentication work in Symfony 5.*

This is mostly for myself as a reminder. The most frustrating part of Symfony is Authentication because the information is scattered all over between articles, symfonycasts etc. just all over, like a unicorn farting out rainbow sprinkles.

There are two versions of authentication an old one and a new one. The old one uses Authentication providers the new one users just Authetincators. No one but the authors of Symfony know WTF the difference is though.

Note : to add confusion Symfony refers to what you usually call Sessions as Tokens FFS.

First off a list of files involved in the login process :

  1. The login form obviously app/templates/security/login.html.twig
  2. A security controller app/src/Controller/SecurityController.php
  3. A user Provider aka the User entity class app/src/Entity/User.php
  4. An Authenticator app/src/Security/LoginFormAuthenticator.php

When a user requests /login Symfony first calls LoginFormAuthenticator.php to check to see if the user is logged in/authenticated so the work is not done in the controller like most other actions. To change, add, remove anything from the authentication process you make changes in the LoginFormAuthenticator.php methods.

There is a new experimental Authentication system it still uses authenticators but a slightly different process.

This authenticator is listed in the app/config/packages/security.yaml file under firewalls:main:guard:athenticators as

- App\Security\LoginFormAuthenticator

symfony firewall authenticator section

Every time a request is made the firewall will use the authenticator listed to try to authenticate the user. If authentication fails Symfony secretly behind the scenes tries other ways to authenticate the user as you can see in the image below.

symfony guards
Secret guards attack

As you can see in the image above Symfony will try your guard you listed in the configuration file, but it also tries it’s own secret list of default authenticators.

For information about the login form see this article in the scatterdocs. A little more info about the login form and process from the Symfony Spaghetti docs.

Categories
Resources Web Development

Symfony Session resources list

Plain session docs – This is the symfony documentation page about Sessions alone. This link shows the basic configuration and use of Sessions in Symfony. This also mentions not starting a session for Anonymous users and has links to other info about sessions.

Configuring Sessions and Save handlers – Symfony documentation link. This covers more about how to configure sessions and their Save Handlers. This is some of the better information about Sessions and how they work in Symfony. It covers the save handlers and more of the configuration information.

Session proxy examples – Symfony Documentation link. This covers how to create your own session handler. It also discusses how to encrypt session data with an example.

Framework configuration – Symfony documentation link. This covers many of the options for the security component of Symfony.

Store sessions in a database – Symfony documentation link that describes how to store session data in a database or Redis.

Session Management – Symfony documentation link. Explains how sessions are managed in symfony. Gives a good overview and important information about how symfony functions. It covers the functions symfony uses to replace PHP session functions and how to use them. This also covers the ways to work with sessions in Symfony. Oddly this covers Flash messages too.

 

Categories
Resources Web Development

Symfony errors and exception handling resources

How to customize error pages – Documentation page about how to create custom error pages.
How to Customize Access Denied Responses – specifically about how to customize access denied responses. This is useful for when you use voters to authorize a users access to content.

Categories
Resources

Links and resources about Symfony firewall and authentication system

One thing you will want to do is view your current security settings to do so you use this command.
php bin/console debug:config security

Old symfony cookbook security entry – This is an ancient link to nearly the very beginning of symfony. This explains the mechanics of the Symfony security system if you are like me and just want to know how the hell this functions so you can feel confident in the system and be able to diagnose and fix issues.

More on Security – this is another ancient link like above, it explains the system.


Symfony cast covering
firewall and authentication and how it works. This has lots of info that should be directly in the documentation.

Security configuration reference -> not complete listing of some of the values you can set. If you run the debug:config command above you will see more values you can set, but good luck figuring out what they do.

How to restrict firewalls to a request -> symfony docs. This talks about using multiple firewalls and how the Symfony firewall system works like a waterfall trying one firewall after another until it finds one that works or uses the last  firewall listed. This also explains some of the options to the firewall. This basically shows how to use multiple firewalls.

Symfony cast about security – this covers the entire system. Some things have changed in version 5 but this is mostly correct and serves as a starting point.

Security user providers – Part of the Firewall/Authentication/Authorization system is something called security providers. User providers check the users identity from a session cookie to verify the user. This part of the documentation talks about how the firewall uses the User providers to authenticate the user after they have logged in.

Custom Authentication System with Guard (API Token Example) – talks about how to create a custom API token

Built-in Authentication Providers – documentation about the built in service providers.

Symfony Cast about gaurds – this is ancient from version 3, but it is helpful because it covers how the system is supposed to work or was supposed to.

The firewall and authorization – this covers how authorization works in the firewall system. It has a section at the bottom that explains how the firewall/authentication/authorization flow works.

Using the form_login Authentication Provider  – This explains how to create a login form and how the system processes it and authenticates the user.

Videos


A good video explaining how multiple authenticators work