Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Page Link Type Extension Laravel Package

anomaly/page_link_type-extension

Anomaly Page Link Type Extension adds a Page link type to PyroCMS Streams Platform link fields, letting editors browse and select pages from the Pages module. It creates page-aware links without manual URLs and integrates with Anomaly link type field types for streamlined content authoring.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. This extension is a link type for anomaly/navigation-module and resolves its target through anomaly/pages-module. It is inert without both, so install the Navigation and Pages modules first and confirm they are working in the admin before touching this package.

Install.

composer require anomaly/page_link_type-extension
php artisan addon:install anomaly.page_link_type_extension

Then verify the addon appears as installed under Admin → Addons.

Where to look first. Open the package and read, in order:

  1. src/PageLinkTypeExtensionServiceProvider.php — how the link type is bound/registered.
  2. The link type class itself (e.g. src/PageLinkTypeExtension.php) — it extends the Navigation module's LinkType base and defines name(), slug(), form(), and url(). form() is where the page-picker field is defined; url() is where the stored page is resolved into a path.
  3. The parent Anomaly\NavigationModule\Link\LinkType\LinkType class in vendor/anomaly/navigation-module — this is the real contract you will care about.

First use case. The entire point of the package: build a menu whose entries follow a page's slug instead of a hard-coded URL.

  1. Admin → Navigation → edit a menu → Add Link.
  2. Set Type to Page, then pick a page from the dropdown the extension renders.
  3. Save, then change that page's slug in the Pages module. Re-render the menu — the link updates automatically. That is the feature; a plain URL link type would go stale.

Render the menu in a view/plugin (Twig) and iterate links, reading url() rather than raw attributes.

Implementation Patterns

Render links through the link object, not the model column. The stored value is an identifier for the page, not a path. Always let the type resolve it:

{% for link in navigation('main').links %}
    <li>
        <a href="{{ link.url() }}"{% if link.target %} target="{{ link.target }}"{% endif %}>
            {{ link.title ?: link.url() }}
        </a>
        {% if link.children.count %}
            {# recurse / include a partial #}
        {% endif %}
    </li>
{% endfor %}

In Blade/PHP, the same call works: $link->url(). Treat the url column on the link row as meaningless for this type.

Programmatic link creation (seeders, data migrations, imports). Create the link with the type slug and the page identifier in the entry column, then let the type resolve at render time:

$link = $menu->links()->create([
    'type'      => 'page',          // confirm the slug from the link type class
    'entry_id'  => $page->getId(),  // column name may differ; check the navigation migration
    'title'     => $page->getTitle(),
    'target'    => '_self',
]);

Do this in preference to inserting a raw URL — it survives slug changes and keeps the admin UI consistent.

Constrain the picker by subclassing. The common customization request is "only let editors link to pages under /docs" or "exclude the homepage." Extend the package's link type, override the form() method to add your own select field with a filtered PagesRepository query (or override url() to add a guard), and register your subclass in your own service provider with a new slug()/name(). Do not edit the vendor package.

Pair with link permissions. The Navigation module stores allowed roles per link; combine that with page visibility so a menu item is both permitted and points at a published page. Guard against showing a link to a draft page by checking the resolved value before printing the <a>.

Nested menus. The page link type composes fine with Navigation's parent/child structure, so a full site tree can be built entirely from page links — slug renames then propagate through the whole nav without a content release.

Integration tip: one source of truth. If a page exists in Pages and a link exists in Navigation, resist the temptation to also store the path in a custom field. Pull the path from link.url() everywhere, including sitemaps and canonical tags.

Gotchas and Tips

Orphaned links after page deletion. The link stores a page reference, not a copy. Deleting or unpublishing the page leaves a link that resolves to nothing — url() may return null or an unexpected value depending on the parent implementation. Always wrap navigation output:

{% if link.url() %}<a href="{{ link.url() }}">{{ link.title }}</a>{% endif %}

Namespace vs. slug confusion. The composer package is anomaly/page_link_type_extension, but the addon slug used for install/uninstall and the link type slug used in the type column are two different strings. Read the link type class for the exact slug() value before writing seeders or migration updates.

Cache invalidation. Menu output is frequently cached, and link resolution happens at render time. After renaming a page slug, clear the application cache (php artisan cache:clear) and any view/HTTP cache you use before concluding the extension is broken. When it works, the "URL didn't change" complaint is almost always stale cache.

Install order and version pinning. This package tracks the Navigation module's API. Pin it alongside the platform:

composer require "anomaly/page_link_type-extension:^1.0" "anomaly/navigation-module:^3.0"

With zero stars and zero dependents there is little community signal, so treat upgrades as manual QA: after any Navigation or Pages module update, open one menu with a page link and confirm the picker still loads and the URL still resolves.

Large page trees. The picker typically loads the page list to populate the select. On sites with hundreds of pages this makes the link form slow. If that bites, that is the moment to write the constrained subclass described above rather than accept the full tree.

Multi-locale / multisite. Page identity is per site/locale in the Pages module. A menu built for one locale will not automatically repoint for another; build one menu per locale and re-pick pages there, verifying in each locale that the link resolves to a translated page rather than falling back or 404ing.

Debugging checklist when a link goes nowhere. In order: (1) does the page exist and is it published? (2) does the link row have the page identifier in the entry column? (3) does link.type match the extension's slug? (4) is the extension installed and enabled in Addons? (5) is the cache stale? Logging $link->url() at the top of the render loop answers all five quickly.

Extension points worth knowing. The link type base class is the seam for customization — subclass for filtering, for labels, or for URL decoration (prefixing with a domain, appending query strings). Keep custom types in your own addon so composer update never clobbers them.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin