Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

idcreatv's avatar

Replacing a [shortcode] with a query from the database

I have made a system where a user can create many documents which they can include in a PDF using dompdf.

Everything works fine but I've been asked if the customer can use a Wordpress-like shortcode in their documents for replacing with the company name. Something like:

[company_name]

This would return the name of the company for the current record of the active view, so it may be ABC Ltd for one and DEF Inc for another etc.

The shortcode would be inside a WYSIWYG area with the company name pulled from the active record, so something like:

Company name : ABC Ltd
Company address: A N Other Avenue, Citysville
Select documents:
- Terms of business [x]
- Contract [ ]
- Support services [x]
etc etc

When the PDF is created for this record, inside the selected documents the shortcode [company_name] will be replaced with ABC Ltd.

I've had a look for packages which could potentially handle this and have found https://github.com/webwizo/laravel-shortcodes - I'm not 100% sure if this does what I need, so if anyone has any advice as to whether this would do the trick or if there's another way to do it, it would be most appreciated. :)

0 likes
5 replies
steinmagne's avatar

Before you send the text to domPDF you can loop through the allowed placeholders and replace the text with data from the database.

$placeHolders = ['[company_name]' => $company->name, '[company_address]' => $company->address, '[company_email]' => $company->email];
foreach($placeHolders AS $placeholder => $replaceWith){
    $documentText = str_replace($placeholder, $replaceWith, $documentText);
}
// Send $documentText to domPDF.
// ...

1 like
idcreatv's avatar

Aha, I see - that's great, thanks @steinmagne. Is this to work with the webwizo shortcodes package I referenced or is there another way I should do it?

steinmagne's avatar

This is not for webwizo package. I would create a new class that handles this. Example below. I have also added possibility to chain if you have different type of data to be replaced. Haven't tested this very much so there may be some bugs :) But you can give it a try.


namespace App\core;
use App\Company;
use App\Other;
use vendor\Dompdf\Dompdf; // or wherever it may live

class Placeholder{

    private static $documentText;
    private static $_instance = null;

    public static function load($documentText){
        if (self::$_instance === null) {
            self::$_instance = new self;
        }
        self::$documentText = $documentText;
        return self::$_instance;
    }

    public function replaceCompany($companyId = 1){
        // default value 1 for testing purposes
        // Get company
        $company = Company::whereId($companyId)->first();
        // Define placeholders
        $placeHolders = [
            '[company_name]' => $company->customer_name,
            '[company_address]' => $company->address,
            '[company_email]' => $company->email
        ];
        foreach($placeHolders AS $placeholder => $replaceWith){
            static::$documentText = str_replace($placeholder, $replaceWith, static::$documentText);
        }
        return $this;
    }
    public function replaceOther($otherId = 1){
        // default value 1 for testing purposes. This model is the same as company, just different name to show how it can be done.
        // Get Other
        $other = Other::whereId($otherId)->first();
        // Define placeholders
        $placeHolders = [
            '[zip_code]' => $other->zipcode,
            '[city]' => $other->city
        ];
        foreach($placeHolders AS $placeholder => $replaceWith){
            static::$documentText = str_replace($placeholder, $replaceWith, static::$documentText);
        }
        return $this;
    }

    public function get(){
        return static::$documentText;
    }
}

// Use it
// Get documentdata.
$document = ['content' => 'Company name : [company_name]. Address: [company_address], [zip_code] [city].'];

// Replace text with chaining
$documentText = Placeholder::load($document['content'])->replaceCompany()->replaceOther()->get();

$dompdf = new Dompdf();
$dompdf->loadHtml($documentText);
$dompdf->render();
$dompdf->stream();

1 like
martinbean's avatar
Level 80

You don’t need to do replacements in a foreach() loop. The str_replace() function accepts array for the first two arguments, so you could do this:

$shortcodes = [
    '[company_name]' => $company->customer_name,
    '[company_address]' => $company->address,
    '[company_email]' => $company->email,
    // and so on
];

$find = array_keys($shortcodes);
$replace = array_values($shortcodes);

$string = str_replace($find, $replace, $string);
2 likes
idcreatv's avatar

Thanks so much chaps, I'll give the above a try and see how I get on (if all works well I'll mark this question as answered).

Please or to participate in this conversation.