Links

Url structures are a significant part of web applications. For this reasons the Adventure PHP
Framework (APF) provides a framework-like solution to easily generate and manipulate urls.

Within the past (including release 1.13) the APF provided the LinkHandler and
FrontcontrollerLinkHandler components that have provided static methods to generate new
urls or provide existing ones. Manipulation of existing urls is the basis of loose coupling of
software components using the url. If every component just changes "their" own set of
parameters and remains the "others" un-touched several components can be managed within
one request at the same time.

One big disadvantage of the statical approach is that the url layout and the generation mechanism
must be kept synchronous for all components. As a last consequence, this breaks the separation of
url layout and software as described in the APF's
filter concept.

For this reason, the link generation mechanism has been redesigned in 1.14 to easily implement
custom url layouts (see
wiki
page) that can be injected to existing applications.

The architecture of the link generation mechanism starting with release 1.14 introduces a
separation between the construction of an url and the url itself (class Url). Beyond, the
LinkGenerator component is able to create "normal" and
front controller action urls.

The real "work" is done by an LinkScheme implementation that is provided the
url representation created by the developer. The link scheme's code then formats the url as
described in the following picture:

The Url class represents any url according to
RFC 1630
which is independent from the formatting that is done later on. This enables you to generate every
link format out of the url representation or from any "ordinary" url.

The LinkGenerator class is responsible for link formatting. It delegates the real work
to the globally configured or applied LinkScheme.

Basically, the LinkGenerator is an abstraction component concerning the link generation.
In case each software component uses the link generator (as it is the case for all APF components)
changing the link scheme causes an on-the-fly adaption of the url layout.

As mentioned in the introduction the LinkGenerator features a special method to generate
action urls to explicitly address
front controller actions.

generateActionUrl() is intended to create an explicit front controller action call.
Actions that should remain within the url for consistency reasons are automatically embedded into
the generated url by the link scheme implementations shipped with the APF. Details can be taken
from chapter 7
within the front controller documentation.

The LinkScheme interface defines the structure of every dedicated link formatting component.
Each implementation must be able to create a url by an applied Url or a Url
together with action parameters.

In other words: a LinkScheme represents the actual url layout concerning the generation
of links. Please note, that an url layout is only fully functional in combination with a suitable
input filter. This is because
urls must be interpreted to be able to control the application from the outside.

formatLink() is intended to generate "normal" urls, formatActionLink()
generates front controller urls. setEncodeAmpersands() and getEncodeAmpersands()
can be used to configure the link scheme.

Within the present version of the APF two implementations of the interface are included:
DefaultLinkScheme and RewriteLinkScheme. The former is used to format
"default" urls, the latter one handles rewritten urls according to the layout definition
within chapter rewrite urls of the
filter documentation and or the url layout
section of the front controller documentation.

The usual application case of the link generation is the manipulation of an existing url. For this
reason, the current Url can be configured with the desired parameters. After that, it
can be passed to the LinkGenerator for formatting:

The Url class provides a fluent interface for all setter and factory methods.
So, configuration can be done by combining various calls.

In addition, you can also use the creation methods described in the previous chapter since the
result is always an instance of the Url class. After creation the parameters and properties
can be adapted like this:

The link schemes delivered with the APF include the logic to remove a parameter in case it's
value is null. Since this is a special interpretation of these link schemes this is no
common behaviour of all LinkScheme implementations!

If you intend to generate only few links using a dedicated link scheme (e.g. for AJAX or external
urls) you are able to pass a special link scheme to the generateUrl() call. This call
then overwrites the global link scheme:

PHP code

use APF\tools\link\LinkGenerator;
use APF\tools\link\Url;
use VENDOR\..\link\AjaxLinkScheme;
$ajaxUrl = LinkGenerator::generateUrl(Url::fromString('news.php')
->setQueryParameter('page', 4), new AjaxLinkScheme());

As you can take from the code block the second argument takes a newly generated link scheme. For
convenience, you can also re-use an existing link scheme to be configured for the current case:

Each front controller action has a property that defines whether the action's representation
should be kept in the url or not. This is - as described in
chapter 7
- a technical way, the decoupling of software components via the url is realized for the APF.
For the developer this possibility is especially interesting in case an action should remain
within the url for application management purposes but the application executed "within"
this action should not know about that.

The functionality described in the last paragraph is already part of the APF link scheme
implementations. In case of custom link schemes the automatic inclusion of front controller
actions must be implemented as desired!

Nevertheless, this chapter mainly deals with links that address dedicated actions that are not
marked to be kept within each url. For this reason, the LinkGenerator::generateActionUrl()
is provided. This method can generate action links by a basic url, the action's namespace and
name as well as a set of parameters:

In case te base url already contains a permanent action instruction the explicit action instruction
is added at the end. The main difference between the action link generation and the normal method
is the fact, that the action parameters are passed as independent arguments.

Moreover, the generation of action urls can be done using adapted base urls. For this reason all
methods described in chapter 3.2 can be used.

As you have seen for LinkGenerator::generateUrl(),
LinkGenerator::generateActionUrl() accepts a custom link scheme, too:

In case you intend to generate an action URL using LinkGenerator::generateActionUrl() including an action
that has the $keepInUrl flag set to true the action instruction is potentially doubled. This is
prevented by the shipped APF LinkScheme implementations to avoid multiple action executions and parameter
interferences.

Please note that with the given scenario the action definition applied to the corresponding LinkScheme by
LinkGenerator::generateActionUrl() makes it into the URL. Action representations contained within the
URL that have been added due to the $keepInUrl flag are discarded.

Anchor support is also available for action URLs. Please note chapter 3.2
for details.

As already mentioned in the previous chapters the APF provides two link schemes:
DefaultLinkScheme and RewriteLinkScheme. They implement the
LinkScheme interface and can be configured for some special cases.

At present, the configuration switches regard the activation or deactivation of the ampersand
(&) encoding feature. In case you do not want the ampersand to be encoded, you can do something
like this:

The above described concept has been designed for flexibility but also for enhancement.
Separation of the LinkGenerator from it's LinkSchemes enables you to inject
an absolutely new link scheme without having to change the functionality.

In order to guarantee such flexibility it is important to use a generic internal url layout that
can be transformed to the desired representation of the currently active link scheme.

The next two chapters describe the enhancement of the link generation mechanism of the APF.

A link scheme is defined by the LinkScheme interface. In order to implement a custom
scheme you have to implement the methods formatLink() and formatActionLink()
as well as setEncodeAmpersands() and getEncodeAmpersands().

The former two functions are intended to generate the desired url layout from the applied url
abstraction. Having a look at the next code sample you can see an implementation, that uses the
current page identifier as an url path and adds all further parameters as a "real"
request parameters. Sample: