Creating a rewrite plugin by country codes

Hi all, happy holidays and I trust all is well with everyone.

I have a request that I’m wondering is even possible. I have a multi-site hosted in Ngnix and I’m filtering the countries by the country code in the url e.g https://mysite/en/home?country=bb or https://mysite.com/en/home?country=jm

My question is: is it possible to create a plugin that rewrites the url from ‘?country=bb’ to use the url friendly country name ‘barbados‘? I was wondering if it’s even possible to rewrite the url to https://mysite.com/en/{countryname}/home or must the country name must be appended at the end of the url like https://mysite.com/en/home/{countryname}

I forgot to mention that I have a snippet at the top of every snippet that checks if the $_GET[‘country‘] is set in url. If true, it creates/updates a cookie to the country code, providing the cookie hasnt been set to the code in the $_GET. Therefore, if the first question is possible, can I also set the cookie from the country name?

I’m not sure I understand your question completely.


It’s possible to write a plugin in MODX, so that a request to en/{countryname}/home shows the same result as a request to en/home?country={countrycode}.

This is usually done by using the event OnPageNotFound.
When there is a request to en/barbados/home and MODX can’t find a resource with this URI, the event OnPageNotFound is invoked, where you can check the requested URI (usually $_REQUEST['q']) and then load the correct resource yourself.

In this case you would check if $_REQUEST['q'] matches a certain pattern (like e.g. ^en\/(.+)\/home$). If it’s a match, you’d set $_GET['country'] to the correct value (based on the URI), change $_REQUEST['q'] to exclude the country name and use modX.sendForward() to forward the request to the correct page (en/home).


There is the extra CustomRequest that does something like this, but you may have to write a custom plugin for your specific use case.

I am also very interested in a similar situation and instead of opening a new thread, I am joining this one, hoping that any responses will also be useful to random_noob.

I ask those who, if they respond, to be as detailed as possible to the point of copy/pasting. :grinning_face:

On a site, I have a page mysite.it/teams/ that displays news from a table based on the id parameter about the teams.
First of all, is it okay to set teams as a container? Is it the best solution considering the following?

My table is structured as follows
id name(unique in the table) foundation
1 name_1 2005
2 name_2 2003

Assuming that the container for the page is fine, when I go to the page

mysite.it/teams/?id=1 I would like the URL to be

mysite.it/teams/name_1.html (or even without html)

Is it enough to create a plugin that activates only with the OnPageNotFound event and nothing else?

In this plugin, if possible in detail, what specific code should I include to achieve the above?

In case I wanted to use CustomRequest, what are the detailed settings I need to configure?

Thanks in advance to anyone who replies to me

@SilverMabol In your case it’s probably best to just use the CustomRequest extra, as that is much easier than writing your own custom plugin.

For more information about how to use CustomRequest, please read the documentation page:


Yes.

It’s usually better not to use id as a request parameter, as MODX uses the id parameter for resources (if request_method_strict is not set, or the value of request_param_idis not changed).

1 Like

Thank you, by always using furl’s I always forget that otherwise MODx uses id as a parameter, I’ll use t instead.
I had already read the page on CustomRequest but, due to my ignorance, I didn’t understand how to use it in my case. :grinning_face:
It seemed to me that with customRequest by inserting the parameter [“t”], the result would be mysite.it/teams/1/ and not mysite.it/teams/nome_1.
I’m still a stubborn fool :grinning_face: :grinning_face: :grinning_face: and I like to understand and “build” things, so I won’t abandon the idea of a personal plugin.
I will write my solutions while waiting for some good Samaritan to give me advice.:upside_down_face:
Then, reading around, I read that for large sites this solution (plugin with the OnPageNotFound event) might not be performant, but I wouldn’t know what else to use.

If you’re concerned about performance, you could also run your plugin earlier in the process (like OnMODXInit or OnHandleRequest), before MODX does the look-up for the resource (or even adapt the .htaccess file).

Here is some example plugin for the OnMODXInit event:

<?php
$eventName = $modx->event->name;
switch($eventName) {
    case 'OnMODXInit':
        $requestParamAlias = $modx->getOption('request_param_alias', null, 'q');
    	if (!isset($_REQUEST[$requestParamAlias])) {
    		return;
    	}	
    	$q = $_REQUEST[$requestParamAlias];
    	if (preg_match('#^teams/([^/]+)/?$#i', $q, $matches)) {
    		$_GET['t'] = $_REQUEST['t'] = $matches[1];
    		$_GET[$requestParamAlias] = $_REQUEST[$requestParamAlias] = "teams/";
    	}
        break;
}

So a request to
https://mysite.com/teams/name_1
gets rewritten in the .htaccess file to
https://mysite.com/?q=teams/name_1
and then in the custom plugin to (basically)
https://mysite.com/?q=teams/&t=name_1


Then in the “teams” resource, add an uncached snippet tag (like e.g. [[!getTeam]]) to the content/template that loads the team information based on the $_GET['t'] request parameter.

Here is some example code: (This is just some basic code to demonstrate the process. Please adjust it to your needs.)

<?php
use MyCompany\Model\Team; // The custom class for my database table with the team information

$output = "";
$team_name = $_GET['t'] ?? ''; // Read the value of the "t" request parameter
if ($team_name) {
    // load the team corresponding to the GET parameter "t"
    $team = $modx->getObject(Team::class, ["name" => $team_name]); // this assumes that the team-names are unique
    if ($team) {
        // output the information for this team
        $ateam = $team->toArray();
        $output = "<h2>{$ateam['name']}</h2><p>Founded in {$ateam['foundation']}</p>";
    } else {
        $output = "No team found with this name!"; // ouput an error message (or alternatively forward to the error page)
    }
} else {
    // no "t" request parameter -> output a list of all the teams
    $teams = $modx->getCollection(Team::class);
    $url = $modx->makeUrl($modx->resource->get('id')); // URL of the current resource
    $output .= "<h2>Teams</h2><ul>";
    foreach($teams as $team){
        $ateam = $team->toArray();
        $output .= '<li><a href="' . $url . $ateam['name'] . '">' . $ateam['name'] . '</a></li>'; // Add the team name to the URL for the link
    }
    $output .= "</ul>";
}
return $output;
1 Like