Actually, I am trying to define a constant and setting value from the session
in a custom helper added using Helper Service Provider. But not getting the session data in here.
I have added a Helper using Helper Service Provider, It's working fine.
But trying to get the session value.
In HelperServiceProvider.php
public function register()
{
foreach (glob(app_path().'/Helpers/*.php') as $filename){
require_once($filename);
}
}
And in ERPHelper.php in App/Helpers folder, I am trying to get the session data. But not getting the session value.
$company = session('company');
This is often down to the middleware. If you're setting the company session value under the web middleware, you might not be able to retrieve this is in a helper function registered by the service provider.
Also, out of interest, why are you setting this in a constant? It seems odd to me to use a the session helper to retrieve a value and then set it in a constant. A constant should probably not be used in this way but also you are adding an additional layer of abstraction. Why not just call session('company') as and when you need it?
I load in a helper Bootstrap.php via the composer.json file in the autoload section:
"autoload": {
"files": [
"app/Helpers/Bootstrap.php"
],
"psr-4": {
"App\\": "app/"
},
"classmap": [
"database"
]
},
Then in the Bootstrap.php you could run your glob to load the relevant files.
That said, this still might not help because you're outside the web middleware. Can you not pass the session value to your helper function?
// Helper function.
function myErpHelper($companySessionValue) {
// My code here...
}
// Calling the helper function.
myErpHelper(session('company'));
Related
Please, don't talk to technical in the answers:-D I am not a hardcore programmer.
What is a good way to store certain functions in Laravel? I have functions that apply on a "post" only or "media" only, like getAttributeList or getComponents. I say "Post" and "Media" because both have their own controller, model and views. It feels wrong to put it in the model because that should be database stuff right? And traits are more for recurring functions all over the place, right? So, right now I have one big file called Helpers.php. And uh, it is getting large... should I simply separate it in PostHelpers.php, MediaHelpers.php etc? Or is there a more elegant way in Laravel to do it?
It is quite simple : Just check your composer.json file at root directory of ur app. and under autoload section add :
"autoload": {
"psr-4": {
"App\\": "app/"
},
"files": ["app/helper.php"],
"classmap": [
"database/seeds",
"database/factories"
]
"files": ["app/helper.php"], This is the line you need to add in ur composer file and provide the path to file .
In my case i have created a file helper.php in App directory where i keep all my functions .
after this run this command :
composer dump-autoload
Now u can access your functions anywhere.
In your composer json file check this snippet
"autoload": {
"files": [
"app/Helpers/global_helper.php"
],
As you see I have auto loaded 1 single file called global_helper.php in a folder called Helpers Now in this file I have a function called loadHelper(...$files)
What this function does is
if (!function_exists('loadHelper')) {
function loadHelper(...$file_names)
{
foreach ($file_names as $file) {
include_once __DIR__ . '/' . $file . '_helper.php';
}
}
}
You can pass your file name as array or string and it will include those files into your Controller constructor
So In my Controller whenever I want some helper function I create a saperate helper file for that controller then in constructor i ust include it.
I am not sure if there is any better solution but so far this is how I am making all my projects .
I hope this will help you ;)
On the documentation for Slim Framework, it says
In this example application, all the routes are in index.php but in
practice this can make for a rather long and unwieldy file! It’s fine
to refactor your application to put routes into a different file or
files, or just register a set of routes with callbacks that are
actually declared elsewhere.
It doesn't say how to actually do this though. My only thought is that you could split code into multiple PHP files and then use include or require in index.php to reference these.
I'm also not sure what it means by "register a set of routes with callbacks that are actually declared elsewhere"
Does anyone have any thoughts on this, since the application I'm wanting to build might have quite a few routes?
Being a micro-framework, Slim does not enforce any specific method. You can either find a ready-to-use structure (Slim Skeleton Application comes to my mind) or write your own; unlike other frameworks, Slim does not try to protect you from PHP.
Route definitions can be something as simple as an array of strings:
<?php // routes.php
return [
'/' => ['Foo\\Home', 'index'],
'/about' => ['Foo\\Home', 'about'],
'/contact' => ['Foo\\Contact', 'form' ],
];
... which you then load and process in your index.php entry point:
$routes = require('/path/to/routes.php');
foreach ($routes as list($path, $handler)) {
$app->get($route, $handler);
}
And you can leverage the existing Composer set up to auto-load your classes by adding the appropriate directories to composer.json:
{
"require": {
"slim/slim": "^3.3",
"monolog/monolog": "^1.19"
},
"autoload": {
"psr-4": {"Foo\\": "./Foo/"}
}
}
From here, it can get as complex as required: define routes in a YAML file, auto-load from defined classes, etc.
(Code samples are shown for illustration purposes and might not even be valid.)
There're some thoughts on it in Slim documentation
Instead of require's you can use composer autoloading
"register a set of routes with callbacks that are actually declared elsewhere"
From docs:
Each routing method described above accepts a callback routine as its final argument. This argument can be any PHP callable...
So you can do:
$routeHandler = function ($request, $response) { echo 'My very cool handler'; };
$app->get('/my-very-cool-path', $routeHandler);
But usually people use classes instead of functions:
http://www.slimframework.com/docs/objects/router.html#container-resolution
I think you almost get the basic idea right. I recommend reading chapter on routing a couple of times. It covers everything pretty good.
Happy coding and let me know if you need any other help!
I have some php lines which will be used very often in my application. So I would like to build a function and call it every where in my app. My function could be :
static function array_matiere($id_ecole) {
return $something;
}
I tried to put this code in a controller and then call it like that :
$liste_matieres = MatieresController::array_matieres(Session::get('id_ecole'));
It works, but where to put this kind of function ? in the controller ? in a method file ? what is the best practice ?
Thanks for your responses.
Dominique
There are multiple ways to implement this. look here
Method 1 This method is highly suggested by Laravel Expert ( JeffreyWay)
If your helper functions are similar to the way laravel 5 ones work, i.e Illuminate/Support/helpers.php you could just create a helpers.php and have composer do the autoloading for you.
Edit your composer.json file and add the file to the autoloading key. In my example my app is called Tasky so just add the files key and reference helpers.php.
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"Tasky\\": "app/"
},
"files": [
"app/Support/helpers.php"
]
},
That way you just create your file inside app/Support/helpers.php and all your common function based view helpers or other helpers can go here. If you take the class based approach then the above is great.
Also then remember to just run the following once.
$ composer dumpautoload
Source
Method 2
Please Follow the link and read answer & Its comments
Whenever u need to include a piece of code providing some functionality through out your application then the best way in Laravel is to make Service class inside app/Services and then you can use that class anywhere in your application using
use App\Services\YourServiceName;
I know that Blade already caches the compiled PHP for all blade views, but I would like to take this a step further. A website that I'm working on is modularized into component views and then pieced together in the default controller. Each of the "widgets" has its own view, which rarely changes content (with the exception of a few frequently updating ones). So, I'd like to cache the HTML output of these rarely-changing views to prevent them from being evaluated on every page load.
In Laravel 3 we could do something like so (credit Laravel forums):
Event::listen(View::loader, function($bundle, $view)
{
return Cache::get($bundle.'::'.$view, View::file($bundle, $view,
Bundle::path($bundle).'view'));
});
Unfortunately, View::loader has entirely disappeared in Laravel 4. When digging through \Illuminate\View\View and \Illuminate\View\Environment, I discovered that each view dispatches an event named "composing: {view_name}". Listening for this event provides the view name and data being passed to it on each view render, however returning from the callback does not have the same effect as it did in Laravel 3:
Event::listen('composing: *', function($view) {
if(!in_array($view->getName(), Config::get('view.alwaysFresh'))) {
// Hacky way of removing data that we didn't pass in
// that have nasty cyclic references (like __env, app, and errors)
$passedData = array_diff_key($view->getData(), $view->getEnvironment()
->getShared());
return Cache::forever($view->getName() . json_encode($passedData), function() {
return 'test view data -- this should appear in the browser';
});
}, 99);
The above does not circumvent the normal view including and rendering process.
So how can you circumvent normal view rendering and return cached content from this composing event? Is it possible currently in Laravel without some ugly hackery?
Quick and Dirty
Well, one option, as I'm sure you know, is to cache the items inside of controllers as the View is being rendered. I suspect you don't want to do that, as it's less maintainable in the long-run.
More maintainable(?) method
However, if the View loader/renderer doesn't fire an event where you want, you can create one. Because every package/library in Laravel 4 is set in the App container, you can actually replace the View library with your own.
The steps I would take is:
Create a library/package. The goal is to create a class which extends Laravel's view logic. After taking a look, you might want to extend this one - This is the View facade
If you extended the View facade with your own (aka if my assumption on the file in step 1 is correct), you'll then just need to replace the alias for View in app/config/app.php with your own.
Edit- I played with this a bit. Although I don't necessarily agree with caching a View result, vs caching sql queries or the "heavier lifts", here is how I'd go about doing this in Laravel 4:
The View rendering in Laravel 4 doesn't fire an event that let's us cache the result of a view. Here's how I've added in that functionality to cache a view's result.
You may want to consider the ramifications of caching a view's result. For instance, this doesn't get around doing the hard work of talking to a datbase to get the data needed for the view. In any case, this gives a good overview on extending or replacing core items.
First, create a package and set up its autoloading. I'll use the namespace Fideloper\View. It's autoloading in composer.json will looks like this:
"autoload": {
"classmap": [
"app/commands",
"app/controllers",
"app/models",
"app/database/migrations",
"app/database/seeds",
"app/tests/TestCase.php"
],
"psr-0": {
"Fideloper": "app/"
}
},
Next, create a class to replace the View facade. In our case, that means we'll be extending Illuminate\View\Environment.
In this class, we'll take the result of the View being rendered and add some logic to cache (or not cache) it. Here is Fideloper/View/Environment.php:
<?php namespace Fideloper\View;
use Illuminate\View\Environment as BaseEnvironment;
use Illuminate\View\View;
class Environment extends BaseEnvironment {
/**
* Get a evaluated view contents for the given view.
*
* #param string $view
* #param array $data
* #param array $mergeData
* #return \Illuminate\View\View
*/
public function make($view, $data = array(), $mergeData = array())
{
$path = $this->finder->find($view);
$data = array_merge($mergeData, $this->parseData($data));
$newView = new View($this, $this->getEngineFromPath($path), $view, $path, $data);
// Cache Logic Here
return $newView;
}
}
So, that's where the bulk of your work will be - filling out that // Cache Logic Here. However, we have some plumbing left to do.
Next, we need to set up our new Environment class to work as a Facade. I have a blog post about creating Laravel facades. Here's how to accomplish that in this case:
Create the facade for our new Environment. We'll name it fideloper.view in code.
<?php namespace Fideloper\View;
use Illuminate\Support\Facades\Facade;
class ViewFacade extends Facade {
/**
* Get the registered name of the component.
*
* #return string
*/
protected static function getFacadeAccessor() { return 'fideloper.view'; }
}
Then, create the Service Provider which will tell Laravel what to create when fideloper.view is called. Note that this needs to mimic functionality of the Illuminate\View\ViewServiceProvider for creating the extended Environment class.
<?php namespace Fideloper\View;
use Illuminate\Support\ServiceProvider;
class ViewServiceProvider extends ServiceProvider {
public function register()
{
$this->app['fideloper.view'] = $this->app->share(function($app)
{
// Next we need to grab the engine resolver instance that will be used by the
// environment. The resolver will be used by an environment to get each of
// the various engine implementations such as plain PHP or Blade engine.
$resolver = $app['view.engine.resolver'];
$finder = $app['view.finder'];
$env = new Environment($resolver, $finder, $app['events']);
// We will also set the container instance on this view environment since the
// view composers may be classes registered in the container, which allows
// for great testable, flexible composers for the application developer.
$env->setContainer($app);
$env->share('app', $app);
return $env;
});
}
}
Lastly, we need to hook this all together and tell Laravel to load our Service Provider and replace Illuminate's View facade with our own. Edit app/config/app.php:
Add the Service Provider:
'providers' => array(
// Other providers
'Fideloper\View\ViewServiceProvider',
),
Replace the View facade with our own:
'aliases' => array(
// Other Aliases
//'View' => 'Illuminate\Support\Facades\View',
'View' => 'Fideloper\View\ViewFacade',
),
You'll then be able to use whatever logic you wish in the View::make() method!
Finally
It's worth noting that there are some patterns to load in multiple "requests" per web request. Symfony, for instance, let's you define controllers as servers. Zend has (had?) a concept of Action Stacks, which let you
... effectively help you create a queue of [controller] actions to execute during the request.
Perhaps you'd like to explore that possibility within Laravel, and cache the results of those "actions" (vs caching a view directly).
Just a thought, not a recommendation.
There is a library for caching views/parts in Laravel(and not only) - Flatten.
It is a powerful cache system for caching pages at runtime. What it does is quite simple : you tell him which page are to be cached, when the cache is to be flushed, and from there Flatten handles it all. It will quietly flatten your pages to plain HTML and store them. That whay if an user visit a page that has already been flattened, all the PHP is highjacked to instead display a simple HTML page. This will provide an essential boost to your application's speed, as your page's cache only gets refreshed when a change is made to the data it displays.
To cache all authorized pages in your application via the artisan flatten:build command. It will crawl your application and go from page to page, caching all the pages you allowed him to.
Flushing
Sometimes you may want to flush a specific page or pattern. If per example you cache your users's profiles, you may want to flush those when the user edit its informations. You can do so via the following methods :
// Manual flushing
Flatten::flushAll();
Flatten::flushPattern('users/.+');
Flatten::flushUrl('http://localhost/users/taylorotwell');
// Flushing via an UrlGenerator
Flatten::flushRoute('user', 'taylorotwell');
Flatten::flushAction('UsersController#user', 'taylorotwell');
// Flushing template sections (see below)
Flatten::flushSection('articles');
link to - https://github.com/Anahkiasen/flatten
I am wondering where to put the Laravel Event Listeners and Handlers. Somebody told me that I can put them anywhere. This is what I have tried so far.
# listeners/log.php
<?php
Event::listen('log.create', 'LogHandler#create');
# handlers/LogHandler.php
<?php
class LogHandler {
public function create(){
$character = new Character;
$character->name = "test";
$character->save();
}
}
# controllers/MainController.php
public function test(){
Event::fire('log.create');
return "fired";
}
# start/global.php
ClassLoader::addDirectories(array(
app_path().'/commands',
app_path().'/controllers',
app_path().'/models',
app_path().'/database/seeds',
app_path().'/libraries',
app_path().'/listeners',
app_path().'/handlers',
));
I'm going to assume that you're asking this because they're not working, rather than for confirmation of something that you've got working.
Whilst it is correct that you can put event listeners anywhere, you need to make sure they'll actually get included - Laravel doesn't search through your source code looking for them.
My favourite place to include such files is in start/global.php. If you look at the bottom of the file you can see where the filters are included, you can do the same to include your listeners. It would be cleanest to keep them all in one listeners file, like all of your routes are in one routes file...
# start/global.php
require app_path().'/filters.php';
My personal opinion is that it's bad practice in general to lump event listeners in a single place. Sure, today you only need 2 or 3, but scope can be added to any project at any time, possible adding a lot more.
Instead, I generally create a directory underneath the app directory (e.g. app/CompanyName) and put all of my application specific code in there. To tell Laravel how to find your files, you can then update your composer.json llike this:
"autoload": {
"classmap": [
// ...
],
"psr-4": {
"CompanyName\\" : "app/"
},
}
After that, be sure to run composer dump-autoload.
Now, you can create namespace directories inside of your custom application directory, like app/CompanyName/Events/, and be able to segregate out your event listeners into groups that make sense, and put them inside of a service provider, for example:
<?php namespace CompanyName/Events;
// File: app/CompanyName/Events/LogEventsProvider.php
use Illuminate\Support\ServiceProvider;
class LogEventsProvider extends ServiceProvider
{
public function register()
{
Event::listen('log.create', 'CompanyName/Events/LogEventsProvider#create');
}
public function create()
{
// ...
}
}
Now you can add this service provider to your app/config/app.php and be good to go, and have all of your related event listeners in a single file, and ALL of your event listeners in a single directory, yet separate so that if something goes wrong with one of them you don't have to search through ALL of them to find where the error is happening.
NB: I did not come up with this as a practice, but found it somewhere along the way. I however cannot remember where it was.