Skip to content

Install and show the forms ​

This page is for the markup. Everything below is done in a MODX template and in .tpl files; PHP starts only on the next page, and then only two lines of it.

Installation ​

  1. Install PageBlocks 3.x — without it the component switches itself off and writes a log entry.
  2. Extras → Installer → Download Extras, find and install pbAuth.
  3. System → System Settings, filter by pageblocks. The pageblocks_routing setting must be set to Route Only or Full API.
  4. While you are there, enable pageblocks_load_scripts — forms will start submitting without a reload, and errors will light up right in the fields.
  5. Clear the site cache.

Check: open /login. A page with a working login form should come up. You do not need to create a resource for it — the router serves that address.

The migration is a separate step

The table is only needed for social networks, and the package creates it during installation on its own. If exec() is disabled on the hosting, the resolver says so plainly in the log — then apply the migration by hand:

bash
php core/components/pageblocks/vendor/bin/phinx migrate \
    --configuration=core/components/pbauth/src/phinx.php --environment=production

Without the table everything works except social login.

What the installer put where ​

WhereWhatWhose
core/components/pbauth/code, routes, shipped settings, lexiconsthe component's — will be overwritten on update
core/App/elements/auth/wrapper templates and form chunksyours
core/App/lang/{ru,en,uk,de}/auth.phpall the labelsyours
core/App/config/pbauth.phpa settings stub, entirely commented outyours

"Yours" here is not politeness. Neither installation nor an update ever overwrites a file that already exists in core/App/. Exactly what the installer put there is recorded with hashes in core/App/.pbauth-installed.json, and uninstalling the component removes only the files you never touched.

"Login" and "Register" buttons in the header ​

The ready-made chunks are already in place, you only have to call them from the site template. There are two options.

Plain links — they lead to the separate pages /login and /register:

{include 'file:auth/chunks/auth.tpl'}

Modal windows — the forms open on top of the page:

{include 'file:auth/chunks/auth_modal.tpl'}

Both chunks work out for themselves whether the person is logged in: a guest sees the buttons, a logged-in user sees an avatar with their name and a link to the profile.

file: is the site's folder

file:auth/chunks/auth.tpl means core/App/elements/auth/chunks/auth.tpl. The default source is set by the pageblocks_elements_path setting.

Changing how they look ​

Open core/App/elements/auth/chunks/auth.tpl and edit it like ordinary markup. There are only two meaningful constructs inside:

{auth}   ...what a logged-in user sees...   {/auth}
{guest}  ...what a guest sees...            {/guest}

Do not write the links by hand — take them by name, then they will not break if the page address changes:

html
<a href="{route 'pageLogin'}">Login</a>
<a href="{route 'pageRegister'}">Register</a>
<a href="{route 'pageProfile'}">My profile</a>
<a href="{route 'logout'}">Log out</a>

The full list of names is in the reference.

The login and registration pages ​

A page is assembled from two files:

FileWhat it is
wrappercore/App/elements/auth/templates/auth.tpl<html>, <head>, styles, the common frame
formcore/App/elements/auth/chunks/form.login.tplthe form itself, inserted inside the wrapper

There are two wrappers: auth.tpl (login, registration, recovery) and profile.tpl (profile and password change — that one has a section menu on the side).

The forms sit next to each other, one per action:

core/App/elements/auth/chunks/
    form.login.tpl              login
    form.register.tpl           registration
    form.forgotPassword.tpl     "forgot password"
    form.resetPassword.tpl      entering a new password via the link from the e-mail
    form.changePassword.tpl     changing the password in the profile
    form.confirmPassword.tpl    password confirmation
    form.resendVerification.tpl re-sending the confirmation link
    form.twoFactorChallenge.tpl entering the code at login
    form.twoFactor.tpl          enabling and disabling the code in the profile
    form.socialEmail.tpl        asking for an e-mail when the social network gave none
    form.profile.tpl            profile editing
    social.buttons.tpl          social login buttons
    social.accounts.tpl         linked networks in the profile
    modals/                     the same forms for modal windows
    email.verifyEmail.tpl       the e-mail with the confirmation link
    email.resetPassword.tpl     the password reset e-mail

Two variables reach the wrapper template: $title — the page heading, and $form — the name of the chunk with the form (for example form.login). The form is included like this:

{set $chunkPath = 'file:auth/chunks/' ~ $form}
{include $chunkPath}

What a form field must have ​

When editing a form, keep three things on every field — otherwise it stays functional but stops behaving decently:

html
<div class="form-group mb-3">
    <label class="mb-2" for="email">E-mail</label>
    <input type="email" name="email" id="email"
           class="form-control{if $errors.email} is-invalid{/if}"
           value="{$old_input.email}" required>
    <span class="invalid-feedback" data-error="email">{$errors.email}</span>
</div>
WhatWhy
name="email"the field arrives at the server under this name
{$errors.email} and data-error="email"the error text lands here; data-error is what the script needs to insert it without a reload
{$old_input.email}so that what was typed is not wiped on an error

Errors are not shown

Almost always one of two things: the field has no {$errors.name} and data-error="name", or the pageblocks_load_scripts setting is off.

Replace a single form ​

Your own registration form, with the rest left as they are: put your chunk next to them and name it in core/App/config/pbauth.php.

php
<?php

return [
    'forms' => [
        'register' => 'my.register',   // core/App/elements/auth/chunks/my.register.tpl
    ],
];

And if your template draws the form itself and does not need the $form variable:

php
'forms' => ['profile' => null],

Your own template instead of the shipped one ​

If you already have your own page template — do not edit the shipped file, point to yours:

php
'views' => [
    'auth'    => 'file:templates/my-auth',      // core/App/elements/templates/my-auth.tpl
    'profile' => 'file:templates/my-profile',
],

There are only two wrappers, but an individual page can be given its own — a key named after the action overrides the general one:

php
'views' => [
    'profile'    => 'file:templates/my-profile',   // all profile pages
    'two_factor' => 'file:auth/templates/profile', // and this one its own way
],

Handy when the site's profile template is self-sufficient and does not substitute $form, yet some page does need a form after all.

Write only the differences

The settings file is merged with the shipped one: dictionaries are extended by key, lists are replaced whole. There is no need to list all the forms for the sake of one replacement. Details — "The settings file".

Texts and translations ​

All the labels are in core/App/lang/ru/auth.php, an ordinary PHP array:

php
<?php

return [
    'login_title' => 'Login',
    'register_title' => 'Register',
    'register_success' => 'Check your e-mail — we have sent a confirmation link',
];

In a template a label is called as {lang 'auth.login_title'}, in PHP as lang('auth.login_title').

There are four languages: ru, en, uk, de. Add a new key to all of them — otherwise another language will show the key itself instead of the text.

Do not confuse this with the lexicon

core/components/pbauth/lexicon/ holds the captions for settings and buttons in the MODX manager. They belong to the component and are overwritten on update.

If the confirmation e-mail never arrived ​

After registering, a person receives an e-mail with a link and cannot log in until they follow it. E-mails get lost all the time: spam, delays, a typo in the address.

That is what the /resend-verification page is for — it is already wired up, and a link to it sits at the bottom of the login form.

The form's response is always the same, regardless of whether the address was found or not and whether it is confirmed. Otherwise this form could be used to brute-force which addresses are registered on the site. "Forgot password" behaves the same way.

The two forms are not interchangeable

Password recovery works only for confirmed accounts, and re-sending only for unconfirmed ones. MODX keeps both one-time keys in the same remote_key field, and if the forms overlapped, an issued link would kill the previous one.

The edit is not visible ​

Clear the MODX cache and reload the page with Ctrl+F5. If the edit has vanished entirely — most likely it was in a file inside core/components/pbauth/: everything there gets overwritten.

pbAuth — login, registration and profile for PageBlocks