I'm building an API using Slim and the Illuminate Database package with Eloquent models etc. I have instantiated the database handler using Capsule as shown in the README. However, now I want to use the validation features on my models without installing the full Laravel suite, but I cannot quite wrap my head around the design of this library.
How would I go about this? It seems like the documentation provided for Laravel is pretty much expecting that you use Laravel out of the box.
Here is a solution for the current version: Laravel 5.4.
The composer.json file:
{
"name": "Validation standalone",
"require": {
"php": ">=5.6.4",
"illuminate/validation": "5.4.*",
"illuminate/translation": "5.4.*"
}
}
Note that we must also require "illuminate/translation": "5.4.*". And then in your php file:
use Illuminate\Validation;
use Illuminate\Filesystem;
use Illuminate\Translation;
include 'vendor/autoload.php';
$filesystem = new Filesystem\Filesystem();
$fileLoader = new Translation\FileLoader($filesystem, '');
$translator = new Translation\Translator($fileLoader, 'en_US');
$factory = new Validation\Factory($translator);
$messages = [
'required' => 'The :attribute field is required.',
];
$dataToValidate = ['title' => 'Some title'];
$rules = [
'title' => 'required',
'body' => 'required'
];
$validator = $factory->make($dataToValidate, $rules, $messages);
if($validator->fails()){
$errors = $validator->errors();
foreach($errors->all() as $message){
var_dump($message);
}
}
Here I have intentionally missed the "body" field in the data provided for validation, so that a validation error is displayed.
As for early 2021 the solution from #vivanov here works perfectly with Laravel 8 packages.
Here I add the ability to use default Laravel validation messages as using your own is too annoying.
Here is what you have to change in the #vinvanov solution.
Upddate composer.json
"require": {
"illuminate/validation": "^8.25",
"illuminate/translation": "^8.25"
},
Copy Laravel validation messages file to your project/laravel/en/validation folder.
Amend #ivanov's solution code as follows (only changes are reflected)
$translationDir = dirname(__DIR__, 4) . '/project/laravel/en/validation';
$fileLoader = new Translation\FileLoader($filesystem, $translationDir);
$fileLoader->addNamespace('lang', $translationDir);
$fileLoader->load('en', 'validation', 'lang');
$validator = $factory->make($dataToValidate, $rules);
See the full code with more comments in my gist;
This is it. You have the default Laravel messages in place working for you.
Here is the Laravel validation docs.
PS: Credits also go to this blog post from Jeff.
PPS: This is brilliant that despite version jump from 5.6 to 8.25 the packages interface is stable and works seamlessly. So mature and insightful open source attitude and great care about developers from Taylor Otwell. You can only apreciate the utmost convenience of this when you work outside of modern PHP frameworks within a shitty PHP codebase.
I hate to suggest this but the Laravel validator is probably not what you want. I suggest having a look at the validator classes in either Symfony or Zend Framework (2+). They work quite well as stand-alone validators and in fact I am using the ZF2 form classes and validator in a Laravel project at the moment because the Laravel form and validator classes are just not up to scratch.
It's probably not the answer you wanted to hear but it might save you some pain in the long term.
I was just wondering the same thing, and here I am a year later finding delatbabel's answer to be seriously wanting. I did find the following Gist where spekkionu has a fairly simple setup to get you started. (It's working on my machine?? ;P ) It shows how to make the translator for the factory, etc, etc. It's all included when you import illuminate/validation with composer.
Hope it helps:
https://gist.github.com/spekkionu/e9103993138e666f9f63
Best,
Related
I'm trying to rewrite a "custom framework" application to the Symfony, but I can not do everything at once, so I've divided the process into steps.
From important notes - I've already implemented the symfony/templating component and the symfony/twig-bridge component.
That's how I want to output the form in the template:
<?php echo $view['form']->form($form) ?>
As I'm doing so the following error is thrown:
Symfony\Component\Form\Exception\LogicException
No block "form" found while rendering the form.
/var/www/html/vendor/symfony/form/FormRenderer.php on line 98
To render the templates I'm using the DelegatingEngine which uses the PhpEngine and the TwigEngine.
Setting up the Twig with the \Symfony\Bridge\Twig\Extension\FormExtension is well documented, but what I'm missing is the php setup. This is how I'm doing this:
new \Symfony\Component\Form\Extension\Templating\TemplatingExtension($phpEngine, $this->csrfManager());
Could you point me what am I missing or what's wrong with my setup?
I think the simplest way would have been to install the Symfony 3.3 standard edition next to your app (pending the release of Symfony Flex).
After this, find a way to use the router of Symfony with the router of your application.
So you could have the full Symfony framework, create your form type in it and let Symfony render it :
With an ajax call
With a new Symfony Kernel in your legacy app
I've found the answer:
I was using the wrong FormRendererEngineInterface. Instead of relying on the \Symfony\Component\Form\Extension\Templating\TemplatingExtension class I've registered the form helper by myself:
$phpEngine = new PhpEngine(new TemplateNameParser(), new FilesystemLoader(realpath(__DIR__.'/../Template').'/%name%'));
$twigEngine = new TwigEngine($this->twig(), new TemplateNameParser());
$this->TemplateEngine = new DelegatingEngine(array(
$phpEngine,
$twigEngine,
));
$phpEngine->addHelpers(array(
new FormHelper(new FormRenderer($this->twigFormRendererEngine())),
));
As you can see in the TemplatingEngine:
public function __construct(PhpEngine $engine, CsrfTokenManagerInterface $csrfTokenManager = null, array $defaultThemes = array())
{
$engine->addHelpers(array(
new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenManager)),
));
}
It relies on the TemplatingRendererEngine while I need the TwigRendererEngine instance, as the form templates are the twig files.
Correct me if my explanation is wrong, but the solution is working.
i'm want to creating a design pattern and use the "Blade templating engine".
Can I use the Blade templating engine outside of Laravel and use it in my new pattern ?
For the record:
I tested many libraries to run blade outside Laravel (that i don't use) and most are poor hacks of the original library that simply copied and pasted the code and removed some dependencies yet it retains a lot of dependencies of Laravel.
So I created (for a project) an alternative for blade that its free (MIT license, i.e. close source/private code is OK) in a single file and without a single dependency of an external library. You could download the class and start using it, or you could install via composer.
https://github.com/EFTEC/BladeOne
https://packagist.org/packages/eftec/bladeone
It's 100% compatible without the Laravel's own features (extensions).
How it works:
<?php
include "lib/BladeOne/BladeOne.php";
use eftec\bladeone;
$views = __DIR__ . '/views'; // folder where is located the templates
$compiledFolder = __DIR__ . '/compiled';
$blade=new bladeone\BladeOne($views,$compiledFolder);
echo $blade->run("Test.hello", ["name" => "hola mundo"]);
?>
Another alternative is to use twig but I tested it and I don't like it. I like the syntax of Laravel that its close to ASP.NET MVC Razor.
Edit: To this date (July 2018), it's practically the only template system that supports the new features of Blade 5.6 without Laravel. ;-)
You certainly can, there are lots of standalone blade options on packagist, as long as you are comfortable with composer then there should be no issue, this one looks pretty interesting due to having a really high percentage of stars compared to downloads.
Be warned though i have not tried it myself, like you i was looking for a standalone option for my own project and came across it, i will be giving it a real good workout though at sometime in the near future,
Matt Stauffer has created a whole repository showing you how you can use various Illuminate components directly outside of Laravel. I would recommend following his example and looking at his source code.
https://github.com/mattstauffer/Torch
Here is the index.php of using Laravel Views outside of Laravel
https://github.com/mattstauffer/Torch/blob/master/components/view/index.php
You can write a custom wrapper around it so that you can call it like Laravel
use Illuminate\Container\Container;
use Illuminate\Events\Dispatcher;
use Illuminate\Filesystem\Filesystem;
use Illuminate\View\Compilers\BladeCompiler;
use Illuminate\View\Engines\CompilerEngine;
use Illuminate\View\Engines\EngineResolver;
use Illuminate\View\Engines\PhpEngine;
use Illuminate\View\Factory;
use Illuminate\View\FileViewFinder;
function view($viewName, $templateData)
{
// Configuration
// Note that you can set several directories where your templates are located
$pathsToTemplates = [__DIR__ . '/templates'];
$pathToCompiledTemplates = __DIR__ . '/compiled';
// Dependencies
$filesystem = new Filesystem;
$eventDispatcher = new Dispatcher(new Container);
// Create View Factory capable of rendering PHP and Blade templates
$viewResolver = new EngineResolver;
$bladeCompiler = new BladeCompiler($filesystem, $pathToCompiledTemplates);
$viewResolver->register('blade', function () use ($bladeCompiler) {
return new CompilerEngine($bladeCompiler);
});
$viewResolver->register('php', function () {
return new PhpEngine;
});
$viewFinder = new FileViewFinder($filesystem, $pathsToTemplates);
$viewFactory = new Factory($viewResolver, $viewFinder, $eventDispatcher);
// Render template
return $viewFactory->make($viewName, $templateData)->render();
}
You can then call this using the following
view('view.name', ['title' => 'Title', 'text' => 'This is text']);
Yes you can use it where ever you like. Just install one of the the many packages available on composer for it.
If you're interested in integrating it with codeigniter I have a blog post here outlining the process.
Following the above steps should make it obvious how to include it into any framework.
I want to use the Respect/Validation library in PHP. I know how to use it but currently I'm using it in a project in German language and of course, I also want the error messages in German.
For language translation, there is a section in the documentation but I don't really get it and I did not found any answer yet.
They're talking about a translator that should handle the translation of the messages. As a second parameter they're giving "gettext" but I don't know what this should be and how this should handle the translation.
Can anybody explain me how this works?
Respect/Validation won't do the translation for you, you should use a different project, library or function to do that. It won't leave you empty handed though, as the documentation states.
First, you should try to understand how translation libraries work (such as gettext()) and then read PHP documentation on Callables. Then it is a matter of choosing a library, creating the translations and calling setParam('translator', 'callable') method on the exception instance.
A quick introduction to your problem:
Translations are done based on a source: it can be a file, a database or something else, depending on which library you use.
Respect/Validation exception messages use the same pattern: {{name}} is invalid.. Where {{name}} will be replaced by the input given or the name if setName() was called on that rule.
You can see all messages you need to translate under the Respect\Validation\Exceptions namespace.
Usually, every library provide a single function/method to translate a given string. This is the method/function you want to set on the $exception->setParam() call.
If you ever translate all exception messages, we would love to make them available to everyone else.
PS: You could also make this question on the repository page, more people would help and we could also improve the way translations are handled by the library in the future.
I just changed all Exception defaultTemplates property, it works for me.
class Localization
{
public function init()
{
$this->validation();
}
public function validation()
{
$prefix = '\\Respect\\Validation\\Exceptions\\';
$localize = [
'EmailException' => 'local message',
'NotEmptyException' => 'local message'
];
foreach($localize as $class => $message) {
($prefix.$class)::$defaultTemplates[
ValidationException::MODE_DEFAULT][ValidationException::STANDARD] = $message;
}
}
}
$localization = new Localization();
$localization->init();
Lately I've been using a template manager for silex, but I've noticed that it's been abandoned and no longer works for newer versions of silex. Here's an example code of what it does (it can be seen on its GitHub page):
<?php
use Herrera\Template\TemplateServiceProvider;
use Silex\Application;
$app = new Application();
$app->register(new TemplateServiceProvider(), array(
'template.dir' => '/path/to/dir',
'template.dir' => array(
'/path/to/dir1',
'/path/to/dir2',
'/path/to/dir3',
)
));
$app['template.engine']->render('test.php');
So, what it exactly does is that it renders the file you give, and you can also give other parameters to send it to the file before rendering it... It was very useful to me, but as I said, it's been abandoned and it no longer works with newer versions of Silex.
So, what I'm asking is: is it a good alternative of this that works with newer versions? Should I downgrade my Silex in order to be able to use this? Or is it very hard to try to "create" a system for being able to use this?
I've heard about Twig, but it doesn't really convince me because it doesn't seem to be convenient with what I want to achieve.
Thanks!
You can have the same result just extending the twig loader (Twig_Loader_Filesystem).
$app['twig.loader.filesystem'] = $app->share(
$app->extend('twig.loader.filesystem', function($loader, $app) {
$loader->addPath('/path/to/dir1');
$loader->addPath('/path/to/dir2');
$loader->addPath('/path/to/dir3');
return $loader;
}
);
Then you just use twig as always. $app['twig']->render('template.twig', array(...));
The filesystem loader will look for templates in /path/to/dir1, and if they dont exists it will fallback to look for them in /path/to/dir2 and so on.
If you insist in using a pure PHP templating engine you can do it with the Symfony Templating Component:
Install with composer symfony/templating and then register the service:
use Symfony\Component\Templating\PhpEngine;
use Symfony\Component\Templating\TemplateNameParser;
use Symfony\Component\Templating\Loader\FilesystemLoader;
$app['templating'] = $app->share(function() {
$loader = new FilesystemLoader(array(
'/path/to/dir1',
'/path/to/dir2',
'/path/to/dir3',
));
$nameParser = new TemplateNameParser();
$templating = new PhpEngine($nameParser, $loader);
return $templating;
});
Then you just use this engine as $app['templating']->render('template.php', array(...));
It should be "trivial", but after some chating on #laravel irc channel, I found it may be impossible for now. But I'll ask it here before doing it the ugly-go-horse way just to have the project done. If it's indeed impossible by current means, I'll fill a request on github (after handing over the project to my client).
I'm using Zizaco\Confide to handle authentication in my service. It uses Laravel Lang everywhere to get strings in one of the 8 bundled languages of the package. But I need to override some of those strings, and I don't want to modify the package files (which would defeat the whole purpose of Composer). How can I do this?
For example, I needed to modify confide::confide.alerts.wrong_credentials for pt_BR language. What I tried so far:
/app/lang/pt_BR/confide.php file, with contents return array('alerts' => array('wrong_credentials' => '...')). It works for Lang::get('confide.alerts.wrong_credentials') but not for the namespaced Lang::get('confide::confide.alerts.wrong_credentials')
/app/lang/pt_BR/packages/zizaco/confide/confide.php with return array('alerts' => ......)
/app/lang/pt_BR/packages/zizaco/confide/confide/alerts.php with return array('wrong_credentials' => ...)
/app/lang/packages/zizaco/confide/pt_BR/confide.php with array('alerts' => array('wrong_credentials' => '...')) - /app/lang/packages/zizaco/confide/pt_BR/confide/alerts.php with return array('wrong_credentials' => ...)
Any clue on what am I missing? Or does Laravel4 really lacks this feature?
Thanks in advance!
actually it fixed in Laravel 4.1 core
you can now overwrite it by doing
app/lang/packages/(locale)/confide/confide.php
check this
laravel 4 language issue
correct path for overriding package languages
So, as for today, Laravel really does lack this feature.
I've asked for it creating a issue on github.
Meanwhile, this functionality could be achieved seamlessly using crynobone's Orchestra Platform 2 Translation Component, which can be found here
All you need to do is require it in composer.json
{
"require": {
"orchestra/translation": "2.0.*"
}
}
and replace the original translation package ('Illuminate\Translation\TranslationServiceProvider') in /config/app.php
'providers' => array(
//'Illuminate\Translation\TranslationServiceProvider',
// ...
'Orchestra\Translation\TranslationServiceProvider',
),
That's it! Now, having app/lang/en/packages/confide/confide.php will do it!
(please note that the path should be /packages/packagename/, not /packages/vendor/packagename/
It really saved me from a big headache, hope others find this useful too.