I want to validate an enum in laravel, but it's not clear to me how to do this.
In my database I have an enum attribute and the migration converts the enum to an array type (e.g. enum('Delta','Statisch') -> array('Delta','Statisch')). But how do I validate the enum/ the data which I receive (how do I know which value of the enum has been selected and how can I ensure that the received value is part of the enum)?
This one is easy:
<?php
use Illuminate\Validation\Rule;
use Illuminate\Http\Request;
class DummyController extends Controller
{
public function store(Request $request)
{
$validatedData = $request->validate([
'filed_name' => ['required', Rule::in(['Delta','Statisch'])
]);
}
}
Checkout Laravel Docs for more info.
Try This
use Validator;
$validator = Validator::make([
'type' => 'in:Delta,Statisch', // DEFAULT or SOCIAL values
]);
Related
i'm trying to create a product which belongs only to one order. That order id i'm taking with me to create form, but don't know how to pull it to store function.
Updated files:
ProductController:
use Illuminate\Http\Request;
use App\Order;
use App\Product;
use Illuminate\Support\Facades\Route;
class ProductController extends Controller
{
public function create(Order $order){
return view('order.product-create', compact($order));
}
public function store(Order $order, Request $request){
$this->validate($request, [
'name'=>'required',
'drawing'=>'nullable|file',
'3d_file'=>'nullable|file',
'quantity'=>'integer',
'unit_price'=>'required',
'discount'=>'nullable'
]);
$order->products()->create($request->all());
session()->flash('product-created', 'New product was added successfully');
return redirect()->route('order.view');
}
}
Route:
Route::get('/order/{order}/product/create', 'ProductController#create')->name('product.create');
Route::post('/order/{order}/product', 'ProductController#store')->name('product.store');
view.blade.php ---> link to product create form
Add new product
product.create.blade.php ---> fragment to method action
action="{{route('product.store', ['order' => $order])}}"
so with this at the moment, i can't get in to product-create.blade.php with error $order is undefined
Dynamic parameters are defined as curly braces in your route file in routes/web.php or routes/api.php
// routes/web.php
Route::get('/order/{order}/product/create', 'ProductController#create')->name('product.create');
Route::post('/order/{order}/product', 'ProductController#store')->name('product.store');
Use Route model binding in ProductController.php to have Laravel resolve the order out of the container.
// ProductController.php
use App\Order;
use App\Product;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function create(Order $order)
{
// Only get here if laravel resolves the $order model
return view('order.product-create', compact('order'));
}
public function store(Order $order, Request $request)
{
// Only get here if laravel resolves the $order model
//validation
$this->validate($request, [
'name' => 'required',
'drawing' => 'nullable|file',
'3d_file' => 'nullable|file',
'quantity' => 'integer',
'unit_price' => 'required',
'discount' => 'nullable'
]);
// Create related Product model and associate it with the Order model.
// https://laravel.com/docs/7.x/eloquent-relationships#the-create-method
//
// Need to allow for mass assignment in the Product.php model
// https://laravel.com/docs/7.x/eloquent#mass-assignment
$order->products()->create($request->all());
// Flash to session and redirect after creating
session()->flash('product-created', 'New product was added successfully');
return redirect()->route('order.view');
}
}
view.blade.php
Add new product
product.create.blade.php
action="{{route('product.store', ['order' => $order])}}"
The way i understood, you want to pass the Order ID from your create form to your controller function, and based on that you want to save your form data.
You can pass your Order ID to your POST route by
{{ route('route_name', ['order_id' => $order->id]) }}
and your Route in web.php would be
Route::post('/order/{order_id}/product/create', 'ProductController#store')->name('route_name)
Create Method with Relationship
Relationship Documentation
You can accept your parameters passed with in your controller function by
public function store($order_id)
{
//validation
//save function
$order = App\Order::findOrFail($order_id); //Fails if the passed id is not present in DB
// Assuming you have one to one relationship
// Product() is the relationship you declare in your model
$product = $order->Product()->create([
'your_columns' => 'values',
]);
// redirect after save
}
Edit : Updated Question
use Illuminate\Http\Request;
use App\Order;
use App\Product;
use Illuminate\Support\Facades\Route;
class ProductController extends Controller
{
public function create(Order $order){
// you are receiving the Order instance by the Order ID (primary key defined)
return view('order.product-create', compact($order));
}
public function store(Order $order, Request $request){
$this->validate($request, [
'name'=>'required',
'drawing'=>'nullable|file',
'3d_file'=>'nullable|file',
'quantity'=>'integer',
'unit_price'=>'required',
'discount'=>'nullable'
]);
$order->products()->create($request->all());
session()->flash('product-created', 'New product was added successfully');
return redirect()->route('order.view');
}
}
and your Routes
// order = order id which is passed to the controller Order $order variable instance
Route::get('/order/{order}/product/create', 'ProductController#create')->name('product.create');
Route::post('/order/{order}/product/create', 'ProductController#store')->name('product.store');
Your form POST
// You can pass the ID of the order result you receive from your `create` function
<form action = "{{ route('product.store',['order' => $order->id]) }}" ... >
I'm trying to build a multiple authentification in laravel with different tables (2 tables) for admin and user. The problème is that the registration and login forms work only with default auth login/register.
I've tried some examples form web tutorials but it didn't work.
HomeController.php:
public function __construct() {
$this->middleware('auth');
}
public function index() {
return view('home');
}
I have added createAdmin function in "Auth/RegisterController.php":
protected function createAdmin(array $data)
{
$this->validator($data->all())->validate();
$admin = Admin::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
return redirect()->intended('login/admin');
}
I have changed email validation rules to:
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'|'unique:admins']
And the route (web.php) is:
Route::post('/register/admin', 'Auth\RegisterController#createAdmin');
When I fill admin register credentials and click register button I get this message:
Symfony\Component\Debug\Exception\FatalThrowableError Too few arguments to function App\Http\Controllers\Auth\RegisterController::createAdmin(), 0 passed and exactly 1 expected
The error is coming from the array $data parameter in your createAdmin() controller method.
Usually, you want to use one of two types of parameters in your controller methods: route parameters or injected dependencies. The $data parameter isn't matching either of those, so Laravel doesn't know to provide it.
If you'd like to access the request (POST) data in the controller, you can either ask for an instance of Illuminate\Http\Request as a parameter:
// Import it at the top of your PHP file
use Illuminate\Http\Request;
// Then your updated method:
public function createAdmin(Request $request)
{
$data = $request->all();
// ...
}
Or, use the request() helper directly:
public function createAdmin()
{
$data = request()->all();
// ...
}
I am using Laravel's Validation through FormRequest. An extract of the code is here. It seems laravel's validation is letting email addresses like "user#hotmail" through.
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class DirectorForm extends FormRequest
{
public function rules()
{
return [
'email' => 'required|email',
];
}
}
it seems the above validation allows "username#hotmail", which isn't a valid email address.
Did i set it up wrongly
Actually user#hotmail is a valid email, as user#localhost can also be a valid email address.
If you want to check that if the email address also contains a TLD, you can try:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class DirectorForm extends FormRequest
{
public function rules()
{
return [
'email' => 'required|regex:.+#.+\..+',
];
}
}
For more regex email validation rules take a look at this answer.
Use the regex from: https://emailregex.com/
And combine with Laravel regex rule: https://laravel.com/docs/5.8/validation#rule-regex
It appears validation is working as expected. Thanks for reading!
You can write custom validation for an email in AppServiceProvider like
Boot method
Validator::extend('email_address', function ($attribute, $value, $parameters, $validator) {
return (!preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*#([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $value)) ? FALSE : TRUE;
});
Rules
public function rules()
{
return [
'email' => 'required|email_address',
];
}
I use proengsoft/laravel-jsvalidation in combination with a custom FormRequest and custom validation rules that I defined via Validator::extend(...) in a service provider. This works well.
However, when I port my custom rules to the new(ish) custom Rule class in Laravel 5.5+, JsValidator fails at getting my custom Rule messages.
I have this custom rule:
use Illuminate\Contracts\Validation\Rule;
class MyRule implements Rule
{
public function passes($attribute, $value) {
return $value > 10;
}
public function message() {
return 'Your :attribute is pretty small, dawg!';
}
}
My form request uses this rule:
use Illuminate\Foundation\Http\FormRequest;
use App\Rules\MyRule;
class MyRequest extends FormRequest
{
public function authorize() {
return true;
}
public function rules() {
$rules = [
'foo' => 'required|numeric',
'bar' => ['required', new MyRule()],
];
return $rules;
}
}
This should work, but I get thrown an Exception on
{!! JsValidator::formRequest('\App\Http\Requests\MyRequest') !!}
An Exception is thrown from a call to Str::snake(Object(App\Rules\MyRule)) made by Proengsoft\JsValidation\Javascript\MessageParser.php.
JsValidation does not look at the $rule object type before calling Validator->getMessage($attribute, $rule)
where instead it should be calling $rule->messages();
Can I work around this bug somehow, and use laravel-jsvalidation together with my custom Rule and FormRequest -- or does it necessarily require i make a pull request and hope it will be fixed... someday? I'd like to make this work now-ish.
This can be archived by passing JsValidator instance based on rules and message arrays instead of passing the form request. In controller Pass this instance to blade. Read here for more details.
JsValidator::make($rules, $messages, $customAttributes, $selector)
In controller,
$validator = JsValidator::make(
[
'name' => 'required',
],
[
'name.required' => 'Name field is a required field',
]
)
return View::make("Your view", compact($validator));
In blade,
{!! $validator->selector('.wizard_frm') !!}
<form class='wizard_frm'></form>
And in this case we can create object of request class and pass rules function returned array to JsValidator::make if needed.
I am using form request validation and there are some rules that needs external values as a parameters.
Here are my validation rules for editing a business profile inside a form request class,
public function rules()
{
return [
'name' => 'required|unique:businesses,name,'.$business->id,
'url' => 'required|url|unique:businesses'
];
}
I can use this on the controller by type hinting it.
public function postBusinessEdit(BusinessEditRequest $request, Business $business)
{
//
}
But how to pass the $business object as a parameter to the rules method?
Lets say this is your model binding:
$router->model('business', 'App\Business');
Then you can reference the Business class from within the FormRequest object like this:
public function rules()
{
$business = $this->route()->getParameter('business');
// rest of the code
}
Note that if you use your form request both for create and update validation, while creating the record, the business variable will be null because your object does not exists yet. So take care to make the needed checks before referencing the object properties or methods.
There can be many ways to achieve this. I do it as below.
You can have a hidden field 'id' in your business form like bellow,
{!! Form::hidden('id', $business->id) !!}
and you can retrieve this id in FormRequest as below,
public function rules()
{
$businessId = $this->input('id');
return [
'name' => 'required|unique:businesses,name,'.$businessId,
'url' => 'required|url|unique:businesses'
];
}
For those who switched to laravel 5 :
public function rules()
{
$business = $this->route('business');
// rest of the code
}
Let say if we have a scenario like we want to change our validation rules depends on the type that we pass in with the route. For example:
app.dev/business/{type}
For different type of business, we have different validation rules. All we need to do is type-hint the request on your controller method.
public function store(StoreBusiness $request)
{
// The incoming request is valid...
}
For the custom form request
class StoreBussiness extends FormRequest
{
public function rules()
{
$type = $this->route()->parameter('type');
$rules = [];
if ($type === 'a') {
}
return rules;
}
}
In Laravel 5.5 at least (haven't checked older versions), once you did your explicit binding (https://laravel.com/docs/5.5/routing#route-model-binding), you can get your model directly through $this:
class StoreBussiness extends FormRequest
{
public function rules()
{
$rules = [];
if ($this->type === 'a') {
}
return rules;
}
}
Since Laravel 5.6 you may type hint it in the rules method:
public function rules(Business $business)
{
return [
'name' => 'required|unique:businesses,name,'.$business->id,
'url' => 'required|url|unique:businesses'
];
}
See the docs for more:
You may type-hint any dependencies you need within the rules method's signature. They will automatically be resolved via the Laravel service container.