• Stars
    star
    106
  • Rank 325,871 (Top 7 %)
  • Language
    PHP
  • License
    MIT License
  • Created over 10 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Accept anonymous entry submissions with Craft.

Guest Entries for Craft CMS

Allow guests to create entries from your site’s front end.

Requirements

Guest Entries requires Craft CMS 4.0 or later.

Installation

You can install Guest Entries from the Plugin Store or with Composer.

From the Plugin Store

Go to the Plugin Store in your project’s control panel (in an environment that allows admin changes), search for “Guest Entries,” then click Install.

With Composer

Open your terminal and run the following commands:

# Navigate to your project directory:
cd /path/to/my-project

# Require the plugin package with Composer:
composer require craftcms/guest-entries -w

# Install the plugin with Craft:
php craft plugin/install guest-entries

Settings

From the plugin settings page, you can configure…

  • …which sections should allow guest entry submissions;
  • …the default entry authors and statuses;
  • …and whether submissions should be validated before being accepted.

Usage

A basic guest entry template should look something like this:

{# Macro to help output errors: #}
{% macro errorList(errors) %}
    {% if errors %}
        {{ ul(errors, { class: 'errors' }) }}
    {% endif %}
{% endmacro %}

{# Default value for the `entry` variable: #}
{% set entry = entry ?? null %}

<form method="post" action="" accept-charset="UTF-8">
    {# Hidden inputs required for the form to work: #}
    {{ csrfInput() }}
    {{ actionInput('guest-entries/save') }}

    {# Custom redirect URI: #}
    {{ redirectInput('success') }}

    {# Section for new entries: #}
    {{ hiddenInput('sectionHandle', 'mySectionHandle') }}

    {# Entry properties and custom fields: #}
    <label for="title">Title</label>
    {{ input('text', 'title', entry ? entry.title, { id: 'title' }) }}
    {{ entry ? _self.errorList(entry.getErrors('title')) }}

    <label for="body">Body</label>
    {{ tag('textarea', {
        text: entry ? entry.body,
        id: 'body',
        name: 'fields[body]',
    }) }}
    {{ entry ? _self.errorList(entry.getErrors('body')) }}

    {# ... #}

    <button type="submit">Publish</button>
</form>

Note
The process of submitting data and handling success and error states is outlined in the controller actions documentation.

Supported Params

The following parameters can be sent with a submission:

Name Notes Required
sectionHandle Determines what section the entry will be created in.
sectionUid Can be sent in lieu of sectionHandle.
sectionId Can be sent in lieu of sectionHandle.
typeId Entry type ID to use. This may affect which custom fields are required. When absent, the first configured type for the specified section is used.
title Optional if the section has automatic title formatting enabled.
slug Explicitly sets the new entry’s slug.
postDate Value should be processable by DateTimeHelper::toDateTime()
expiryDate Value should be processable by DateTimeHelper::toDateTime()
parentId Nest this entry under another. Invalid for channels and structures with a maximum depth of 1.
siteId Create the entry in a specific site.
enabledForSite Whether the entry should be enabled in this site. The global enabled setting is configurable by administrators, so this alone will not immediately publish something.
fields[...] Any custom fields you want guests to be able to populate.

Form Tips

Specifying a Section + Entry Type

The plugin determines what section the new entry is created in by looking for a sectionHandle, sectionUid, or sectionId param, in this order. Entry types, on the other hand, can only be defined by a typeId param—but because IDs can be unstable between environments, you must look them up by a known identifier.

Granted you will already have a section (or at least a section handle), the easiest way to do this is via the section model:

{% set targetSection = craft.app.sections.getSectionByHandle('resources') %}
{% set entryTypes = targetSection.getEntryTypes() %}

{# Select a single type, identified by its handle: #}
{% set targetEntryType = collect(entryTypes).firstWhere('handle', 'document') %}

{{ hiddenInput('sectionId', targetSection.id) }}
{{ hiddenInput('typeId', targetEntryType.id) }}

Sending Custom Fields

Custom field data should be nested under the fields key, with the field name in [squareBrackets]:

<input
    type="text"
    name="fields[myCustomFieldHandle]"
    value="{{ entry ? entry.myCustomFieldHandle }}">

If entries in the designated section are enabled by default, validation will occur on all custom fields, meaning those marked as required in the entry type’s field layout must be sent with the submission. Refer to the field types documentation to learn about the kinds of values that Craft accepts.

Warning
Omitting a field from your form does not mean it is safe from tampering! Clever users may be able to modify the request payload and submit additional field data. If this presents a problem for your site, consider using an event to clear values or reject submissions.

Validation Errors

If there are validation errors on the entry, the page will be reloaded with the populated craft\elements\Entry object available under an entry variable. You can access the posted values from that object as though it were a normal entry—or display errors with getErrors(), getFirstError(), or getFirstErrors().

Note
The entry variable can be renamed with the “Entry Variable Name” setting in the control panel. This might be necessary if you want to use a form on an entry page that already injects a variable of that name.

Redirection

Send a redirect param to send the user to a specific location upon successfully saving an entry. In the example above, this is handled via the redirectInput('...') function. The path is evaluated as an object template, and can include properties of the saved entry in {curlyBraces}.

Submitting via Ajax

If you submit your form via Ajax with an Accept: application/json header, a JSON response will be returned with the following keys:

  • success (boolean) – Whether the entry was saved successfully
  • errors (object) – All of the validation errors indexed by field name (if not saved)
  • id (string) – the entry’s ID (if saved)
  • title (string) – the entry’s title (if saved)
  • authorUsername (string) – the entry’s author’s username (if saved)
  • dateCreated (string) – the entry’s creation date in ISO 8601 format (if saved)
  • dateUpdated (string) – the entry’s update date in ISO 8601 format (if saved)
  • postDate (string, null) – the entry’s post date in ISO 8601 format (if saved and enabled)
  • url (string, null) – the entry’s public URL (if saved, enabled, and in a section that has URLs)

Viewing Entries

Using a redirect param allows you to show a user some or all of the content they just submitted—even if the entry is disabled, by default.

Warning
Take great care when displaying untrusted content on your site, especially when subverting moderation processes!

Enabled by Default

Entries in sections with URLs can be viewed immediately, with this redirect param:

{{ redirectInput('{url}') }}

Disabled by Default

In order to display an entry that is disabled, you will need to set up a custom route

<?php

return [
    // This route uses the special `{uid}` token, which will
    // match any UUIDv4 generated by Craft:
    'submissions/confirmation/<entryUid:{uid}>' => ['template' => '_submissions/confirmation'],
];

…and direct users to it by including {{ redirectInput('submissions/confirmation/{uid}') }} in the entry form. Your template (_submissions/confirmation.twig) will be responsible for looking up the disabled entry and displaying it, based on the entryUid route token that Craft makes available:

{% set preview = craft.entries()
    .status('disabled')
    .section('documents')
    .uid(entryUid)
    .one() %}

{# Bail if it doesn’t exist: #}
{% if not preview %}
    {% exit 404 %}
{% endif %}

{# Supposing the user’s name was recorded in the `title` field: #}
<h1>Thanks, {{ preview.title }}!</h1>

<p>Your submission has been recorded, and is awaiting moderation.</p>

This query selects only disabled entries so that the “preview” is invalidated once the entry goes live. This “confirmation” URI does not need to match the actual URI of the entry.

Events

Guest Entries augments the normal events emitted during the entry lifecycle with a few of its own, allowing developers to customize the submission process.

The following snippets should be added to your plugin or module’s init() method, per the official event usage instructions.

The beforeSaveEntry event

Plugins can be notified before a guest entry is saved, using the beforeSaveEntry event. This is also an opportunity to flag the submission as spam, and prevent it being saved:

use craft\helpers\StringHelper;
use craft\guestentries\controllers\SaveController;
use craft\guestentries\events\SaveEvent;
use yii\base\Event;

// ...

Event::on(
    SaveController::class,
    SaveController::EVENT_BEFORE_SAVE_ENTRY,
    function(SaveEvent $e) {
        // Get a reference to the entry object:
        $entry = $e->entry;

        // Perform spam detection logic of your own design:
        if (StringHelper::contains($entry->title, 'synergy', false)) {
            // Set the event property:
            $e->isSpam = true;
        }
    }
);

The afterSaveEntry event

Plugins can be notified after a guest entry is saved, using the afterSaveEntry event:

use craft\guestentries\controllers\SaveController;
use craft\guestentries\events\SaveEvent;
use yii\base\Event;

// ...

Event::on(
    SaveController::class,
    SaveController::EVENT_AFTER_SAVE_ENTRY,
    function(SaveEvent $e) {
        // Grab the entry
        $entry = $e->entry;

        // Was it flagged as spam?
        $isSpam = $e->isSpam;
    }
);

The afterError event

Plugins can be notified right after a submission is determined to be invalid using the afterError event:

use craft\guestentries\controllers\SaveController;
use craft\guestentries\events\SaveEvent;
use yii\base\Event;

// ...

Event::on(
    SaveController::class,
    SaveController::EVENT_AFTER_ERROR,
    function(SaveEvent $e) {
        // Grab the entry
        $entry = $e->entry;

        // Get any validation errors
        $errors = $entry->getErrors();
    }
);

More Repositories

1

cms

Build bespoke content experiences with Craft.
PHP
3,213
star
2

happy-lager

Craft CMS demo site.
PLpgSQL
735
star
3

awesome

A collection of awesome Craft CMS plugins, articles, resources and shiny things.
526
star
4

element-api

Create a JSON API/Feed for your elements in Craft.
PHP
498
star
5

contact-form

Add a simple contact form to your Craft CMS site.
PHP
293
star
6

feed-me

Craft CMS plugin for importing entry data from XML, RSS or ATOM feeds—routine task or on-demand.
PHP
287
star
7

commerce

Fully integrated ecommerce for Craft CMS.
PHP
215
star
8

craft

Composer starter project for Craft CMS.
Twig
183
star
9

nitro

Speedy local dev environment for @craftcms.
Go
178
star
10

plugins

The master list of Craft 3-compatible plugins
107
star
11

docker

Craft CMS Docker images.
Dockerfile
102
star
12

redactor

Edit rich text content in Craft CMS using Redactor by Imperavi.
JavaScript
101
star
13

webhooks

Plugin for integrating Craft with Zapier and IFTTT.
PHP
84
star
14

generator

Scaffold new Craft CMS plugins, modules, and system components from the CLI
PHP
83
star
15

starter-blog

Blog starter site learning resource.
JavaScript
79
star
16

server-check

Craft CMS server requirements checker.
Hack
68
star
17

store-hours

Manage business hours with Craft CMS.
PHP
62
star
18

aws-s3

Amazon S3 volume type for Craft CMS.
PHP
60
star
19

gatsby-source-craft

Gatsby source plugin for Craft CMS.
TypeScript
54
star
20

spoke-and-chain

Craft CMS + Craft Commerce demo site.
Twig
54
star
21

phpstorm-settings

PhpStorm settings used for Craft CMS development.
50
star
22

anchors

Add anchor links to headings in your Craft CMS website content.
PHP
48
star
23

europa-museum

Craft CMS demo site.
SCSS
47
star
24

ckeditor

Edit rich text content in Craft CMS using CKEditor.
PHP
46
star
25

shopify

Synchronize and extend product data from your Shopify storefront.
PHP
45
star
26

apple-news

Publish your Craft CMS content with Apple News Format.
PHP
41
star
27

docs

Documentation for Craft CMS, Craft Commerce, and other official products.
JavaScript
38
star
28

commerce-stripe

Stripe payment gateway for Craft Commerce
PHP
30
star
29

plugin-installer

Composer installer for Craft CMS plugins.
PHP
28
star
30

mailgun

Mailgun mailer adapter for Craft CMS.
PHP
28
star
31

redactor-clips

Adds Redactor’s “Clips” plugin to Rich Text fields in Craft
PHP
27
star
32

simple-text

Simple textarea field type for Craft CMS.
JavaScript
27
star
33

contact-form-honeypot

Add a honeypot captcha to your Craft CMS contact form.
PHP
26
star
34

vue-asset

⛔️ DEPRECATED | Vue.js asset bundle for Craft 3 Beta
JavaScript
24
star
35

postmark

A Postmark mail adapter for Craft CMS.
PHP
20
star
36

rector

Rector rules for updating plugins and modules to Craft CMS 4.
PHP
19
star
37

digital-products

Sell digital products with Craft Commerce.
PHP
18
star
38

legacy-docs

The source documentation for Craft CMS
JavaScript
16
star
39

ecs

Easy Coding Standard configurations for Craft CMS projects.
PHP
16
star
40

oauth2-craftid

Craft ID Provider for OAuth 2.0 Client.
PHP
15
star
41

query

Run SQL queries as an admin from the Craft CMS control panel.
PHP
15
star
42

gatsby-helper

Craft CMS helper plugin for Gatsby.
PHP
15
star
43

fix-fks

Utility that restores any missing foreign key constraints
PHP
12
star
44

mandrill

Mandrill mailer adapter for Craft CMS.
PHP
12
star
45

phpstan

PHPStan configuration for Craft CMS projects.
12
star
46

google-cloud

Google Cloud Storage volume type for Craft CMS.
PHP
11
star
47

tutorial-project

Tutorial demo project source.
Twig
9
star
48

image

Container images that are used as the base for Craft CMS container applications
Dockerfile
8
star
49

sass

Sass mixins for the Craft CMS control panel.
SCSS
8
star
50

commerce-paypal

PayPal payment gateway for Craft Commerce.
PHP
6
star
51

commerce-omnipay

Omnipay gateway bridge for Craft Commerce
PHP
5
star
52

license

The Craft License
5
star
53

hexdec

Adds a ‘hexdec’ filter to Craft CMS.
PHP
5
star
54

commerce-paypal-checkout

PayPal Checkout gateway for Craft Commerce.
PHP
5
star
55

commerce-mollie

Mollie payment gateway for Craft Commerce.
PHP
5
star
56

.github

GitHub community files for Craft CMS.
5
star
57

ontherocks

JavaScript
5
star
58

stripe

Sync and extend Stripe products and subscriptions.
PHP
5
star
59

azure-blob

Azure Blob Storage for Craft CMS.
PHP
4
star
60

commerce-sagepay

SagePay payment gateway for Craft Commerce.
PHP
4
star
61

yii2-dynamodb

Yii2 implementation of a queue and cache driver for DynamoDB
PHP
4
star
62

automation-workshop

PLpgSQL
4
star
63

html-field

Base class for Craft CMS field types with HTML values.
PHP
4
star
64

cloud

Public repo for discussions, feature requests, and ehancements Craft Cloud. For support, please email [email protected]
4
star
65

legacy-commerce-docs

Commerce Documentation
JavaScript
4
star
66

flysystem

Flysystem integration package for Craft CMS 4
PHP
3
star
67

locales

Craft CMS localization data for all the locales.
PHP
3
star
68

commerce-eway

eWay payment gateway for Craft Commerce.
PHP
3
star
69

commerce-multisafepay

MultiSafepay payment gateway for Craft Commerce.
PHP
3
star
70

rackspace

Rackspace Cloud Files volume type for Craft CMS
PHP
2
star
71

commerce-paystack

Paystack payment gateway for Craft Commerce.
PHP
2
star
72

commerce-worldpay

Worldpay payment gateway for Craft Commerce.
PHP
2
star
73

plugin-port-helper

Plugin port helper for porting plugins from Craft 2 to Craft 3.
PHP
2
star
74

homebrew-nitro

Brew repository for Craft Nitro.
Ruby
2
star
75

commerce-taxjar

TaxJar integration for Craft Commerce.
PHP
2
star
76

docs-translations

Translated content moved out of `docs` and maintained separately.
JavaScript
1
star
77

textlint-rule-linkable-params

Custom textlint rule for allowing lowercase variations of terms when linked.
JavaScript
1
star
78

craftcms-imgproxy

PHP
1
star
79

console

Public repo for bug reports, discussions, feature requests, and ehancements Craft Console and the Plugin Store
1
star
80

ddev-craft-cloud

Shell
1
star