Difference between using App::environment() vs app()->environment() vs config('app.env') - laravel

What's the difference between using App::environment() vs app()->environment() vs config('app.env') for checking environment? I assume the first two are the exact same thing, but what about those vs using config('app.env')?
What I can see the first two returns the whole service container instance, so is that worse for performance, but more secure or something? I'm reading that people recommend only using config() for your own config variables and for any other config variable that isn't the env one. Trying to figure out the reasoning.
Thanks!

App::environment() and app()->environment() are the exact same thing. The App facade and the app() helper function are both just shortcuts to access your application container.
In a web context (hitting your page from a browser), the App::environment() method and the config('app.env') function will return the same value.
In a cli context (artisan command, queued job, etc), the App::environment() method and the config('app.env') function could return different values. If the command being run is executed with the --env argument (ex: --env=testing), then the App::environment() method will return the actual detected environment ("testing"), whereas the config('app.env') function will continue to return the environment defined in your config file.
Two extra things to consider:
The environment() method is part of the public api. This means the only potential for breaking changes is on major releases. The app.env config value is not part of the public api. Laravel could change that at any point if they wanted to, even on a minor release. I doubt they ever would, but they've made no public promises.
The environment() method takes optional parameters to add a little syntactic sugar for testing your current environment. If you pass parameters, the method will return a boolean if you're in any of the supplied environments, instead of returning a string with the name of the current environment. The parameters are also treated as regex searches:
$isTesting = App::environment('test', 'testing', 'testarossa')
// or
$isTesting = App::environment('test*')
(the "*" is replaced with ".*" before the regex is run)

App::environment()
uses a Facade to get the environment, a facade of Illuminate\Foundation\Application.
app()
uses a helper function to return the \Illuminate\Container\Container::getInstance(). environment() in a method of this Container instance.
resolve()
is an alias for app() but expects a parameter e.g. resolve('config') or resolve(Application::class).
app()->make(Application::class)
Uses the Container to resolve the Application. This is equal to app(Application::class).
Config::get('app.env')
uses the Facade of \Illuminate\Config\Repository.
config('app.env')
uses a helper function to call app() to resolve the Config. You should only use env() when you are working in a config file located in config/.
public function __construct(Config $config)
uses dependency injection to resolve the Config.
Answer
When bootstrapping the Application, the config variables are loaded in this application using the Config.
So the Container uses Config to load the variables. Both are singletons, so calling them does not really affect the performance.
Which solution you choose sometimes depends on the use-case and mostly on preference.

Related

Fortify Scan - Possible Variable Overwrite: Global Scope

We had Forify scan for our website code and fortify reported few issues. We are using CodeIgniter 3.1.9 framework. One of the issue they mentioned as
Possible Variable Overwrite' for function 'extract()' in file mysqli_utility.php.
As this is core file of CI framework, I'm not using this function directly and also I do not know where this function getting used by CI.
Will you please help to resolve the issue reported by Fortify? What could be the solution?
extract() imports variables from an array into the current symbol table. The phrase "current symbol table" basically means into the current scope of the code. For the usage in question, extract() is called inside a class method. So the current scope for the extracted vars will be in that method and that method only for that instance of the class.
CodeIgniter's core code does not define or use global variables. Unless code developed for the application uses globals (which it should not as "globals" are more of a "procedural programming" thing) the possibility of overwriting is exceedingly low.
I'm curious as to why the scan didn't pick up all the other times extract is used by CodeIgniter.

Manually calling controller method with parameter and still have method injection

How can I call a controller method manually specifying some input parameters yet still have method injection work for the parameters not specified (example below).
routes.php
$myController->index($id);
controllers/MyControllerOne.php
class MyControllerOne
{
public function index($id, MyRequest $request)
{
}
}
extra information
The reason I need this is because I have special information in my routes that determines which controller should be executed such as /myroute/{data}/{id}. It's a bit unorthodox but it's a necessary evil given the scope of our system.
Once I resolve within my routes which controller needs to be called I then want to call the method on that controller. $controllerInstance->index($id).
If it's only for Request, I think you could manually pass this $this->app->make('Request'), like so
$controllerIntance->index($id, $this->app->make('Request'))
Note that you actually don't have to inject Request, since you might as well use App::make inside of your controller. But I'm not sure how good this decision is in case of testability and coupling.
For more info:
This function resolves 'Request' out of the container, that is instantiates or returns an existing instance (depending of the type of service provider).
Using make is described here http://laravel.com/docs/5.0/container (see "Resolving"). I also found this answer helpful, to understanding how the container works https://stackoverflow.com/a/25798288/1627227

Dynamically get the public path for a workbench package in laravel

I'd like to get the path to a package public directory (css etc) based on the package alias.
Is there anything already built into the laravel framework?
In other words something like:
public_path('myalias');
When I'm talking about alias, you would typically "alias" a module by adding the following within your service provider's boot method:
$this->package('namespace/package','alias_name');
For those wondering why someone might want to do this:
We are running a multi domain/subdomain application that makes use of a central piece of code for all of the domains and then specific packages per domain (I'll refer to them as funnels).
Each funnel has its own controllers that can possibly extend base controllers to implement their own functionality while re-using code where they can. They also have their own views.
The funnel refers to its own views by way of something like:
View::make('funnel::path.to.view')
The way we accomplish this is by doing some business logic on page load to only load the FunnelServiceProvider related to that particular domain and aliasing it to "funnel". This way our base controllers can also refer to funnel and not be tied to a particular packages views,includes,blocks etc.
My hope is to do something similar on the views so that I can simply call something like get_funnel_path() to get the path to the funnel that is currently being loaded.
The value could then be used to load css,js,images etc without worrying about the funnel path.
This would allow us to simply copy and paste views from one domain to the next without having to modify all of the paths in potentially multiple files. We could also make use of globally included files in all/most of the views.
An example of this might be the head. The head section should be the same for 99% of the files, however the path where it loads its resources should change based on the funnel.
We use the same naming conventions for css files as well as use sass, imports, merging for all of the funnels; so only the path needs to change.
You can do something like this although it will only work with your own packages and require a bit of work. Because the alias is not really stored somewhere you can easily access you have to do that yourself.
First create some kind of class to store your package names in. I called mine PackageManager:
class PackageManager {
private $packages = array();
public function addPackage($fullName, $alias){
$this->packages[$alias] = $fullName;
return $this;
}
public function getPublicPath($alias){
if(!isset($this->packages[$alias])) return public_path();
$path = 'packages/' . $this->packages[$alias];
return public_path($path);
}
}
Now let's register that class as a singleton in a service provider:
$this->app->singleton('packagemanager', function(){
return new PackageManager();
});
Then, in every package you want to register, add this call in the boot method right next to $this->package():
$this->app['packagemanager']->addPackage('vendor/package', 'alias');
After that you can do this anywhere in your application:
app('packagemanager')->getPublicPath('alias');
If you want a shorter syntax, add this helper function somewhere:
function public_package_path($alias){
return app('packagemanager')->getPublicPath($alias);
}
And just do:
public_package_path('alias');

CodeIgniter - Private functions

I have started playing with CodeIgniter now.
And I use their user guide and other third-party tutorials available for learning. I'm a bit stuck at the naming of private functions. Based on the user guide, I have to prefix a _ in the name of private functions. But in this tutorial, check the Add Logout section. In it, there is a private function: private function check_isvalidated(). Here, it is not prefixed with the character _.
So that's also an accepted naming convention ?
At the same time, there is another one called _output(): Processing Output.
It's a public function with the naming convention of a private function !
It's a bit of confusing when I try to learn in a systematic manner.
The _ prefix is a convention for functions defined in the CONTROLLER.
The user guide says:
In some cases you may want certain functions hidden from public access. To make a function private, simply add an underscore as the name prefix and it will not be served via a URL request.
http://www.codeigniter.com/user_guide/general/controllers.html#private-methods
Adding an _ is CodeIgniter's own way of declaring functions in the controller (only in the controller) that cannot be called directly by the user:
Controller functions are mapped to parts of the URL (controller/function)
there are functions in the controller which should NOT be mapped to the URL
- they are declared as `private` (available since PHP5)
OR
- their names start with `_` (works also for PHP4)
Regarding _output function, it is public, but it cannot be called directly since it contains _.
Why is public?
The function is called by the system, so it needs to be accessible from outside the class, it is not a private function. But, it contains _ to make sure it is not called via the URL.
To sum up, if you have functions in your controller which you don't want to be called directly via the url, add _ prefix OR use the private access operator. Either one of them is good enough.
FYI, other frameworks like Yii or Zend framework, use the action prefix for all controller functions which CAN be called via the URL (are mapped).
While the user guide does say that you have to prefix the function name for private functions inside a controller with an underscore, it is not mandatory to do so. Although, it might be a good idea to follow the convention and it is recommended that you do so.
The noticeable effect when prefixing the function name with an underscore can be seen if the access modifier is public. In this case, if you try to access the function via URL will give you a 404 error. But in the case, that you have the access modifier set to private it does not matter whether if you prefix the function name with an underscore.
But in this tutorial, check the Add Logout section. In it, there is a
private function: private function check_isvalidated(). Here, it is
not prefixed with the character _.
In that tutorial, the function name is not prefixed with an underscore, but it is a private function because it is declared to be one. Thus, trying to access it via URL will not work.
At the same time, there is another one called _output(): Processing
Output. It's a public function with the naming convention of a private
function!
I've already explained this, but I want to point out that the _output() function is one of those special functions that will be called at a certain point during a script execution. In this case, CodeIgniter will call this function at the end of the function, right when it's time to output something to the browser.

Codeigniter: Use of load_class

I am writing my own logging class to save data in a DB. As I looked how CI is doing I noticed there is a log_message() function which handles the logging. There is a load_class function I can't assign to anything in the CI user guide.
1 Why do they put this into an extra function?
2 What/where loads this function files from?
Hope there are some CI guys how can answer :-)
Short answer:
You can write your own log class to override the default CI class:
<?php
// this file is /application/libraries/MY_Log.php
class MY_Log extends CI_Log {
public function write_log($level = 'error', $msg, $php_error = FALSE)
{
// Put your own logging function in here.
// If you want it to still log to a file as usual, use this:
parent::write_log($level, $msg, $php_error);
}
}
Long answer:
The load_class() function is basically a singleton loader. If the class has already been loaded, return a previous instance; otherwise, load it and create the singleton. It is very important in a framework like CI. You have to know that every time you call, say, a database function, it is applying it to the same object, not instantiating a new one (that would get really messy). All CI libraries function this way by default.
An important note: they changed how this functions significantly in version 2.0. Previously, it would only load from the /libraries folder, but now, it will load from /core or wherever you specify when calling the function.
Here's the process for loading, say, the Log class (from your example):
$_log =& load_class('Log');
$_log->write_log($level, $message, $php_error);
This runs the following checks, in sequence:
If the Log class already exists, we're done. Return the singleton.
If not, first check the /system/libraries folder for a "Log.php" file
If no file existed for step #2, now check /application/libraries for a "MY_Log.php" file (or whatever your subclass prefix is set to in your configuration)
If it loaded the default CI class (from the /system folder), but you DO have an extended class under /application, load that class too.
Return a new instance of the class (YOURS if it exists; otherwise, it's the CI_* class)
I've actually never needed to use the load_class() function, as it allows extension fairly seamlessly. However, it's good to know how it works.
So, to override a class, first find where the original resides (usually /system/libraries or /system/core). Put your extending file in the corresponding /application folder (this is important! If it's under /system/core, the extension MUST be under /application/core). Prefix both the filename and the class name with MY_ (or whatever you set in your configuration), and have it extend the CI_ base class.

Resources