coyote6/laravel-forms

用于生成表单HTML并协助Laravel中的验证过程的简单类,可选Livewire和Tailwind集成。

v0.5.13 2023-12-05 16:47 UTC

README

关于项目

Laravel Forms是一个基于类的表单包,用于生成表单HTML并协助Laravel中的简单验证过程。该项目仍在开发中,因此文档将逐步完善。

先决条件

  • PHP 8.0或更高版本
  • 安装Laravel 8+

入门

通过composer安装

composer require coyote6/laravel-forms

可选 - 将配置文件复制到您的配置文件夹。

php artisan vendor:publish --tag=laravel-forms

使用方法

基本示例

在控制器文件中

use Coyote6\LaravelForms\Form\Form;

$form = new Form();

$field1 = $form->text('field-name--1');		// Returns the field object
$field1->addRule ('min', '5');
$field1->label = 'Field 1';
$field1->required();

$form->textarea ('field-name--2')
	->label('Field 2')						// Chained label and placeholder
	->placeholder('Field 2');

在Blade模板中

{!! $form !!}

最佳实践

为了最佳使用,建议在控制器中设置自己的私有/受保护的表单方法,以便它可以用于验证。

在控制器文件中

namespace App\Http\Controllers;

use Coyote6\LaravelForms\Form\Form;
use Illuminate\Http\Request;


class HomeController extends Controller  {
	
	
	protected function form () {

		static $form;						// Create a singleton to keep form ids the same when validating.
		
		if (is_null ($form)) {
			$form = new Form();
			$form->action ('/home');		// Default action is '#' so it will submit to the same page if not set.
			$form->method ('POST');			// Available methods GET, POST, PUT, or DELETE
			
			$form->email('email')	
				->placeholder ('Please, Enter Your Email Address')
				->required();
			
			$form->checkbox ('tos')
				->label ('You must agree to our ToS.')
				->required();
		}
		
		return $form;
		
	}


	public function create () {
		return view ('home',['form'=> $this->form()]);
	}
	
	
	public function store () {
		$this->form()->validate();
		return ['success'];
	}

}

验证

$form = new Form();
$form->action ('/home')
	->method ('PUT');

$form->text ('username')
	->label ('Username')
	->required()
	->addRules (['min:8', 'max:255', 'unique:users']);	// Add laravel validation rules as an array.

$form->email ('email')
	->label ('Email')
	->required()
	->addRule ('max:255')								// Add laravel validation rules individually
	->addRule ('unique', 'users')
	->confirm()											// Automatically adds extra confirm field and validates it.
	->label ('Email Confirmation');						// Return value is the confirmation field.

$form->password ('password')
	->label ('Password')
	->required()
	->addRules (['min:5', 'max:255'])
	->removeRule ('max')								// Remove rules by their name
	->confirm()
	->label ('Password Confirmation');

// Default submit button gets automatically added, unless told otherwise.
if (isset ($_POST['submit'])) {
	$validatedData = $form->validate();
	return $validatedData;
}

与Livewire一起使用

在您的应用程序的基本Blade模板中,在调用@livewireScripts之后,如果您还没有这样做,添加一个stack('scripts')调用。

@stack('scripts')

在组件(基本方法)中

 
namespace App\Http\Livewire;
 
use Livewire\Component;
use Coyote6\LaravelForms\Form\Form;
 
class Example extends Component {
	 
	 
	public $email = '';
	public $password = '';
	public $passwordConfirmation = '';
	
	
	protected function rules() {
		return $this->form()->lwRules();					// lwRules() is an alias to livewireRules()
	}
    	
	public function updated ($field) {
		$this->validateOnly($field);
	}
	
	
	public function render () {
		return view ('livewire.example', ['form' => $this->form()]);		
	}
	
	 
	public function store () {
		
		$values = $this->validate();  
		return ['success' => $values];
		
	}
	
	
	// Optionally set up a store method as a fallback in case someone shuts off JavaScript
	public function storeFallback () {
		$values = $this->form()->validate();
		return ['success' => $values];
	}
	
	
	public function form () {
		
		static $form;										// Create a singleton to keep form ids the same when validating.
		
		if (is_null ($form)) {
			
			$form = new Form ($this);						// Sets up the form as a Livewire form... 
															// alternatively you can call $form->isLivewireForm($this);	
											
			$form->action ('/store')						// Optional fallback in case someone shuts off Javascript
				->method('POST')
				->addAttribute ('wire:submit.prevent', 'store');
			
			$form->email ('email')
				->label ('Email')
				->livewireModel ('email')
				->required()
				->addRule('unique:users');
			
			$p = $form->password ('password')
				->label ('Password')
				->lwModel()									// lwModel() & lw() are aliases to livewireModel() method
															// If no value is passed, the name is used for the livewire model.
				->addRule ('min:6');
			
			$pc = $p->confirm();
			$pc->label ('Confirm Password')
				->lwModelLazy ('passwordConfirmation');		// Use livewireModelLazy(), lwModelLazy(), lwLazy() to call wire:model.lazy 
			
			//
			// Use getLivewireModel(), getLwModel(), getLw() methods to retrieve the Livewire model name.
			// $pc->getLw();
			//
		
		}
		return $form;
		
	}
	
}

在组件(使用Coyote6\LaravelForms\Livewire\Component)中

 
namespace App\Http\Livewire;
 
use Coyote6\LaravelForms\Livewire\Component;
use Coyote6\LaravelForms\Form\Form;
 
class Example extends Component {
	 
	 
	public $email = '';
	public $password = '';
	public $passwordConfirmation = '';
	
	
	// Optional
	public function template () {
		return 'livewire.example';
	}	
	 
	public function store () {
		
		$values = $this->validate();  
		return ['success' => $values];
		
	}
	
	
	// Optionally set up a store method as a fallback in case someone shuts off JavaScript
	public function storeFallback () {
		$values = $this->form()->validate();
		return ['success' => $values];
	}
	
	
	public function generateForm () {
		
		$form = new Form ([
			'lw' => $this, 
			'cache' => false,
			'theme' => 'minimal'
		]);
		
		$form->addAttribute ('wire:submit.prevent', 'store');
		
		$form->email ('email')
			->lwLazy()
			->label ('Email')
			->required()
			->addRule('unique:users');
		
		$form->password ('password')
			->lwLazy()
			->label ('Password')
			->addRule ('min:6')
			->confirm()
			->label ('Confirm Password')
			->lwLazy ('passwordConfirmation');
		
		$form->submitButton ('submit')
			->content ('Comfirm');

		return $form;

	}
	
}

在Livewire Blade模板中

{!! $form !!}

在Web路由文件中 -- 可选

Route::post('/store', 'App\Http\Livewire\Example@storeFallback');

与Tailwind CSS一起使用

现在,Tailwind是表单的默认主题。您必须已经购买、安装并配置了Tailwind。

一些非Tailwind类会自动添加到项目。这些是通用的类名,如.form-item、.label、.field等。您可以在.env文件中使用以下方式关闭它们:

FORM_DEFAULT_CLASSES=false

或者如果您已发布配置文件,可以将default-classes设置为false。

如果您想更改默认的Tailwind类,它们存储在配置文件的类部分。此外,还有其他样式选项在此设置。

主题化

您可以通过几种方式主题化表单。

第一种,如上所述,是编辑配置文件并覆盖类。

另一种是将-/-src/Resources/views/-目录中的文件复制到您的应用程序的-/-resources/views/-目录。包将检查您的目录中的文件,并使用它覆盖默认文件。请确保在单个表单/字段或配置中设置主缓存为false。模板命名约定如下

-/-resources/views/forms/{$template}--{$element_id}.blade.php- -/-resources/views/forms/{$template}--{$element_name}.blade.php- -/-resources/views/forms/{$theme}/{$template}.blade.php- -/-resources/views/forms/{$template}--{$theme}.blade.php- -/-vendor/coyote6/laravel-forms/src/resources/views/forms/{$theme}/{$template}.blade.php- -/-vendor/coyote6/laravel-forms/src/resources/views/forms/{$template}--{$theme}.blade.php- -/-resources/views/forms/{$template}.blade.php- -/-vendor/coyote6/laravel-forms/src/resources/views/forms/{$template}.blade.php-

您可以将自定义类合并到模板中的任何属性变量中

<div {{ $attributes->merge([
	'class' => 'new classes'
]) }}></div>
// Or
<x-component :attributes="$attributes->merge(['class'=>'new classes'])"></x-component>

要针对某些表单使用主题,并从配置方法设置类,则在构建表单时设置主题。

$form = new Form (['theme' => 'minimal']);

如果您只想在不设置配置文件中的类的情况下覆盖模板,则可以在渲染或验证之前调用它。

$form->theme ('minimal');		// Using the method option is chainable
$field->theme ('minimal');

// Or set the property directly.
$form->theme = 'minimal';
$field->theme = 'minimal';

如果设置在构建时或添加字段之前,字段将继承其父级主题。

可用字段(更多即将到来)

按钮 - <button>

$form->button ('field-name')
	->value ('Button Value')								// Is the default button content unless the content property is set.
	->content ('This is what shows inside the button');

复选框 - <input type="checkbox">

$form->checkbox ('field-name')
	->value ('Value when submitted')	
	->label ('Click me');

电子邮件 - <input type="email">

简单电子邮件
$form->email ('field-name');
带有确认的电子邮件
$form->email ('field-name')
	->label ('Email')
	->confirm()
	->label ('Confirm Email');

字段组 - <div>

这只是一个包装了一组字段的容器。如果需要,它可以有一个标签。

$form->fieldGroup ('field-name')
	->label ('Contact Info');

文件 - <input type="file">

$form->file ('field-name')
	->label ('Upload File');
设置默认值、删除图片、无需Livewire检索图片
单个文件

注意:由于我没有时间测试,非Livewire文档可能已过时。

public function storeFallback () {

	$upload = request()->file('file');
	if (!is_null ($upload) && $upload->isValid()) {
		
		//
		// Save File using the Laravel method
		//
		// @see https://laravel.net.cn/docs/10.x/filesystem#file-uploads
		//
		
	}
	
	//
	// Note:
	// This still requires Livewire... need to revisit.
	//
	$removed = request()->input('fileRemove');
	if (!is_null ($removed) && is_array ($removed)) {
		$file = current ($removed);
		if ($file == '1') {
			
			//
			// Remove File
			//
			// This method depends on how you saved the file.
			//
			
		}
	}
	
}
	
	
protected function generateForm () {
	
	$form = form();
	$form->action('/post/path');
	
	$default = '/path/to/file.jpg';
	
	$form->file ('file')
		->label ('File')
		->value ($default);
	
	return $form;
	
}
多个文件
public function storeFallback () {

	$uploads = request()->file ('files');
	if (!is_null ($uploads) && is_array ($uploads)) {
		foreach ($uploads as $key => $upload) {
			if ($upload->isValid()) {
				
				//
				// Save File using the Laravel method
				//
				// @see https://laravel.net.cn/docs/10.x/filesystem#file-uploads
				//
		
			}
		}
	}
	
	//
	// Note:
	// This still requires Livewire... need to revisit.
	//
	$removed = request()->input('filesRemove');
	if (!is_null ($removed) && is_array ($removed)) {
		$file = current ($removed);
		if ($file == '1') {
			
			//
			// Remove File
			//
			// This method depends on how you saved the file.
			//
			
		}
	}
	
}
	
protected function generateForm () {
	
	$form = form();
	$form->action('/post/path');
	
	$default = [
		'/path/to/file.jpg'
	];
	
	$form->file ('files')
		->label ('Files')
		->multi()			// Alias to multiple ($maxFiles)
		->value ($default);
	
	return $form;
}
使用Livewire设置默认值、删除图片和获取图片

该字段将为Livewire组件添加4个额外的属性。这些属性包括之前上传的文件、之前上传后被删除的文件、所有最新的文件以及图片预览的临时访问时间。可以通过将'PreviousUploads'、'Removed'、'All'、'TempAccessTimes'添加到Livewire属性中来访问这些属性。例如,如果属性设置为$this->file,则可以通过$ this->filePreviousUploads、$this->fileRemoved、$this->fileAll、$this->fileTempAccessTimes分别访问这些值。

注意:$this->imageAll可能需要在表单生成或验证后才更新。

单个文件
public function store () {

	$this->validate();

	if ($this->file instanceof \Livewire\TemporaryUploadedFile) {
		
		//
		// Save File using the Livewire Temp File method
		//
		// @see https://laravel-livewire.com/docs/2.x/file-uploads#storing-files
		//
		$this->file->store ('dir');
		
	}
	

	foreach ($this->fileRemoved as $hash => $file) {
		
		//
		// Remove File
		//
		// This method depends on how you saved the file.
		//
		
	}
	
}
	
	
protected function generateForm () {
	
	$form = form();
	$form->action('/post/path');
	
	$default = '/path/to/file.jpg';
	
	$form->file ('file')
		->label ('File')
		->value ($default);
	
	return $form;
	
}
多个文件
public function store () {

	$this->validate();
	foreach ($this->files as $file) {
		
		// Save File using the Livewire Temp File method
		//
		// Multi File Method
		// @see https://laravel-livewire.com/docs/2.x/file-uploads#multiple-files
		// 
		$this->file->store ('dir');
		
	}
	

	foreach ($this->filesRemoved as $hash => $file) {
		
		//
		// Remove Files
		//
		// This method depends on how you saved the file.
		//
		
	}

	
}

protected function generateForm () {
	
	$form = form();
	$form->action('/post/path');
	
	$default = [
		'/path/to/file.jpg'
	];
	
	$form->file ('files')
		->label ('Files')
		->multi()			// Alias to multiple ($maxFiles)
		->value ($default);
	
	return $form;
}

隐藏的 - <input type="hidden">

$form->hidden ('field-name')
	->value = 'some value';

HTML - <div>

$form->html ('field-name')
	->content  ('<em>Custom Html Field</em>');
	

图片 - <input type="file">

这与文件字段相同,但仅限于图像文件。

$form->image ('field-name')
	->label ('Upload Image');

数字 - <input type="number">

$form->number ('field-name')
	->label ('Enter Your Lucky Number');

密码 - <input type="password">

简单密码
$form->password ('field-name')
	->label ('Password');
	
带确认的密码
$p = $form->password ('field-name')
	->label ('Password')
	->confirm()
	->label ('Password Confirm');
	

单选按钮 - <input type="radio">

简单单选按钮
$form->radios ('field-name')
	->label ("Please select an option")
	->addOptions([
	  'o1' => 'Option 1',
	  'o2' => 'Option 2',
	  'o3' => 'Option 3',
	  'o4' => 'Option 4'
	])
	->required();
带HTML的单选按钮
$r2 = $form->radios ('field-name')
	->required()
	->value ('o1');			// Set a default value
	    
$rb1 = new Radio ('field-name');
$rb1->label ('Option 1')
	->value ('o1')
	->init(); 				// When building directly from field classes,
							// initiating the theme/classes is optional, 
							// but required to add default and theme classes
	    
$h1 = new Html ('field-name--html-1');
$h1->value ('Cool HTML info about option 1');
	    
$rb2 = new Radio ('field-name');
$rb2->label ('Option 2')
	->value ('o2');
	->theme ('minimal')		// You must set the theme before calling init()
	->init();

$h2 = new Html ('field-name--html-2');
$h2->value ('Cool HTML info about option 2');

$r2->addField ($rb1);
$r2->addField ($h1);
$r2->addField ($rb2);
$r2->addField ($h2);

选择 - <select>

$s = $form->select ('field-name');
$s->addOptions([
  'o1' => 'Option 1',
  'o2' => 'Option 2',
  'o3' => 'Option 3',
  'o4' => 'Option 4'
]);
$s->required();

提交按钮 - <button> 或 <input type="submit">

渲染为主要/提交 <button>
$form->submitButton ('field-name')
	->value ('submit')
	->content ('Press me');			// $s->label becomes the content, if the content property is not set.
渲染为次要 <button>
$form->submitButton ('field-name')
	->value ('submit')
	->content ('Press me')
	->renderAsButton();
渲染为 <input type="submit">
$form->submitButton ('field-name')
	->value ('submit')
	->label ('Press me')
	->renderAsInput();

文本 - <input type="text">

$form->text ('field-name');

文本区域 - <textarea>

$form->textarea ('field-name');

未来还将推出更多字段。