I'm trying to arrange things properly in my app, so I created a folder called "validators" in my "/app/models" directory to keep my custom validation rules there. I expected it to be auto-loaded, but it's not. Here's the code of my validator:
class AuthValidator extends \Illuminate\Validation\Validator
{
public function validateActive($input, $value, $parameters)
{
if ( $input === "email" )
{
return User::where("email", $value)->first()->confirmed();
} else
{
return true;
}
}
}
Validator::resolver(function($translator, $data, $rules, $messages)
{
$messages['active'] = "You need to confirm your email first";
return new AuthValidator($translator, $data, $rules, $messages);
});
It works fine, if i put it in /app/models/User.php file, so the problem is not in the class definition.
I tried to make a separated "/app/validators" directory and put it into composer.json and /app/start/global.php files for autoloading. Still doesn't load, even though I did "artisan dump-autoload" and "composer dump-autoload" both.
Every time I try to use my custom rule "active", Laravel says "Method [validateActive] does not exist.".
I also tried to write "echo '123'; exit;" in the beginning of my file and it didn't work, so the file is obviously just not loaded.
It's especially weird, because other custom models are loaded.
UPD: I use the standard files structure and right now composer.json is not edited.
Did you add a namespace?
This worked for me:
app/models/validators/AuthValidator.php:
namespace app\models\validators;
class AuthValidator
{
function test()
{
dd("message from AuthValidator");
}
}
In controller:
use app\models\validators\AuthValidator;
class WelcomeController extends Controller {
public function __construct(AuthValidator $av)
{
$av->test();
}
}
It autoloaded, I didn't have to add it in composer.json
Related
I would like to make a package which uses a custom stub for creating migrations needed for my package. More precisely, running the command should make pivot tables for models which have a specific trait present.
If I make a "normal" command, I can register it within my service provider:
public function boot()
{
if ($this->app->runningInConsole()) {
$this->commands([
MakeContainerMigration::class,
]);
}
}
However in this case I wanted to reuse Laravel's coding and save myself the trouble to reinvent the wheel. So my command looks like this:
class MakeContainerMigration extends MigrateMakeCommand
{
protected $name = 'custom:make-container';
protected $description = '...';
}
Since MigrateMakeCommand doesn't have stubs defined, but rather it's dependency MigrationCreator, I needed to find a way to provide custom stub path to it without disrupting "regular" migration stubs.
I tried doing something like this but failed:
public function register()
{
$this->registerCreator();
$this->registerMigrateMakeCommand();
if ($this->app->runningInConsole()) {
$this->commands([
//MakeContainerMigration::class,
'custom.command.migrate.make'
]);
}
}
protected function registerCreator()
{
$this->app->singleton('custom.migration.creator', function ($app) {
return new MigrationCreator($app['files'], __DIR__ . '/stubs');
});
}
protected function registerMigrateMakeCommand()
{
$this->app->singleton('custom.command.migrate.make', function ($app) {
$creator = $app['custom.migration.creator'];
$composer = $app['composer'];
return new MakeContainerMigration($creator, $composer);
});
}
I'm aware that registering the command shouldn't function like this as I am simply registering singletons to Laravel app instance, but I have no idea how to register it through the class while ensuring that the right version of MigrationCreator will be injected. I'm kinda stuck here, is there a way to do it?
Turns out everything is working, I just needed to replace
protected $name = 'custom:make-container';
with
protected $signature = 'custom:make-container';
I am using laravel latest version and i have a common field in all model called slug.I would to check whether slug is unique or not. i have slug field in all tables
so i have extended Valdiator class
class CustomValidator extends Validator{
protected function validateIsUniqueSlug($attribute, $value, $parameters)
{
$isSlugExist= User::where('slug', $value)->exists();
if ($isSlugExist) {
return false;
}
return true;
}
}
this works but problem here is i need to repeat this for models but i dont want to do this .is there any better approach so i can handle it in one method
i know laravel has sluggable package but for some reason i cant use that package
If you using create cutom rules try this code
php artisan make rule command for create rule go to App\Rules dir
u can see passes function condition here
and use any model
'slug'=>[new SlugDomain], in validator
Rules file
public function passes($attribute, $value)
{
$isSlugExist= User::where('slug', $value)->exists();
if ($isSlugExist) {
return false;
}
return true;
}
I am using the standard Laravel 5.2 authentication.
But i want to have certain variables available in my Registration view
The route that i'm interested in is this one:
Route::get('register', 'Auth\AuthController#showRegistrationForm');
The method showRegistrationForm is created in a trait called RegistersUsers , This trait is located in Illuminate\Foundation\Auth .
public function showRegistrationForm()
{
if (property_exists($this, 'registerView')) {
return view($this->registerView);
}
return view('auth.register');
}
I can just simply pass trough my parameters here, but the problem is that this file is located in the vendor directory , so when i run Composer Update my changes will be overwritten & my website would break. Is there a update-proof way to do this?
You can overwrite the method in your AuthController:
class AuthController extends Controller
{
....
public function showRegistrationForm()
{
$data = ['foo', 'bar'];
if (property_exists($this, 'registerView')) {
return view($this->registerView, compact('data'));
}
return view('auth.register', compact('data'));
}
}
I am trying to implement a Billing interface which uses Stripe.
I have created the Billing interface, Stripe class and binded the interface using a Service Provider.
I receive a Class not found error when trying to run the code:
ReflectionException in Container.php line 737: Class
Acme\Billing\StripeBilling does not exist
I can't figure out what the issue is, I've double checked for small issues like correct case etc.
Here is the code I've used:
app/Acme/Billing/BillingInterface.php
<?php
namespace Acme\Billing;
interface BillingInterface {
public function charge(array $data);
}
app/Acme/Billing/StripeBilling.php
<?php
namespace Acme\Billing;
use Stripe;
use Stripe_Charge;
use Stripe_Customer;
use Stripe_InvalidRequestError;
use Stripe_CardError;
use Exception;
class StripeBilling implements BillingInterface {
public function __construct()
{
Stripe::setApiKey(env('STRIPE_SECRET_KEY'))
}
public function charge(array $data)
{
try
{
return Stripe_Charge::create([
'amount' => 1000, // £10
'currency' => 'gbp',
'description' => $data['email'],
'card' => $data['token']
]);
}
catch(Stripe_CardError $e)
{
dd('card was declined');
}
}
}
app/Providers/BillingServiceProvider.php (UPDATED)
class BillingServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('Billing\BillingInterface', 'Billing\StripeBilling');
}
}
BasketController.php (ADDED)
public function store(Request $request)
{
$billing = \App::make('Billing\BillingInterface');
return $billing->charge([
'email' => $request->email,
'stripe-token' => $request->token,
]);
I have added App\Providers\BillingServiceProvider::class to my app.php file, and updated my composer.json to include Acme folder "Acme\\": "app/"
Your problem looks two-fold:
The PSR-4 autoload definition in your composer.json file is incorrect.
If your Acme folder lives inside the app folder, e.g. /dir/project_root/app/Acme/Billing/BillingInterface.php, then your composer.json definition should look like this:
"psr-4": {
"Acme\\": "app/Acme"
}
This is the root cause of the error you are receiving, which is not a Laravel-specific error. The autoloader simply cannot find the class you are asking for, even though the requested fully qualified class name is correct.
Your interface and class are not bound to the container properly (missing the Acme portion of the namespace).
Because you've defined both of them in the Acme namespace, you need to ensure Acme is present in your service provider definitions. So your service provider should look like this:
class BillingServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('Acme\Billing\BillingInterface', 'Acme\Billing\StripeBilling');
}
}
(Or, better yet, use the ::class syntax for improved IDE support.)
You will also need to make sure the fully qualified classname is correct when requesting the class in your controller: App::make('Acme\Billing\BillingInterface'). (I would recommend using dependency injection instead of this syntax, anyway.)
I am trying to use the Extend function that the validation offer,
Here is what I have:
1). HomeController.php :
$rules = array(
'first_name'=>'required|regex:/^[a-z ,."-]+$/i|min:2',
'last_name'=>'required|regex:/^[a-z ,."-]+$/i|min:2',
'gender'=>'required|alpha|gendercheck',
'email'=>'required|email|unique:users,email,'.Input::get('id').',id',
'zip'=>'required|zipcheck|max:10',
);
2). Then to use the extend method I add it to routes.php:
Validator::extend('zipcheck', function($field,$value,$parameters){
// List of regular expressions to use, if a custom one isn't specified.
$countryRegs = array(
"US"=>"/^[\d]{5}(-[\d]{4})?$/",
"GB"=>"/^(GIR|[A-Z]\d[A-Z\d]??|[A-Z]{2}\d[A-Z\d]??)[ ]??(\d[A-Z]{2})$/",
"DE"=>"/\b((?:0[1-46-9]\d{3})|(?:[1-357-9]\d{4})|(?:[4][0-24-9]\d{3})|(?:[6][013-9]\d{3}))\b/",
"CA"=>"/^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ])\ {0,1}(\d[ABCEGHJKLMNPRSTVWXYZ]\d)$/",
"FR"=>"/^(F-)?((2[A|B])|[0-9]{2})[0-9]{3}$/",
"IT"=>"/^(V-|I-)?[0-9]{5}$/",
"AU"=>"/^(0[289][0-9]{2})|([1345689][0-9]{3})|(2[0-8][0-9]{2})|(290[0-9])|(291[0-4])|(7[0-4][0-9]{2})|(7[8-9][0-9]{2})$/",
"NL"=>"/^[1-9][0-9]{3}\s?([a-zA-Z]{2})?$/",
"ES"=>"/^([1-9]{2}|[0-9][1-9]|[1-9][0-9])[0-9]{3}$/",
"DK"=>"/^([D-d][K-k])?( |-)?[1-9]{1}[0-9]{3}$/",
"SE"=>"/^(s-|S-){0,1}[0-9]{3}\s?[0-9]{2}$/",
"BE"=>"/^[1-9]{1}[0-9]{3}$/"
);
// get country submitted..
$country = Input::get('country');
// check country if in the array..
if (key_exists($country , $countryRegs))
return preg_match($countryRegs[$country], $value);
else // other countries make sure no special characters in there
return preg_match('/^[a-z0-9- ]+$/i' , $value);
});
The problem is I want to keep my code organized and I dont want to add the validation extend to my routes.php
What is the best way where I can have those in its own class and call those from my HomeController and still it will work?
Thanks
There are lots of ways to do this. The way I like is make a file /app/validators.php (So it is in the same location as routes.php and filters.php)
Then go to app/start/global.php and add this at the bottom after the filters require:
require app_path().'/validators.php';
You can now declare all your extended validators in the validators.php file -and Laravel will use them.
There are several ways to do. Personally I like to extends validation by a ValidationService (I think it is much cleaner).
1) We assume you use PSR-4 to load you own company directory in composer.json:
{
"autoload": {
"psr-4": {
"Acme\\": "app/Acme"
}
...
},
}
You have to run composer dumpautoload.
2) Create your validation service provider:
app/Acme/Extension/Validation/ValidationServiceProvider.php
<?php
namespace Acme\Extension\Validation;
use Illuminate\Support\ServiceProvider;
class ValidationServiceProvider extends ServiceProvider {
public function register() {
}
public function boot() {
$this->app->validator->resolver(function($translator, $data, $rules, $messages) {
return new CustomValidator($translator, $data, $rules, $messages);
});
}
}
3) Register your service provider in app/config/app.php for autoloading:
<?php
return array(
'providers' => array(
...
'Acme\Extension\Validation\ValidationServiceProvider',
),
);
4) Create your custom validation rule(s):
app/Acme/Extension/Validation/CustomValidator.php
<?php
namespace Acme\Extension\Validation;
use Illuminate\Validation\Validator as IlluminateValidator;
class CustomValidator extends IlluminateValidator {
public function validateAlphaNumSpace($attribute, $value) {
return preg_match('/^([a-z\x20])+$/i', $value);
}
public function validateZip($attribute, $value, $parameters) {
...
}
}
5) You are ready to use your custom rule(s). For example if I want to use my AlphaNumSpace rule (useful in many cases because original AlphaNum rule doesn't allow space!):
$rules = [
'name' => 'required|alpha_num_space',
'zipcode' => 'required|zip',
];