Serious issues understanding namespacing in Laravel 5 - laravel

I am having problems understanding namespacing. It just feels so stupid that for every Facade or helper I want to include, I need to included it in the controller file.
So, say I have this exerpt of my controller:
<?php namespace App\Http\Controllers;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Auction;
use App\Bid;
use App\BidBuy;
use App\Http;
use Redirect;
use Session;
use Illuminate\Http\Request;
use Omnipay\Omnipay;
class PayPalController extends Controller {
private $data;
public function getPayment()
{
redirectIfNotLoggedIn();
}
The line with redirectIfNotLoggedIn(); is a function I want to call that is stored in App/Http/helpers.php
This is the file: helpers.php
<?php namespace App\Http;
class HelperFunctions {
// Filter for guest only pages
public function redirectIfLoggedIn() {
if (Session::has('steamid')) {
return Redirect::to('/');
} else {
return false;
}
}
// Filter for logged users only pages
public function redirectIfNotLoggedIn() {
if (Session::has('steamid')) {
return true;
} else {
return Redirect::to('/');
}
}
}
Back in the controller I have included: use App\Http;
When I go to call that function I get this:
FatalErrorException in PayPalController.php line 20:
Call to undefined function App\Http\Controllers\redirectIfNotLoggedIn()
EDIT:
Now I have: HelperFunctions.php located at App/Helpers/HelperFunctions.php:
<?php namespace App\Helpers;
use Session;
use Redirect;
// Filter for guest only pages
function redirectIfLoggedIn() {
if (Session::has('steamid')) {
return Redirect::to('/');
} else {
return false;
}
}
// Filter for logged users only pages
function redirectIfNotLoggedIn() {
if (Session::has('steamid')) {
return true;
} else {
return Redirect::to('/');
}
}
Excerpt of composer.json:
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
},
"psr-0": {
"Ignited\\LaravelOmnipay": "src/"
},
"files": [
"app/Helpers/HelperFunctions.php"
]
},
And this is my controller:
<?php namespace App\Http\Controllers;
//use App\Helpers\HelperFunctions;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App\Auction;
use App\Bid;
use App\BidBuy;
use Redirect;
use Session;
use Illuminate\Http\Request;
use Omnipay\Omnipay;
class PayPalController extends Controller {
private $data;
public function getPayment(\App\Helpers\HelperFunctions $helper)
{
$helper->redirectIfNotLoggedIn();
}
.. rest of the controller code here ..
}

Do not use helpers for this. You are violating pretty much everything related to OOP in doing so.
Instead, use Middleware.
In your controller, simply require the auth middleware:
public function __construct()
{
$this->middleware("auth");
}
You are trying to solve a solved problem. If you need to do something before executing a route/controller method, middleware (the Laravel 5 replacement for route filters) should be used.
You will likely have to customise your own middleware, however, then add it to the middleware array in app/Http/Kernel.php. Just use php artisan make:middleware CustomAuthMiddleware.

You could use your HelperFunctions via method injection in your controller. Like this:
public function getPayment(\App\Http\HelperFunctions $helper)
{
$helper->redirectIfNotLoggedIn();
}
It's not tested.

Related

Laravel and Local Tunnel integration

My idea was to use Local Tunnel's subdomain feature to expose callback URI in a more convenient way. However, I believe that I could've achieved the same results in a simper way.
This is the solution with Laravel Valet:
In package.json I've added a script called shared
"scripts": {
...
"share": "lt --port 80 --subdomain blog --local-host blog.test"
}
In AppServiceProvider.php I've extended the UrlGenerator to avoid redirecting back to http://blog.test
<?php
namespace App\Providers;
use App\Services\LocalTunnelUrlGenerator;
use Blade;
use Illuminate\Http\Resources\Json\Resource;
use Illuminate\Routing\Router;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
(...)
}
public function register()
{
$this->enableLocalTunnel();
}
private function enableLocalTunnel()
{
if (!app()->environment('local') || !config('app.use_local_tunnel')) {
return;
}
$this->app->extend('url', function (UrlGenerator $defaultGenerator) {
/** #var Router $router */
$router = $this->app['router'];
$routes = $router->getRoutes();
return new LocalTunnelUrlGenerator($routes, $defaultGenerator->getRequest());
});
}
}
This is the the LocalTunnelUrlGenerator.php:
<?php
namespace App\Services;
use Illuminate\Http\Request;
use Illuminate\Routing\RouteCollection;
use Illuminate\Routing\UrlGenerator;
class LocalTunnelUrlGenerator extends UrlGenerator
{
public function __construct(RouteCollection $routes, Request $request)
{
parent::__construct($routes, $request);
}
public function formatRoot($scheme, $root = null)
{
return "https://blog.localtunnel.me";
}
}
Why all that? Because whenever the application call the redirect() method, we are sent back to http://blog.test.
Do I really need to extend the UrlGenerator to make it work?

Returning views using controller present somewhere else other than Views folder

How to return view present somewhere other than views folder from the controller in Laravel? I am making a project divided into modules. I want to return the view of the module from the controller of the main project. How to do it?
Because currently when I try to route to other links it shows:
MethodNotAllowedHttpException in compiled.php line 8895
Routes/web.php:
Route::get('/', function () {
return view('welcome');
});
Route::post('/navpage1',[
'uses'=>'ProjectController#nextpage1',
'as'=>'navpage1'
]);
Route::post('/navpage2',[
'uses'=>'ProjectController#nextpage2',
'as'=>'navpage2'
]);
Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
class ProjectController extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
public function nextpage1()
{
return view('C:/xampp/htdocs/larve/app\Modules\Course_Entry\views\welcome');
}
public function nextpage2()
{
return view('C:/xampp/htdocs/larve/app\Modules\Log_in_blog_post\views\welcome');
}
}
App/Modules/ServiceProvider.php:
<?php namespace App\Modules;
class ServiceProvider extends \Illuminate\Support\ServiceProvider
{
public function boot()
{
$modules = config("module.modules");
while (list(,$module) = each($modules)) {
if(file_exists(__DIR__.'/'.$module.'/web.php')) {
include __DIR__.'/'.$module.'/web.php';
}
if(is_dir(__DIR__.'/'.$module.'/Views')) {
$this->loadViewsFrom(__DIR__.'/'.$module.'/Views', $module);
}
}
}
public function register(){}
}
I know something is wrong with my controller, but i am just trying to figure out how to do it...
I have given more code here: Laravel program divided into modules
change the paths in app->config->view.php.
'paths' => [
realpath(base_path('app\Modules\Log_in_blog_post\views')),
],
then use in controller:- view('welcome').

Laravel Pass Authenticated to Every View

I need to pass a collection to every view; the collection contains the IDs of the items in the user's shopping cart. I've tried Service Providers and a BaseClass but neither worked as (apparently) Auth hasn't been registered at those points and only returns null.
What's the best way get records from an authenticated user and pass it to every view?
Edit: here's the relevant code
User.php
public static function getCart()
{
if (Auth::guest()) {
return [];
}
$collection = new \Illuminate\Database\Eloquent\Collection();
$collection = Auth::user()->cart()->pluck('post_id');
return $collection;
}
CartServiceProvider.php
namespace App\Providers;
use View;
use App\User;
use Illuminate\Support\ServiceProvider;
class CartServiceProvider extends ServiceProvider
{
public function boot()
{
View::share('cart', User::getCart());
}
public function register()
{
//
}
}
In any view...
<?php dd($cart); ?>
returns [] because Auth hasn't been registered yet, so the empty array is returned.
Found the answer on Laracasts and it seems to work quite well.
https://laracasts.com/discuss/channels/general-discussion/l5-service-provider-for-sharing-view-variables
From the OP #imJohnBon: "I managed to solve this issue by creating 2 files. First a ComposerServiceProvider which uses a wildcard to be applied to every view and not just particular views:"
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Contracts\View\Factory as ViewFactory;
class ComposerServiceProvider extends ServiceProvider {
public function boot(ViewFactory $view)
{
$view->composer('*', 'App\Http\ViewComposers\GlobalComposer');
}
public function register()
{
//
}
}
"And then the corresponding GlobalComposer where I share variables that should be available in all views:"
namespace App\Http\ViewComposers;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Auth;
class GlobalComposer {
public function compose(View $view)
{
$view->with('currentUser', Auth::user());
}
}

Laravel 5.2 custom helper not found

I have created app/Http/helpers.php
if (!function_exists('getLocation')) {
function getLocation($request)
{
return 'test';
}
I have added files section in composer.json autoload
"autoload": {
"classmap": [
"database"
],
"psr-4": {
"App\\": "app/"
},
"files": [
"app/Http/helpers.php"
]
},
Here is my controller :
namespace App\Http\Controllers;
use App\Jobs\ChangeLocale;
use App\Http\Requests;
use Illuminate\Http\Request;
use DB;
use Log;
class HomeController extends Controller
{
public function index(Request $request)
{
$data['location'] = getLocation($request);
}
}
When I call the function in controller as getLocation($request); it is saying "Call to undefined function App\Http\Controllers\getLocation()"
This is working fine in my local , but not on remote server. What am I missing in my remote server. Tried composer install and composer dump-autoload.
UPDATE:
The helper file is not getting listed in vendor/composer/autoload_files.php
On server, you need to execute:
composer dumpautoload
because it is not found on vendor/autoload.php
Try like this,
create Helpers directory inside the app directory.
create a Example.php file inside the Helpers directory
create a alieas for this file at config/app.php file
Ex: 'Example' => App\Helpers\Example::class,
The code in the Example.php like follows,
<?php
namespace App\Helpers;
class Example
{
static function exampleMethod()
{
return "I am helper";
}
}
Using the above Example helper in Controller files like follows,
<?php
namespace App\Http\Controllers;
use App\Helpers\Example;
class HomeController extends Controller
{
public function index(Request $request)
{
return Example::exampleMethod();
}
}
Using the above Example helper in blade view files like follows,
<div>{{ Example::exampleMethod()}}</div>
This will help you to get solution.
Make Sure the structure of the Helper.php is correct...
<?php
//no namespace, no classes
//classes are not helpers
if ( !function_exists('nextStage') ) {
function nextStage($currentStage) {
//if you need to access a class, use complete namespace
return \App\Models\Stage::where('id',$currentStage)->first()->next_stage;
}
}
More help on Laracast found here

Facade not found by AliasLoader in Laravel

I added a custom facade to my 'config/app.php' in my laravel project under 'aliases'
'GeoLocation' => '\App\Facades\GeoLocation',
The folder of the custom class is in 'app/Facades/GeoLocation.php' and the service provider in 'app/Providers/GeoLocationServiceProvider.php'
How do I need to state the correct alias in the app.php to be able to load the Facade correctly? The error message is:
ErrorException in AliasLoader.php line 63:
Class 'Facades\GeoLocation' not found
This is my facade:
<?php namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class GeoLocation extends Facade {
protected static function getFacadeAccessor() { return 'geolocation'; }
}
Could it be that the return value of my service provider is incorrect?
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class GeoLocationServiceProvider extends ServiceProvider {
public function register() {
\App::bind('geolocation', function()
{
return new GeoLocation;
});
}
}
For a test I created another service provider called custom function:
<?php namespace App\Helpers;
class CustomFunction {
//Generate random float between -1 and 1
function f_rand($min = 0, $max = 1, $mul = 1000000) {
if ($min>$max) return false;
return mt_rand($min*$mul, $max*$mul) / $mul;
}
function test() {
echo "OK";
}
}
<?php namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class CustomFunctionServiceProvider extends ServiceProvider {
public function register() {
\App::bind('customfunctions', function()
{
return new CustomFunction;
});
}
}
the simplest way is to change the namespace to the file app/Facades/GeoLocation.php' to App\Facades;
then update aliase registration to
'GeoLocation' => 'App\Facades\GeoLocation',

Resources