how laravel autoload classes and use them without initiate it? - php

I am trying to deep dive laravel concept. In the very first step i got stuck. Loading different classes and use them.
In the laravel routing (where you can register web routes for your application), there is no any use keyword used for using class and initiate Route class in web.php
Route::get('/home', 'HomeController#index')->name('home');
how Route::get run without using any class?
And when we go more deep using model class
namespace hosam\Http\Controllers\Auth;
use hosam\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Auth;
use Illuminate\Support\Facades\DB;
and we use Auth in aur code like this.
Auth::login($user);
from using use keyword does php load auth class in our code where we are using Use Auth?

All the route files under routes folder are loaded automatically by laravel. routes/web.php and laravel/api.php are assigned to middleware web and api respectively.
All the classes and namespaces in laravel are loaded from the composer autoloader.
These files are mapped in the RouteServiceProvider class under Provider folder. So that class use Route facade. As the web.php and api.php is not called directly so there is no need to initiate the class in the particiular file
//RouteServiceProvider.php
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
Routing

You can also make your Helper folder with HelperClass and run can be run from any where
make folder in app > Helpers folder.
make helper class Helpers.php
where you can write all your function like
function write_yourfunction(){
// your code
// return something
}
to load every where you can use service provider. Edit app > Providers > AppServiceProvider.php
public function register()
{
foreach (glob(app_path() . '/Helpers/*.php') as $filename) {
require_once($filename);
}
}
Now you can call write_yourfunction() from everywhere

Related

PHP Laravel - Controller does not exist

I am new to PHP and Laravel. I am creating my first Laravel API where I am working with Post object.
In order to do so I use a PostController. I have created this controller using the php artisan command: php artisan make:controller PostController --api. This created a PostController class inside the app\Http\Controllers.
When I want to append this controller to the api routes using the Route::resource function I came across something strange. The course I followed told me to declare the controller like so: Route::resource('posts', 'PostController');. When testing the api php artisan route:list this gave the following error:Target class [PostController] does not exist.
Then I did some research and found an other way to declare the controller inside the api routes using:
use App\Http\Controllers\PostController;
Route::resource('posts', PostController::class);
This worked for me but I don't have any clue why the first declaration failed. I have looked inside my PostController class to see any typo's. But I couldn't find any:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
...
}
The reason for this is just like the exception says: it could not find the PostController in your declared namespace.
The reason for that highly depends on the Laravel version you are using. Laravel 8 removed the default namespacing to App\Http\Controllers, so if you are using Laravel 8 but have followed a tutorial for an earlier Laravel version, that might be the reason.
However, using the declaration using class imports is the better way to do it anyways, so I would stick with that.
Since Laravel 8, there were some changes to the automatic controller namespace prefixing.
https://laravel.com/docs/8.x/upgrade#routing
You can continue to use the original auto-prefixed controller routing, see the 4th paragraph on the upgrade documentation. But the new way is recommended.
You should tell Route::resource method the controller's namespace. As you did in your second try.
If you wanna do it with your first attempt, you can tell it the required namespace
Route::resource('posts', 'App\Http\Controllers\PostController');
You can also set the namespace in your App\Providers\RouteServiceProvider:
public function boot()
{
$this->routes(function () {
Route::prefix('api')
->middleware('api')
->namespace('App\Http\Controllers\Api')
->group(base_path('routes/api.php'));
});
}

Do I need to have Controller.php in all my API subversion?

I am trying to create an API directory in my Laravel project and I'm receiving the following error...
Class 'App\Http\Controllers\Controller' not found
I have tried using use App\Http\Controllers\Controller; on top of my API controllers but no luck.
My API classes are defined like...
class SyncController extends Controller {...}
class TimecardController extends Controller {...}
I'm pretty sure the error is coming from the extends Controller portion.
in App\Http\Controllers\Controller I have Controller.php. One way I have pushed past this is to duplicate the Controller.php into App\Http\Controllers\Api\v2\ and change the namespace of that controller to match where it is located (namespace App\Http\Controllers\Api\v2;)
I don't believe this is correct, as there should be a way to reference the Controller.php from the controllers in the API subdirectory.
../Controllers/Controller.php and API is a subdirectory, ../Controllers/Api/v2/SyncController.php
Any help would be much appreciated.
Thanks
-----------Edit------------
my routes for the api look like so
Route::group(['prefix' => 'api/v2'], function () {
Route::get('sync', 'Api\v2\SyncController#sync')->middleware('auth:api');
Route::post('timecard', 'Api\v2\TimecardController#create')->middleware('auth:api');
});
The Controller class cannot be found because the API controllers are not in the default Laravel controller directory. You need to add the controller class as a use statement. Then the autoloader will be able to find it.
namespace App\Http\Controllers\Api\v2;
use App\Http\Controllers\Controller;
class SyncController extends Controller {...}
And while your at it you might also want to add the auth:api middleware to the entire group. Much safer and efficient.
Route::group(['prefix' => 'api/v2', 'middleware' => 'auth:api', 'namespace' => 'Api\v2'], function () {
Route::get('sync', 'SyncController#sync');
Route::post('timecard', 'TimecardController#create');
});

Can't use a new provider in Laravel

I would like to use Laravel Searchy github here in my RegisterController.php using Laravel 5.4
I followed this :
Add the service provider to the providers array in Laravel's ./config/app.php file:
TomLingham\Searchy\SearchyServiceProvider::class
Add the Alias to the aliases array in Laravel's ./config/app.php file if you want to have quick access to it in your application:
'Searchy' => TomLingham\Searchy\Facades\Searchy::class
Problem
Class searchy does not exist
RegisterController.php
namespace App\Http\Controllers\Auth;
use Searchy;
class RegisterController extends Controller {
public function example () {
Searchy::search('companies')->fields('name')->query('test')->getQuery()->limit(1)->get();
}
}
Question
What should I do to be able to use it ?
Add This In Top of Your File
use TomLingham\Searchy\SearchBuilder;
OR
Try This In Composer
php artisan vendor:publish

Laravel 5, View::Share

I'm trying to do a view::share('current_user', Auth::User()); but in laravel 5 i can't find where to do this, in L4 you could do this in the baseController, but that one doesn't exists anymore.
grt Glenn
I am using Laravel 5.0.28, view::share('current_user', Auth::User()) doesn't work anymore because this issue https://github.com/laravel/framework/issues/6130
What I do instead is, first create a new service provider using artisan.
php artisan make:provider ComposerServiceProvider
Then add ComposerServiceProvider to config/app.php providers array
//...
'providers' => [
//...
'App\Providers\ComposerServiceProvider',
]
//...
Then open app/Providers/ComposerServiceProvider.php that just created, inside boot method add the following
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
View::composer('*', function($view)
{
$view->with('current_user', Auth::user());
});
}
Finally, import View and Auth facade
use Auth, View;
For more information, see http://laravel.com/docs/5.0/views#view-composers
First, you can probably create your own BaseController and extend it in other controllers.
Second thing is, that you may use Auth:user() directly in View, you don't need to assign anything in the view.
For other usages you can go to app/Providers/App/ServiceProvider.php and in boot method you can View::share('current_user', Auth::User()); but of course you need to add importing namespaces first:
use View;
use Auth;
because this file is in App\Providers namespace
In Laravel 5 uses the same method as in laravel 4:
View::share('current_user', Auth::User());
or using the view helper:
view()->share('current_user', Auth::User());
See in http://laravel.com/docs/5.0/views
This will may help:
App::booted(function()
{
View::share('current_user', Auth::user());
});
I'v tried it, put it in app/Providers simply not working. The alternative way is to create a Global middleware and put View::share('currentUser', Auth::user()); there.

Adding routes to laravel via plugins

I am working on designing a specific web framework that allows our team to add new components as plugins, then allowing customers to add these plugins or modules using a control panel.
With CodeIgniter things were easy , just copy the controller into the controllers folder and the client-side module will find its way via the URL app/index.php/module/function
But Laravel doesn't allow such dynamic routing.
Is there anyway to extend the route configuration without editing the routes.php by hand ?
You can simply add any routes you want in your service provider's 'boot' method:
public function boot()
{
$this->app['router']->get('my-route', 'MyVendor\Mypackage\MyController#action');
}
If you want to have a kind of automatic prefix, that doesn't happen automatically, but it's not too hard to create one:
public function boot()
{
$this->app['router']->group(['prefix' => 'my-module'], function ($router) {
$router->get('my-route', 'MyVendor\MyPackage\MyController#action');
$router->get('my-second-route', 'MyVendor\MyPackage\MyController#otherAction');
});
}
A lot of people will have this prefix as a config variable so that developers can choose the prefix they want (if you do this remember to name your routes so you can refer to them easily):
public function boot()
{
$this->app['router']->group(['prefix' => \Config::get('my-package::prefix')], function ($router) {
$router->get('my-route', 'MyVendor\MyPackage\MyController#action');
$router->get('my-second-route', 'MyVendor\MyPackage\MyController#otherAction');
});
}
I know I'm bit late but in Laravel 5.4 we can achieve something like this:
Step 1 Create your package and create service provider in it.
Step 2 Register your package service provider in laravel config app.
Step 3 Now create a sperate routes service provider which will contain following
namespace MyPackage\Providers;
use App\Providers\RouteServiceProvider;
use Illuminate\Support\Facades\Route;
class MyPackageRouteServiceProvider extends RouteServiceProvider
{
protected $namespace='MyPackage\Controllers';
public function boot()
{
parent::boot();
}
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
}
protected function mapApiRoutes()
{
Route::prefix('Mypackage\api')
->middleware('api')
->namespace($this->namespace)
->group(__DIR__ . '\..\Routes\api.php');
}
protected function mapWebRoutes()
{
Route::prefix('Mypackage')
->middleware('web')
->namespace($this->namespace)
->group(__DIR__ . '\..\Routes\web.php');
}
}
Note: I'm considering there is Routes Folder and contain web.php and api.php file. According to your question you want to load it dynamically you can have a constructor function and pass the package name, prefix and namespace as per your ease.
Step 4 Now the final step is registering the service provider you can call something like this in your package service provider:
public function boot()
{
$this->app->register('Mypackage\Providers\MyPackageRouteServiceProvider');
}
Hope this helps. Cheers
Just some theory
That's in fact pretty easy! When you think about it, Laravels routing layer is also just a component that is bound to Laravels container.
That allows us to grab it from there wherever we're accessing the container. Since you're trying to modify routes in a package, a great place to do it would be in your packages Service Provider.
Also, when doing that in a Service Provider you'll automatically have access to the app property (Your service provider is a child class of Laravels ServiceProvider class) and you can grab the router pretty easy!
Hands on code
<?php namespace My\Packages\Namespace;
use Illuminate\Support\ServiceProvider;
class MyPackageProvider extends ServiceProvider {
public function boot()
{
$this->app['router']->get('package-route', function(){
return "I just dynamically registered a route out of my package";
});
}
}
That's the Service Provider of your package. The only thing the user will have to do is to add the Service Provider to his providers array in the config/app.php.
Be careful!
When a user has defined a route that is identically named as your dynamically added route, your route will be overwritten. Make sure that you're using some kind of route prefixes if you are dynamically adding routes.
Further Reading
Laravel Docs - IoC Container

Categories