Laravel 5 namespaces - laravel

I just downloaded Laravel 5 and started migrating to it. However, I find the required use of namespaces really annoying.
I don't feel like I am getting much from it, other than cluttering my code.
How can I disable the namespacing requirement?

I don't think you should disable or remove namespaces. The main reason for namespacing is to avoid conflicts with classes that have the same name. As soon as an application gets larger you will have classes that have the same name. Example from the Framework source:
Illuminate\Console\Application and Illuminate\Foundation\Application
Both are called the same. Only because of the namespacing you can import the right class. Of course you could also name them:
ConsoleApplication and FoundationApplication
But while the namespace normally is only used when importing a class at the top of a file:
use `Illuminate\Console\Application`
The name itself is used everywhere in the code. That's something that really clutters up your code, too long class names.
Besides the naming thing, namespaces also encourage better structure and help with knowing where your files are. That's because Laravel's default structure is PSR-4 compliant. That means if you have a controller App\Http\Controllers\HomeController you can be certain that you will find a HomeController.php under app/Http/Controllers.
I am aware of that, but it's not needed in the project I am working on.
Maybe it doesn't make sense for the current project but getting used to namespaces will help you tackle bigger projects in the future
And being a Sublime Text user, which doesn't have autoimport, it really gets to be a pain
I don't know Sublime Text that well, but CodeIntel might have auto import. Otherwise consider switching to another editor / IDE. I can highly recommend JetBrains PhpStorm
In the end, if you still don't want to use namespaces, keep using Laravel 4 or search for another framework that follows less good practices...
Removing namespaces from your app classes
While a totally don't recommend this, it is possible to at least remove some of the namespacing in your application.
For example the default controller namespace App\Http\Controllers can be changed to no namespace at all in RouteServiceProvider:
protected $namespace = '';
And for your models you can just remove the namespace in the file and your good. But keep in mind that without namespaces PSR-4 autoloading won't work anymore. You will have to autoload your files using classmap in composer.json

You can avoid using namespaces for own classes by defining them in the global namespace in your composer.json file. Like this:
"autoload": {
"psr-0": {
"": ["app/Http/Controllers/",
"app/models/",
"app/helpers"
]
},
You will also have to change your app/Providers/RouteServiceProvider.php to:
protected $namespace = '';
for routing to work.

Related

how laravel handle illuminate namespace

As far as I know, namespace is used for preventing class, function, ... collision in PHP. In Laravel 8 when we create a model for example, the name space is App\Models and when we want to use this model, we have to use it like use App\Models\MyModel. My question is when we use use Illuminate\Support\Arr, why we don't use the full path explicitly vendor\laravel\framework\......
It’s part of the PSR-4 auto loading standard which replaces the PSR-0 auto loading standard. Composer compiled an autoload.php from your project’s and dependencies’ composer.json. As part of the bootstrapping process that file is included in the application and registers each namespace.

How to use Laravel facades (Cache, Log, Storage) in package outside Laravel

Please point out any naivete or incorrect assumptions I'm making about Laravel, Composer, PHPUnit, etc.
I had a class called SpeechToTextHelper that was inside a Laravel project, and it used facades like this:
use Cache;
use Log;
use Storage;
Then, since I wanted to share it between multiple Laravel projects, I moved it into a separate repo and required it (into the first project) as a dependency via Composer.
The code all seems to run fine.
My question is different from Using Laravel Facades outside Laravel
What I want to know is:
Now that I also want to write PHPUnit tests for SpeechToTextHelper in my new tools repo, I see errors like RuntimeException: A facade root has not been set. and Error: Class 'Log' not found, presumably because this tools repo has no awareness of Laravel. I guess this means my production code has been working just by side-effect.
In my new tools repo (where my SpeechToTextHelper now is), how am I supposed to indicate (maybe somewhere in composer.json?) that the code will only work if Laravel's facades exist and are initiated properly?
How can I fix my separate repo's code so that its tests can run and also so that it ensures that it can only be "required" by a Laravel project?
P.S. https://laravel.com/docs/5.7/facades says "When building a third-party package that interacts with Laravel, it's better to inject Laravel contracts (https://laravel.com/docs/5.7/contracts) [which live in their own GitHub repository] instead of using facades." "If you are building a package, you should strongly consider using contracts since they will be easier to test in a package context."
But I do not see contracts for Log or Storage at all.
I think you are looking for Laravel component repositories
Cache - This component shows how to use Laravel's Cache features in non-Laravel applications.
Log - This component shows how to use Laravel's Log features in non-Laravel applications.
This video shows, how you can use eloquent outside laravel, I think that will give you better idea.
I'm not positive that this is the best approach, so I'd love if others
would provide better answers.
For production code
My composer.json still has this in the "require" section: "laravel/framework": "5.7.*",.
I plan to only ever require this tools library from within a Laravel app. I'm not sure that this is the right way to make that a rule, but my production code at least seems to be working.
For tests
As for tests, what seems to have been necessary was to add these files from https://github.com/laravel/laravel/tree/2a1f3761e89df690190e9f50a6b4ac5ebb8b35a3:
app/Console/Kernel.php
app/Providers/AppServiceProvider.php
app/Providers/AuthServiceProvider.php
app/Providers/EventServiceProvider.php
app/Providers/RouteServiceProvider.php
bootstrap/cache/.gitignore
bootstrap/app.php
bootstrap/autoload.php
config/app.php
config/database.php
config/logging.php
config/view.php
storage/logs/laravel.log
tests/CreatesApplication.php
tests/TestCase.php
Perhaps those are the minimum set of barebones Laravel files without which tests can't run.
Then I made sure that each test class extended tests/TestCase.php. And I adjusted the namespaces.

Best practice to modular programming in Laravel 5+

I'm starting a new project and I want to reuse some parts of it, mainly the stuff related to user registration and authentication. I can copy and paste all of the code but I want to use again. I know there is Package Development in Laravel but it's not easy and feel like there must be a better way.
Some days ago I find a pingpong/modules but I don't know about it. It's third party plugin and don't trust it.
Use this plugin is true? Is this plugin is updated later? What's different between Embedd Package Laravel and pingpong/modules? or Do you have any suggestion?
Pingpong modules seems to be build for the earlier version of Laravel 5 and in how far they are compatible with future versions (and maybe current 5.1.11) I cannot say.
There isn't much activity going look the commit history for 2.1, as of today(18 dec) the last commit was over 6 months ago.
But is the package specifically designed for Laravel? It seems to. They offer a bunch of features which are useful for development. The only unfortunate thing is you get a LOT of code within your own git environment (is it a good thing? I don't know, what do you prefer).
Personally I don't like it in this way for development, I prefer them in the vendor/ folder else it's a pain to update it to newer a version.
Since Laravel 5 Taylor wanted to make package development not too specific anymore, like in Laravel 4. The only thing what you can do (but not have to) to make your package using Laravel is using the ServiceProvider's. The ServiceProvider is the bootstrap into the Laravel application.
If you want to extend or implement your own functionality, fork the repo and build it yourself on top off it and host it (through github/packagist or a private repo using Satis).
Pingpong modules (2.1) is build for Laravel 5 and they you described (Embedded Laravel Package) is more for Laravel 4, because the more specific way you have to write the package.
But, there is alternative?
Whenever you want a more active project/package for development you should tryout Asgard CMS. They are pretty modular and I thought I read somewhere it was inspired by this package (totally not sure).
How about building yourself?
Of course you can build your own packages to achieve the same result. And create it as modular as you want. I created a lot modules for my company and we can create pretty easy a entire system and using and extending/overriding modules. Even small parts from a module can be overwritten to project specific needs.
We have chosen for almost the same structure as the app/ folder which Laravel projects, in case of CMS/API modules.
A packages look like:
tests/
src/
Acme/
Controllers/
Requests/
Models/
Module.php // contains some specifc calculations for example
ModelServiceProvider.php
composer.json
In the composer.json file we autoload: "Module\\": "src/"
And in the config/app.php we register the ModuleServiceProvider. Now we injected the functionality into Laravel's container and can we use it through the app() instance.
But whenever we only want to use the Models with in another project or standalone, we can still use it because the autoloaded features from composer and the way we build the package. Possible to use:
<?php
require_once __DIR__ .'/vendor/autoload.php';
use Module\Models\Module;
$module = new Module;
Edit
The package structure we like to use, to have a section for API or CMS stuff:
tests/
src/
Cms/
Controllers/
Requests/
Api/
Controllers/
Transformers/
Models/
Module.php // contains some specifc calculations for example
Providers/
CmsServiceProvider.php // includes `ModuleServiceProvider`
ApiServiceProvider.php // includes `ModuleServiceProvider`
ModuleServiceProvider.php // contains global stuff like commands etc.
composer.json
and instead of registering ModuleServiceProvider in config/app.php we register the ApiServiceProvider or CmsServiceProvider depending on the wishes of the client/project.
To reuse your classes simply use php namespaces or use to call back your clases.
Using the namespace
namespace Acme\Tools;
class Foo
{
echo "me";
}
You can the call class foo
<?php
$foo = new \Acme\Tools\Foo();
Using Use.
You can also use use Statement as below :
<?php
use \Acme\Tools\Foo;
$foo = new Foo();
Use Middleware
You should also use middleware to filter who should use the scripts ie the Auth middle-ware , which will help you in filtering users , registrations , logins READ MORE http://laravel.com/docs/5.1/middleware
Use Eloquent
Use ORM to create REST apis to your models , its very simple , always let your controller class extend eloquent use Illuminate\Database\Eloquent\Model; ie as :
use Illuminate\Database\Eloquent\Model; .Read More http://laravel.com/docs/5.1/eloquent
Lastly Use Laravel In built Helper functions
There are numerous Laravel In built Helper functions , to use simply go over the documentation to help you
I've used pingpong modules. It a pretty cool package. I'm not sure if it's updated much. But it's a very simple package. The only thing it does is create a folder with almost the same structure as in the app folder + views. But these are modules. You can reuse it if you program them right. The same goes for the other answer from jimmy if you have a good structure you can reuse anything.
EDIT
In the image below you'll see an example of pingpong modules. As you it's pretty much the same structure as the app folder. Maybe more the root folder. Normally it runs start.php and you have a routes.php file int he Http folder. I customized mine a bit. And load the frontend and backend routes within the RouteServiceProvider. This is build with laravel 5.1.

Utility Classes In Ruby on Rails

This is probably a stupid question, but I'm new to Ruby on Rails and I could use a little guidance. I want to have a helper/utility class that performs a group of network operations and returns results. Where do I put that class and how do I use it.
I've created network_helper.rb in my app/modulename/helpers directory. In my controller when I try to do
myNetworkHelper = ModuleName::NetworkHelper.new
results = myNetworkHelper.getResults
I get an error
undefined method `new' for MyModule::NetworkHelper:Module
I'm sure this is just a misunderstanding of how ruby on rails works. Can I get some clarification?
Would it be better to make this a class instead of a module and put it in libs? And can I add subfolders in libs and have them automatically loaded?
Lib or Classes
Little utility classes like this typically go in the lib folder, though some people prefer to create a folder called classes. Whichever you choose, make sure you import the folder in config/application.rb, as the lib folder is not autoloaded:
config.autoload_paths += %W(#{config.root}/lib)
Concerns
If instead of a utility class, you want to extend some of your models with reusable code, you may also wish to look at the new Rails 4 concerns folders which encourage you to extract reusable modules:
see: How to use concerns in Rails 4
To use new, the thing your calling it on must be a class, not a module. You're using a module. Change module to class in lib/utilities/network_utility.rb.
I cannot verify this at the moment, however I believe one place you can store your custom modules and classes is the lib directory. Alternatively, you should be able to store them in the app directory in the manner you have indicated by adding the following line to your environment.rb:
config.load_paths << File.join(Rails.root, "app", "modulename")
Also, check out Yehuda Katz's answer, which I think not only answers your question better, but also contains some very interesting and useful information and concepts relating to your situation. Hope that helps!
Add your class to app/lib folder instead of lib, so that you don't change autoload paths!
Explanations:
The accepted answer suggests adding the classes to lib.
But according to this discussion:
The lib folder does not belong to the autoload paths since Rails 3.
So it's discouraged to add lib under autoload path. Use app/lib instead.

Ruby namespace etiquette and convention

If I'm writing a helper for an established library, should I create a TheirLibrary::MyHelper module in their namespace, or stay out and make my own ::TheirLibraryMyHelper?
I'm thinking to be predictably consistent, libraries often have precedent for adding extensions to their namespace, such as Spec::Rails, which is a plugin of rails helpers for RSpec, in the existing ::Spec namespace.
On the other hand, I don't feel I "own" the other authors namespace, so should I have any business adding sub-namespaces to it?
I would stay out of their namespace (whatever you end up choosing to name your extension namespace) because that means you aren't going to accidentally collide with something they decide to do down the road.
Looking around, I noticed that the convention for "plugin" or "extension" gems are required as:
require 'coolthing/plugin' which corresponds to the namespace Coolthing::Plugin
while other projects are
require 'coolthing-plugin' which corresponds to the unique namespace CoolthingPlugin
Generally only those that are "official" are embedded into the original namespace. Those that are follow-on additions from separate parties should use their own namespace.

Resources