Override package localization in Laravel - php

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.

Related

Loading a composer class in laravel

I'm in the process of trying to make a laravel compatible composer/packagist package. I'm using Laravel 5.5.
I've created a package : floor9design/machine-identifier. Composer downloads this to vendors/floor9design fine, but despite reading/googling how to do this, I'm unsure of how to include this in my laravel projects.
PHP Storm is correctly picking up the class, auto-completing as expecting.
I have not modified any files so far. If I add the following to a controller:
use Floor9design\MachineIdentifier\MachineIdentifier;
(alongside some class usage on the page).
PHP storm autocompletes this (as it does with other classes validly called).
When I try to load this, the following error comes:
Class 'Floor9design\MachineIdentifier\MachineIdentifier' not found
I've had a look round plenty of tutorials, and this final step seems to be missing from a lot of information.
I realise there are three approaches:
Firstly:
Direct include_once, which while working, is not the normal approach
Secondly:
Pre-laravel 5.5 approach (add something to app.php)
Thirdly
Laravel 5.5 approach and up, autodetection of something.
I've deliberately said something as the documentation seems to speak about ServiceProviders, and I simply don't get how they work.
Let me rephrase this into a question and a follow up question:
Question: apart from include_once, how do I load the MachineIdentifer class from floor9design/machine-identifier in Laravel.
Question 2: If the answer is via a service provider, can you simply explain how they relate to one another.
Thanks
Answer (as accepted below)
On the composer repo I was incorrectly specifying the PSR4 namespace, which is now corrected to:
"autoload": {
"psr-4": {
"Floor9design\\MachineIdentifier\\": "src"
}
}
The previous namespace had a -, which is an illegal character. Many thanks to lawrence-cherone.
Your PSR4 is wrong in the package
floor9design\\machine-identifier\\": "src"
Will cause the composer/autoload_psr4.php to map to:
'floor9design\\machine-identifier\\' => array($vendorDir . '/floor9design/machine-identifier/src'),
Which is not a valid class namespace.
You should change the PSR4 to match your class namespace:
Floor9design\\MachineIdentifier\\": "src"
Once you fix that you will be able to use it like normal from anywhere in your project.

Can I use the Blade templating engine outside of Laravel?

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.

Illuminate Validator in stand-alone non-Laravel application

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,

Getting CakeS3 to work in the CakeShell

I want to be able to call the CakeS3 plugin from the Cake Shell. However, as I understand it components cannot be loaded from the shell. I have read this post outlining strategies for overcoming it: using components in Cakephp 2+ Shell - however, I have had no success. The CakeS3 code here is similar to perfectly functioning cake S3 code in the rest of my app.
<?php
App::uses('Folder','Utility');
App::uses('File','Utility');
App::uses('CakeS3.CakeS3','Controller/Component');
class S3Shell extends AppShell {
public $uses = array('Upload', 'User', 'Comment');
public function main() {
$this->CakeS3 = new CakeS3.CakeS3(
array(
's3Key' => 'key',
's3Secret' => 'key',
'bucket' => 'bucket')
);
$this->out('Hello world.');
$this->CakeS3->permission('private');
$response = $this->CakeS3->putObject(WWW_ROOT . '/file.type' , 'file.type', $this->CakeS3->permission('private'));
if ($response == false){
echo "it failed";
} else {
echo "it worked";
}
}
This returns an error of "Fatal error: Class 'CakeS3' not found in /home/app/Console/Command/S3Shell.php. The main reason I am trying to get this to work is so I can automate some uploads with a cron. Of course, if there is a better way, I am all ears.
Forgive me this "advertising"... ;) but my plugin is probably better written and has a better architecture than this CakeS3 plugin if it is using a component which should be a model or behaviour task. Also it was made for exactly the use case you have. Plus it supports a few more storage systems than only S3.
You could do that for example in your shell:
StorageManager::adapter('S3')->write($key, StorageManager::adapter('Local')->read($key));
A file should be handled as an entity on its own that is associated to whatever it needs to be associated to. Every uploaded file (if you use or extend the models that come with the plugin, if not you have to take care of that) is stored as a single database entry that contains the name of the config that was used and some meta data for that file. If you do the line of code above in your shell you will have to keep record in the table if you want to access it this way later. Just check the examples in the readme.md out. You don't have to use the database table as a reference to your files but I really recommend the system the plugin implements.
Also, you might not be aware that WWW_ROOT is public accessible, so in the case you store sensitive data there it can be accessed publicly.
And finally in a shell you should not use echo but $this->out() for proper shell output.
I think the App:uses should look like:
App::uses('CakeS3', 'CakeS3.Controller/Component');
I'm the author of CakeS3, and no I'm afraid there is no "supported" way to do this as when we built this plugin, we didn't need to run uploads from shell and just needed a simple interface to S3 from our controllers. We then open sourced the plugin as a simple S3 connector.
If you'd like to have a go at modifying it to support shell access, I'd welcome a PR.
I don't have a particular road map for the plugin, so I've tagged your issue on github as an enhancement and will certainly consider it in future development, but I can't guarantee that it would fit your time requirements so that's why I mention you doing a PR.

Issue with Pear Net_URL_Mapper

I started working on a project which uses Net_URL_Mapper from PEAR (php) as the router. For some reason URLS like the following seem to create a problem to the package classes. Think it's a bug but not sure (haven't looked around for it yet).
example URL : /login/?q=somevalue
Sample code
$m->connect('/login/:action/', array('control' => 'login','action'=>'default'));
The question is: have u used Net_URL_Mapper and had this problem? Did you solve it? Am i doing something wrong with the above path?
Is there an other routing package (or framework) which you could suggest that is simple (low learning curve) and could easily replace net_url_mapper without much trouble (requiring too many changes) ?
Thanks,
$m->connect('/login/:action/',
array('control' => 'login','action'=>'default'));
Would expect a url like this:
http://www.example.com/login/someaction/?q=somevarible
Following would route to the action default
http://www.example.com/login/
This would route to controller login, action opinid and it would pass username Foo as $_Get variable
http://www.example.com/login/openid/?username=Foo

Categories