aidynmakhataev/laravelsurveyjs
Laravel package for integrating SurveyJS: create and manage surveys, store form JSON, collect responses, and retrieve results via Eloquent models and ready-made routes, making dynamic survey forms easy to add to any Laravel app.
composer require aidynmakhataev/laravel-surveyjs
php artisan vendor:publish --provider="AidynMakhataev\LaravelSurveyJs\LaravelSurveyJsServiceProvider"
php artisan migrate
Where to look first, in order:
surveys for the SurveyJS JSON definition, survey_results for submitted answers). Read them before running so you can rename anything that collides.AidynMakhataev\LaravelSurveyJs\Models\Survey and SurveyResult. These are what you'll touch 95% of the time; everything else is yours to build.First use case: take a JSON export from the SurveyJS Designer, persist it, and render it.
use AidynMakhataev\LaravelSurveyJs\Models\Survey;
$survey = Survey::create([
'name' => 'Onboarding feedback',
'json' => json_decode(file_get_contents(resource_path('surveys/onboarding.json')), true),
]);
Controller: return view('survey.show', compact('survey'));
Blade:
<div id="surveyContainer"></div>
<script type="module">
import { Model } from "survey-core";
import { Survey } from "survey-ui"; // survey-js-ui
new Survey.Model(new Model(@json($survey->json))).render("surveyContainer");
</script>
Keep the designer JSON opaque. Don't shred the schema into your own questions/pages tables. Store it verbatim in the JSON column; the front end renders it directly and you stay compatible with whatever SurveyJS version the designer is on.
Result submission route. The canonical flow is survey.onComplete → POST sender.data → persist.
Route::post('/surveys/{survey}/results', function (Request $request, Survey $survey) {
$result = $survey->results()->create([
'json' => $request->input('data'),
'user_id' => auth()->id(),
]);
return response()->json(['id' => $result->id]);
})->middleware('auth');
Attach surveys to domain objects yourself. The package ships only survey + results. Add a surveyable morph or an FK in your own migration, then scope queries through your relation rather than querying Survey directly all over the app.
Version surveys, don't mutate them. Once results exist, treat json as immutable. On a schema change, clone the row (bump a version column), point new submissions at the clone, and leave old results pointing at the old definition. Otherwise you can't interpret historical answers.
Reporting. Answers are JSON. Use whereJsonContains / json_extract for light aggregation; anything heavier (dashboards, exports) belongs in a scheduled job that flattens results into a reporting table.
Front-end integration. Bundle survey-core + the UI package through Vite, not a CDN. Pin the major version to whatever authored the JSON.
composer.json constraints before installing on Laravel 9+. You may need a path repository / fork with widened constraints. Verify the migrations actually run on your version before assuming anything.NOASSERTION. Read LICENSE before shipping commercially. Separately, SurveyJS has its own dual license — the wrapper's license says nothing about your rights to the JS library.required/expression validators run client-side only. Re-validate the posted payload against $survey->json before persisting, or you will store garbage — especially since the endpoint is public by default.json to array on your Laravel version, subclass it and add protected $casts = ['json' => 'array'];.surveys and survey_results are generic. If you already have a surveys table, rename in the migration before migrate.survey_results.survey_id cascades on survey deletion; if not, add it in a migration or an observer, otherwise you orphan answers.vendor/.survey-core 2.x. Pin the same major on both sides and re-export schemas when you upgrade.How can I help you explore Laravel packages today?