Download the PHP package tahsin000/snag without Composer

On this page you can find all versions of the php package tahsin000/snag. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package snag

Snag

Let users point at what's broken.

A portable feedback widget for Laravel Blade applications. Install it, add one line to your layout, and every page gets a slim tab on the edge of the screen. People drag a box around the part that is wrong, describe it, and the report lands in your own database - with the page context and that cropped region attached.

No screen-sharing permission. No build step. No frontend framework.

That is the entire integration.


Features


Requirements

Requirement Version
PHP 8.1+ (whatever your Laravel version already requires)
Laravel 9.x, 10.x, 11.x, 12.x, 13.x
Database Any Laravel-supported driver with JSON column support (MySQL 5.7+, MariaDB 10.2+, PostgreSQL, SQLite)

Installing Snag never forces you to upgrade Laravel, PHP or any other dependency. The package depends only on the individual illuminate/* components it actually uses, pins no Symfony version of its own, and requires no frontend toolchain.


Installation

The service provider is registered automatically through Laravel package discovery.

Publish and run the migration:

Optionally publish the configuration:

Add the widget to your main Blade layout, once:

Every page using that layout now has the widget. That's it.


Configuration

The package works with its defaults; publishing the config is only needed to change them.

Key What it does
enabled Master switch. When false the widget renders nothing and the endpoint returns 404.
table Database table name. Change it if feedback collides with an existing table.
route.prefix Endpoint path. Default POST /_snag.
route.middleware Middleware stack for the endpoint. Add auth to require login.
actor_resolver Class implementing ActorResolver. See below.
suggestion_provider Reserved extension point; the default does nothing.
types Key ⇒ label map. Keys are persisted; add your own freely.
validation.message_min / message_max Message length bounds.
widget.position Which edge the tab sits on: middle-right, middle-left, bottom-right or bottom-left. Unknown values fall back to middle-right. The panel opens against the same edge.
widget.theme auto (follows the OS), light or dark.
widget.color Optional accent hex color (#rgb or #rrggbb). Anything else is ignored; the button text color is chosen automatically for contrast.
widget.screenshot Enables the crop tool. Requires attachments.enabled. See below.
widget.screenshot_library_url Where the browser loads html2canvas from. null serves it from the package route, which needs no publishing.
widget.* labels Every string in the UI.
context.* Per-field switches for context collection. Turn any of them off.
attachments.enabled When false the file field disappears and any uploaded file is rejected.
attachments.disk Any configured filesystem disk.
attachments.directory Base directory on the disk. Files land in {directory}/{Y}/{m}/{uuid}.{ext}.
attachments.max_size_kb Maximum upload size in kilobytes.
attachments.allowed_mimes Extension allowlist, verified server side.

Configuration is cached and serialized by config:cache, so this file must contain only scalars, arrays and class-strings - never closures. Re-run php artisan route:cache after changing route.prefix or route.middleware.


The crop tool

Browsers cannot take a true pixel screenshot from JavaScript. The only native route is getDisplayMedia(), which raises the browser's own "share your screen" prompt - a permission most people decline, for a task as small as reporting a typo.

So this package does not use it. Instead the crop tool renders the page's own DOM into a canvas with html2canvas, entirely in the browser:

  1. The user opens the panel and presses Select an area of the page.
  2. The panel steps aside and the page dims.
  3. They drag a box around the part that is wrong. Escape cancels.
  4. That region - and only that region - is rendered, attached, and previewed in the panel.
  5. They describe the problem and submit.

Nothing leaves the browser until the form is submitted, and the whole step is optional: the manual upload field is always there, and skipping the capture says nothing and shows nothing.

What it can and cannot draw. html2canvas re-renders the DOM; it does not photograph the screen. It handles text, layout, backgrounds, borders and same-origin images well. It cannot see inside cross-origin <iframe>s, and cross-origin images need Access-Control-Allow-Origin to appear. The widget itself is excluded from every capture.

Serving the library. By default it is served from GET {prefix}/html2canvas.js, cached for a year and fetched only when someone first uses the tool. Nothing needs publishing. To serve it yourself instead:

then point the config at it:

Set 'screenshot' => false to remove the tool, its markup and its route usage entirely.

Environment variables


Authentication

Guest feedback

Works out of the box. With the default middleware anyone who can see the page can submit feedback, and the actor columns are left null.

Authenticated feedback

Nothing to configure - if $request->user() returns something, the default resolver records its class, identifier, name and email when those exist.

Authenticated only

Add auth to the endpoint middleware:

The package core never requires authentication.


Custom Actor Resolver

The package deliberately knows nothing about your identity model. To capture your own shape, implement the contract:

Point the config at it:

ActorData::$metadata is stored under metadata.actor in the feedback row.

Actor details are a snapshot taken at submission time, not a foreign key. The package never creates a relationship to your users table, so feedback survives user deletion and the package stays installable in any application.


Attachments

Users may attach one image. Files are validated server side against allowed_mimes and max_size_kb, then stored under a generated path - the uploaded filename never influences where the file lands.

Disable them entirely:

Automatic screenshot capture is deliberately not included: it requires a JavaScript dependency and browser-specific handling. It is reserved for a future optional provider.


Events

Every stored submission dispatches FeedbackSubmitted:

Register it as you normally would (auto-discovery, or in your EventServiceProvider).

Integrations live in your application - the package ships none, so it stays dependency free.


Swapping persistence

FeedbackRepository is a contract. Bind your own implementation to store feedback somewhere else - a remote API, another connection, a queue:

The submission action, validation and widget are unaffected.


Customizing views

Publish them:

The views land in resources/views/vendor/snag/:

Re-theming without publishing

Every colour, radius, spacing and font value is a CSS custom property scoped to .snag-root. Override them from your own stylesheet - no publishing required:

All package styles are namespaced with snag-, use no bare element selectors, and are wrapped in @once so including the widget more than once on a page still emits one stylesheet.


Disabling the package

The widget renders an empty string and the endpoint answers 404 - a disabled package does not advertise its endpoint.


Removing the package

Then remove @include('snag::widget') from your layout. Optionally delete the published config, the published views, the feedback table and any stored attachments. Nothing else in your application is touched.


Testing

The suite runs against a real Laravel application through Orchestra Testbench, with an in-memory SQLite database.

To run a single older lane locally, pin its Testbench and PHPUnit — Testbench selects the Laravel branch, because laravel/framework replaces illuminate/*:

Test methods are named test_* and carry #[Test]. The name is what PHPUnit 9 (the Laravel 9 lane) matches on; the attribute is inert there and authoritative from PHPUnit 10 on. Keep both when adding tests, and do not use the /** @test */ annotation — it was removed in PHPUnit 12.


Version compatibility

Laravel PHP Testbench PHPUnit PHPUnit config
9.x 8.1, 8.2 7.x 9.6 phpunit9.xml.dist
10.x 8.1, 8.2, 8.3 8.x 10.5 phpunit.xml.dist
11.x 8.2, 8.3, 8.4 9.x 10.5 phpunit.xml.dist
12.x 8.2, 8.3, 8.4 10.x 11.x phpunit.xml.dist
13.x 8.3, 8.4 11.x 12.x phpunit.xml.dist

Compatibility is claimed only for combinations covered by CI. Every lane installs its own dependency set and runs both --prefer-lowest and --prefer-stable: a green Laravel 13 run proves nothing about Laravel 9, so each version is exercised independently.

One codebase covers the whole range. There are no per-version classes; the only version-conditional line in the package is the migration publishing guard described below.

Notes for Laravel 9 and 10


Security

Found a vulnerability? See SECURITY.md - please do not open a public issue.


Publishing this package

Tag releases with Git; do not add a version key to composer.json.

Then submit the public repository URL at packagist.org and enable the GitHub webhook so new tags sync automatically.

Local development against a real application


Contributing

See CONTRIBUTING.md.

License

MIT. See LICENSE.


All versions of snag with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
illuminate/contracts Version ^11.0|^12.0|^13.0
illuminate/database Version ^11.0|^12.0|^13.0
illuminate/filesystem Version ^11.0|^12.0|^13.0
illuminate/http Version ^11.0|^12.0|^13.0
illuminate/routing Version ^11.0|^12.0|^13.0
illuminate/support Version ^11.0|^12.0|^13.0
illuminate/validation Version ^11.0|^12.0|^13.0
illuminate/view Version ^11.0|^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package tahsin000/snag contains the following files

Loading the files please wait ...