Laravel 5 Controller from a Different namespace - laravel-5

I am trying to load controller that resides inside a package.
Package itself is on the root level in a folder like /packages/my/ ...
The package structure is like this:
/packages/my/framework/src/My/Controllers/PageController.php
Frist in my RouteServiceProvider:
$router->group(['namespace' => 'My\Controllers'], function($router)
{
require "...../routes.php";
});
in the composer.json in the root of laravel
"psr-4": {
"App\\": "app/",
"My\\": "packages/my/framework/src"
}
then composer dump-autoload , i can see its been added to autoload_psr4.php
the actual controller
<?php
namespace My\Controllers;
use App\Http\Controllers;
class PageController extends Controllers\Controller { .... }
But I am getting ReflectionException that the class does not exist. Obviously the routing part works, why it can't see the Controller?
Thanks!

closing my own question .. I was missing the root namespace in the psr-4 loader .. packages/my/framework/src/My

Related

Autoload with composer custom classes

I'm new to composer to manage the loading of my custom classes. I'm trying to add some custom classes to the autoload but without success, I will get always a Class not found... error.
How I will setup correctly composer, where I should put the composer.json file with the psr-4 info about my custom class/classes?
Can anyone help me understand how it will work in this case?
Here is my class code snippet, I'm using some composer packages so I need to autoload them. This file is placed in it's own directory. th structure looks like this: project_root\assets\library\MyClassFolder
<?php
namespace MyNamespace;
require_once __DIR__.'/vendor/autoload.php';
use \Foo\Bar;
class MyClass {
...
}
?>
This is the code where the class need to be loaded. This file is located inside my project root folder and it's causing the error:
<?php
require_once __DIR__.'/vendor/autoload.php';
use \MyNamespace\MyClass;
if( isset($_POST['do_action']) ){
MyClass::init();
}
?>
This is the composer.json file that is in the project root:
{
"require": {
"gabordemooij/redbean": "^5.3"
},
"autoload": {
"psr-4": {
"MyNamespace\\": "assets/library/"
}
}
}
I've found a fix, I was made a mistake inside the composer.json file. I was not pointing the namespace to the classes directory. This is why I've got a Class not found... error.
the composer file now look like this:
{
"require": {
"gabordemooij/redbean": "^5.3"
},
"autoload": {
"psr-4": {
"MyNamespace\\": "assets/library/MyClassFolder/"
}
}
}
I also needed to change the require_once inside the custom classes files to point to the vendor path where reside the autoload file.
Instead of
require_once __DIR__.'/vendor/autoload.php'
Now I've
require_once dirname(__DIR__, 3).'/vendor/autoload.php'
This because the

Where are namespaces declared in Laravel?

I learned in php that to be able to use a namespace, you have to declare or include first.
<?php
namespace namespace_01;
function f1()
{
echo 'this is function';
}
use namespace_01 as test_namespace;
test_namespace\f1();
?>
Almost all of laravel codes use namespaces. But where are they defined?
Example,
when I created a controller.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class controller1 extends Controller
{
//
}
where is Illuminate\Http\Request defined?
Open file from vendor/laravel/framework/src/Illuminate/Http/Request.php
There you will see the namespace declared on top as namespace Illuminate\Http; and the class name is Request
and you can see in your composer.json file
"autoload": {
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
so all the classes inside App folder are auto loaded with composer and also the vendor files. you don't need to include files every time.
These are found in the Laravel Framework. Laravel uses composer to automatically load these packages. You can find the source in your /vendor folder, this is where composer puts the packages.

Use custom folder(class) in controller

I created a new folder in the directory app which is called Services. So the directory of Services is app/Services. I want to use now a file of Services called Connection.php in a Controller app/Http/Controllers but when I try that, I get following error:
Class App\Services\Connection does not exist
I also tried to add the directory and file in my composer.json but this didn't fixed it either.
Controller:
namespace App\Services;
namespace App\Http\Controllers;
use App\Services\Connection;
use Illuminate\Http\Request;
class ExampleController extends Controller
{
protected $conn;
public function __construct(Connection $conn)
{
$this->conn = $conn;
}
Composer.json
"autoload": {
"classmap": [
"database",
"app/Services"
],
"autoload-dev": {
"classmap": [
"tests/TestCase.php",
"app/Services/Connection.php"
]
},
Edit 17.12.2016: (problem not solved yet)
Thanks for all who stick with me so long on this problem! I'm sry, if I gave too less information so I'll sum up few things that I tried.
1 => Deleted the secound namespace App\Services
2 => Added routes(or directory) to my composer.json ( like above )
3 => Used composer updated and composer dump-autoload
4 => Used use App\Services\Connection (the path to my connection class in Services, which I want to use in my ExampleController in App\Http\Controllers\ExampleController)
Connection class:
class Connection
{
//Some guzzle stuff
}
So the ExampleController looks exact as above just without the Services namespace anymore and I get exact the same error. What am I doing wrong?
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Contracts\Auth\Guard;
use App\Http\Controllers\Controller;
use App\Services\Connection;
class ExampleController extends Controller
{
public function __construct(Guard $auth, Connection $conn)
{
$this->auth = $auth;
$this->conn = $conn;
}
}
Please try to use this code.
Presented this solution as a comment but to make it easier for future viewers:
The solution to this is to ensure that proper name spacing is in all files being referenced including the controller and the classes. If the namespace isn't correct it won't be able to access it.
In this case you have to make sure that the namespace for the Connection class was using App\Services as the namespace and that the controller accessed it in the same namespace of App\Services\Connection.
The error is on your namespace declaration. you are declaring two namespaces for the same class!
namespace App\Services;
namespace App\Http\Controllers;
The last one will be used.
Remove the App\Http\Controllers namespace line.
Also remember that you should import the base controller:
use App\Controllers\Controller;
Why?
When you try to use App\Services\ExampleController, composer will look for that class in the autoload paths, but since your namespace is different, it will not be able to load it.

Where are Laravel 5.1 Repositories?

I was going through socialite tutorial which is created by Laravel 5 and I'm using Laravel 5.1 and I saw that there is a file in tutorial like AuthenticateUser.php in repositories folder. But repositories folder doesn't even exist in Laravel 5.1. Where I should create a file AuthenticateUser.php in Laravel 5.1?
Laravel uses composer's autoloading, so it doesn't matter where you store your files, so long as their autoloading mechanism is defined in the composer.json file. Laravel 5 apps start with this defined in their composer.json:
"psr-4": {
"App\\": "app/"
}
So if you created a directory at app/Repositories, you could create a file in it that looked like this:
<?php namespace App\Repositories;
class MyRepository {
public function doSomething() {}
}
Then you can reference it in the rest of your application like this:
<?php namespace App\Http\Controllers;
use App\Repositories\MyRepository;
use Illuminate\Routing\Controller as BaseController;
FooController {
protected $repo;
public function __construct(MyRepository $repo)
{
$this->repo = $repo;
}
public function someAction()
{
return $this->repo->doSomething();
}
}
Composer will load the file for you, so long as you've defined a mechanism for doing so.

Laravel 4 to 5 Models

Hi can anyone clarify this for me. I have a rather large Laravel 4 app using a few models. I would like to upgrade to L5 and would simply like to use the same model calls in the controllers.
e.g.
Course::
\Course:: //if controller in a deeper folder
The course model is in App/Models. I've tried a composer mapping App/Models but to no avail.
Thanks
I don't know about anyone else. But in my installation of Laravel 5, my models are defined directly within the app folder. The app directory is psr-4 namespaced as App.
composer.json
"autoload": {
...
"psr-4": {
"App\\": "app/"
}
}
Models are then defined under the App namespace. e.g.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Course extends Model {
}
So you can either:
1: Use the full path to the model whenever you use it:
\App\Course::all();
2: use your model before using it like you normally would:
namespace Your\Namespace;
use App\Course;
class YourClass {
public function yourFunction()
{
Course::all();
}
}
3: Create a folder called Models, put your models in there and make sure that their namespace reflects the path (And then call the model like in options 1 and 2):
// app/Models/Course.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Course extends Model {
}
e.g.
\App\Models\Course::all();
or
namespace Your\Namespace;
use App\Models\Course;
class YourClass {
public function yourFunction()
{
Course::all();
}
}
That's just how namespaces work. If you specify a class PHP will always search for it relative to the current namespace. Unless you prepend a backslash and use the full path or add an import statement at the beginning of your files:
namespace App\Http\Controllers;
use App\Models\Course;
class ...
Or
\App\Models\Course::all();
I should add that many editors and IDEs are able to automatically resolve and import classes, so with the right tools it's not that cumbersome...

Resources