定制 brenofortunato/laravel-quiz 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

brenofortunato/laravel-quiz

Composer 安装命令:

composer require brenofortunato/laravel-quiz

包简介

Library for adding questionnaires into a Laravel project.

README 文档

README

Pacote para adicionar questionários a um projeto Laravel.

Requisitos Mínimos

  • PHP 7.0
  • Laravel 5.8
  • Laravel Datatables 9.0

Instalação

Para instalar, basta utilizar o comando abaixo:

composer require brenofortunato/laravel-quiz

Em seguida, publique os assets:

php artisan vendor:publish --provider="PandoApps\Quiz\QuizServiceProvider"

Configuração

Certifique-se de que não existam tabelas com os nomes questionnaires, question_types, questions, alternatives, executables e answers. Caso existam, remova-as ou renomeie-as, não se esqueça dos models, views e tudo o que tiver relação com as tabelas citadas. Quando estiver pronto, execute a migration:

php artisan migrate

Em seguida, execute o seeder QuestionTypeSeeder:

php artisan db:seed --class=QuestionTypeSeeder

Abra o arquivo config/quiz.php e edite o array models para atender suas necessidades, conforme descrições abaixo:

	'models' => [
		'executable'               => App\User::class,      // Model que responderá o questionário
		'executable_column_name'   => 'name',               // Nome da coluna que representa a descrição do model que executa o questionário
		'parent_type'              => App\Holding::class,   // Model que é dono do questionário
		'parent_id'                => 'holding_id',         // Nome da coluna que representa a FK para o model que é dono do questionário
		'parent_url_name'          => 'holdings',           // Nome da tabela do model que é dono do questionário
	]

Adicione os relacionamentos abaixo ao model que responderá o questionário (no caso do exemplo acima, em User):

	/**
     * @return \Illuminate\Database\Eloquent\Relations\MorphMany
     **/
    public function executables()
    {
        return $this->morphMany(\PandoApps\Quiz\Models\Executable::class, 'executable');
	}

	/**
	 * @return \Illuminate\Database\Eloquent\Relations\MorphToMany
	 **/
	public function answeredQuestionnaires()
	{
		return $this->morphToMany(\PandoApps\Quiz\Models\Questionnaire::class, 'executable')->withPivot('id', 'score', 'answered')->withTimestamps();
	}

E o relacionamento abaixo ao model que é dono do questionário (no caso do exemplo, em Holding):

	/**
	* @return \Illuminate\Database\Eloquent\Relations\MorphMany
	**/
	public function questionnaires()
	{
		return $this->morphMany(\PandoApps\Quiz\Models\Questionnaire::class, 'parent');
	}

Adicione as rotas em routes/web.php:

	Route::group(['prefix' => config('quiz.models.parent_url_name'). '/{' . config('quiz.models.parent_id'). '}'], function () {
		Route::group(['prefix' => 'questionnaires'], function () {
			Route::get('/',                                          ['as'=>'questionnaires.index',   'uses'=>'\PandoApps\Quiz\Controllers\QuestionnaireController@index']);
			Route::get('/create',                                    ['as'=>'questionnaires.create',  'uses'=>'\PandoApps\Quiz\Controllers\QuestionnaireController@create']);
			Route::post('/',                                         ['as'=>'questionnaires.store',   'uses'=>'\PandoApps\Quiz\Controllers\QuestionnaireController@store']);
			Route::get('/{questionnaire_id}',                        ['as'=>'questionnaires.show',    'uses'=>'\PandoApps\Quiz\Controllers\QuestionnaireController@show']);
			Route::match(['put', 'patch'], '/{questionnaire_id}',    ['as'=>'questionnaires.update',  'uses'=>'\PandoApps\Quiz\Controllers\QuestionnaireController@update']);
			Route::delete('/{questionnaire_id}',                     ['as'=>'questionnaires.destroy', 'uses'=>'\PandoApps\Quiz\Controllers\QuestionnaireController@destroy']);
			Route::get('/{questionnaire_id}/edit',                   ['as'=>'questionnaires.edit',    'uses'=>'\PandoApps\Quiz\Controllers\QuestionnaireController@edit']);
		});

		Route::group(['prefix' => 'questions'], function () {
			Route::get('/',                                         ['as'=>'questions.index',   'uses'=>'\PandoApps\Quiz\Controllers\QuestionController@index']);
			Route::get('/{question_id}',                            ['as'=>'questions.show',    'uses'=>'\PandoApps\Quiz\Controllers\QuestionController@show']);
			Route::match(['put', 'patch'], '/{question_id}',        ['as'=>'questions.update',  'uses'=>'\PandoApps\Quiz\Controllers\QuestionController@update']);
			Route::delete('/{question_id}',                         ['as'=>'questions.destroy', 'uses'=>'\PandoApps\Quiz\Controllers\QuestionController@destroy']);
			Route::get('/{question_id}/edit',                       ['as'=>'questions.edit',    'uses'=>'\PandoApps\Quiz\Controllers\QuestionController@edit']);
		});

		Route::group(['prefix' => 'alternatives'], function () {
			Route::get('/',                                        ['as'=>'alternatives.index',   'uses'=>'\PandoApps\Quiz\Controllers\AlternativeController@index']);
			Route::get('/{alternative_id}',                        ['as'=>'alternatives.show',    'uses'=>'\PandoApps\Quiz\Controllers\AlternativeController@show']);
			Route::match(['put', 'patch'], '/{alternative_id}',    ['as'=>'alternatives.update',  'uses'=>'\PandoApps\Quiz\Controllers\AlternativeController@update']);
			Route::delete('/{alternative_id}',                     ['as'=>'alternatives.destroy', 'uses'=>'\PandoApps\Quiz\Controllers\AlternativeController@destroy']);
			Route::get('/{alternative_id}/edit',                   ['as'=>'alternatives.edit',    'uses'=>'\PandoApps\Quiz\Controllers\AlternativeController@edit']);
		});

		Route::group(['prefix' => 'executables'], function () {
			Route::get('/',                                     ['as'=>'executables.index',         'uses'=>'\PandoApps\Quiz\Controllers\ExecutableController@index']);
			Route::get('/{questionnaire_id}/questionnaire',     ['as'=>'executables.statistics',    'uses'=>'\PandoApps\Quiz\Controllers\ExecutableController@statistics']);
			Route::get('{executable_id}/',                      ['as'=>'executables.show',          'uses'=>'\PandoApps\Quiz\Controllers\ExecutableController@show']);
			Route::get('{questionnaire_id}/create/{model_id}',  ['as'=>'executables.create',        'uses'=>'\PandoApps\Quiz\Controllers\ExecutableController@create']);
			Route::post('{questionnaire_id}/store',             ['as'=>'executables.store',         'uses'=>'\PandoApps\Quiz\Controllers\ExecutableController@store']);
			Route::post('start',                                ['as'=>'executables.start',         'uses'=>'\PandoApps\Quiz\Controllers\ExecutableController@start']);
		});

		Route::group(['prefix' => 'answers'], function () {
			Route::get('/',                                     ['as'=>'answers.index',   'uses'=>'\PandoApps\Quiz\Controllers\AnswerController@index']);
			Route::get('/{answer_id}',                          ['as'=>'answers.show',    'uses'=>'\PandoApps\Quiz\Controllers\AnswerController@show']);
		});
	});

Adicione o questionário ao menu em resources/views/layouts/menu.blade.php, substituindo request()->PARENT_ID pelo correspondente em seu caso (no exemplo, seria request()->holding_id):

	<li class="{{ (Request::is('*questionnaires*') || Request::is('*questions*') || Request::is('*alternatives*')) ? 'active' : '' }}">
		<a href="{!! route('questionnaires.index', request()->PARENT_ID) !!}"><i class="far fa-list-alt sidebar-icons"></i><span>{!! \Lang::choice('tables.questionnaires','p') !!}</span></a>
		@if(Request::is('*questions*') && request()->questionnaire_id)
			<ul class="treeview-menu">
				<li class="{{ Request::is('*questions*') ? 'active text-bold' : '' }}">
					<a class="treeview-link" href="{!! route('questions.index', [request()->PARENT_ID, 'questionnaire_id' => request()->questionnaire_id]) !!}"><i class="fas fa-question sidebar-icons-treeview"></i><span>{!! \Lang::choice('tables.questions','p') !!}</span></a>
				</li>
			</ul>
		@endisset
		@if(Request::is('*alternatives*') && request()->question_id)
			<ul class="treeview-menu">
				<li class="{{ Request::is('*alternatives*') ? 'active text-bold' : '' }}">
					<a class="treeview-link" href="{!! route('alternatives.index', [request()->PARENT_ID, 'question_id' => request()->question_id]) !!}"><i class="fas fa-check-square sidebar-icons-treeview"></i><span>{!! \Lang::choice('tables.alternatives','p') !!}</span></a>
				</li>
			</ul>
		@endisset
	</li>

Adicione as traduções das tabelas em resources/lang/pt_BR/tables.php:

	'questionnaires'        => '[s] Questionário         |[p] Questionários',
	'questions'             => '[s] Questão              |[p] Questões',
	'alternatives'          => '[s] Alternativa          |[p] Alternativas',
	'question_types'        => '[s] Tipo da Questão      |[p] Tipo das Questões',
	'answers'               => '[s] Resposta             |[p] Respostas',

Personalização

As instruções abaixo não são necessárias, mas servem de orientação para uma maior personalização do pacote.

Caso queira modificar as traduções exibidas nas datatables, edite o arquivo resources/lang/vandor/pandoapps/pt_BR/datatable.php.

Caso queira modificar as views, edite os arquivos no diretório resources/views/vendor/pandoapps.

Para modificar as datatables, crie um cópia delas em app/DataTables. Utilize os arquivos abaixo como base (não se esqueça de mudar o namespace para App\DataTables):

Para modificar as controllers, crie um cópia delas em app/Http/Controllers. Utilize os arquivos abaixo como base (não se esqueça de mudar o namespace para App\Http\Controllers):

Ao modificar as controllers, não se esqueça de atualizar as rotas. Por exemplo, se QuestionnaireController for modificada, altere o atributo uses do bloco sob o prefixo questionnaires para:

	Route::group(['prefix' => 'questionnaires'], function () {
		Route::get('/',                                          ['as'=>'questionnaires.index',   'uses'=>'QuestionnaireController@index']);
		Route::get('/create',                                    ['as'=>'questionnaires.create',  'uses'=>'QuestionnaireController@create']);
		Route::post('/',                                         ['as'=>'questionnaires.store',   'uses'=>'QuestionnaireController@store']);
		Route::get('/{questionnaire_id}',                        ['as'=>'questionnaires.show',    'uses'=>'QuestionnaireController@show']);
		Route::match(['put', 'patch'], '/{questionnaire_id}',    ['as'=>'questionnaires.update',  'uses'=>'QuestionnaireController@update']);
		Route::delete('/{questionnaire_id}',                     ['as'=>'questionnaires.destroy', 'uses'=>'QuestionnaireController@destroy']);
		Route::get('/{questionnaire_id}/edit',                   ['as'=>'questionnaires.edit',    'uses'=>'QuestionnaireController@edit']);
	});

brenofortunato/laravel-quiz 适用场景与选型建议

brenofortunato/laravel-quiz 是一款 基于 HTML 开发的 Composer 扩展包,目前已累计 1 次下载、GitHub Stars 达 0, 最近一次更新时间为 2020 年 09 月 22 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「laravel」 「quiz」 「questionnaire」 「question」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 brenofortunato/laravel-quiz 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 brenofortunato/laravel-quiz 我们能提供哪些服务?
定制开发 / 二次开发

基于 brenofortunato/laravel-quiz 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 1
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 16
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 3
  • 开发语言: HTML

其他信息

  • 授权协议: MIT
  • 更新时间: 2020-09-22