I have a:
// administration
app/controller/admin/ProjectsController.php
And I want use too:
// public in website
app/controller/ProjectsController.php
But, in autoload_classmap.php, it's registred like that:
'ProjectsController' => 'app/controller/admin/ProjectsController'
So, If I want one more 'ProjectsController' for public views, how I need to do?
What is better? 2 controllers (admin and public), or one (hybrid).
Thanks.
You should namespace your Admin controllers.
That way it'll match up to PSR and autoloader will treat them differently.
namespace Admin;
At the top of your admin files.
Edit:
It may even be worth namespacing all your controllers and models.
So for your ProjectController in app\controllers you could put
namespace ProjectName
Then for everything in subfolders, e.g. app\controllers\admin
namespace ProjectName\Admin
and so on for other folders, and files.
This'll reduce the likely hood of your code clashing with anything else.
Edit: Edit:
After namespacing classes you'll need to reference classes and functions that are outside your namespace. For example Controller belongs to the global namespace so you put \ at the start of Controller.
The documentation here should help out a lot. PHP Namespaces
Related
I've performed a long-overdue update on a Laravel project from v5.7 to v9 and ran into a Target class does not exist error. I found this guide and used the first method to resolve the error (adding the namespace into the RoutesServiceProvider.php boot function). This resolved that error but now, everything is giving me Class "App\Whatever" not found.
I did notice that models are now stored in a Models directory within the app directory rather than directly in app, so have moved them to Models. I figured that might be breaking my use App\Whatever; lines at the top of my controllers, so I've tried use App\Models\Whatever and also use app\Models\Whatever (since the "a" is lowercase in the directory name) but no effect.
I should note I don't really have a good grasp of namespaces, MVC frameworks etc. so ELI5 etc :-)
Some of my controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Thing;
use App\AnotherThing;
...
public function thing_summary($id) // show the summary view of the thing
{
if(Auth::check()) {
$thing = Thing::find($id);
...
Laravel 7/8/9 sticks with strict namespacing. When you move the models to a new directory, you need to update the namespace in the models themselves (if specified at all) and any file that has a use for the model. If the models move from app/ to app/models, the namespace must be changed to App/Models
I'm developing a package which has controllers in it and I want this package to be compatible with (or useable by) both Laravel and Lumen projects. My problem is Laravel controllers extend Illuminate\Routing\Controller and Lumen controllers extend Laravel\Lumen\Routing\Controller. The controller inside my package can't extend them both.
The only solution I've come up with is to have the controllers inside the package extend App\Http\Controllers\Controller.
But I see some problems:
App\Http\Controllers\Controller should exist; which means it wouldn't work if the App namespace is named differently.
The package is now "aware" that it is being included in something.
Testability: I can't test the controller independently because of the reference to App\Http\Controllers\Controller.
Is there a better way of doing this?
Edit 1
I'm finding other classes which are affected in a similar way. For example, the namespace of the trait Authorizable is Illuminate\Foundation\Auth\Access in Laravel while it is Laravel\Lumen\Auth in Lumen. I am using a model which uses that trait. How do I make my model compatible with both Lumen and Laravel?
Well, you could simply have two different files and classes wrapped in if statements and check for the corresponding classes to extend. So:
LaravelClass.php:
if(class_exists(Illuminate\Routing\Controller:class)){
class LaravelClass extends Illuminate\Routing\Controller {
use YourCodeTrait;
// any more code that is not in your trait
}
}
LumenClass.php
if(class_exists(Laravel\Lumen\Routing\Controller:class)){
class LaravelClass extends Laravel\Lumen\Routing\Controller {
use YourCodeTrait;
// any more code that is not in your trait
}
}
Loading both files will only load one of the classes. In the code above I use a trait to load the contents of your controller, assuming the contents is the same, you could use the same trait and not have to repeat yourself.
trait YourCodeTrait{
// whatever would normally go in your controllers
}
I am trying to organise my app a bit better by putting models and controllers in subdirectories. I thought it didn't matter if they were in subdirectories as long as the namespace is correct, but now that I've moved them I'm getting a class not found error.
I have tried running composer dumpautoload several times, but it's still not working.
Here is my directory structure:
App
Models
Managers
EntryStructure.php
FieldManager.php
Controllers
EntryControllers.php
Since I have made the new directory Managers and moved those two models in there, When I reference the FieldManager class from EntryStructure, I get the not found error.
Code in EntryStructure.php:
namespace Pascall\ICMS\Models;
use Pascall\ICMS\Models\FieldManager;
class EntryStructure
{
function index(){
new FieldManager(); // class not found
}
}
Code in FieldManager.php:
namespace Pascall\ICMS\Models;
class FieldManager {
//
}
Why is it not finding the FieldManager class when it is explicitly referenced in the use statement and they share the same namespace?
Your use should be
use Pascall\ICMS\Models\Managers\FieldManager;
instead
use Pascall\ICMS\Models\FieldManager;
If your Models directory follow the PSR-4 specifications, the namespace in both of your classes should follow the class file path, so it should be:
namespace Pascall\ICMS\Models\Managers;
Then, in EntryStructure class you should use:
use Pascall\ICMS\Models\Managers\FieldManager;
I have ZF2 module, and simultaneously I use Propel genereted models hosted in root-directory/generated-classes. Can I make them share selfsame namespace - like Bookstore or so?
From Zend\Loader\StandardAutoloader I see:
public function registerNamespace($namespace, $directory)
{
$namespace = rtrim($namespace, self::NS_SEPARATOR) . self::NS_SEPARATOR;
$this->namespaces[$namespace] = $this->normalizeDirectory($directory);
return $this;
}
so if I provide two directories in Module.php, the last will prevail.
There is also:
public function setFallbackAutoloader($flag)
{
$this->fallbackAutoloaderFlag = (bool) $flag;
return $this;
}
Can I resort to it and how do I leverage this option? Any other (better) options?
I wouldn't put my models directly in /your-application/root. This will be against ZF2's recommended directory scaffolding. Instead of that, I'd create a /FooModule/src/FooModule/Model directory and put all of my models inside this folder using namespace FooModule\Model namespace definition in model class.
Another detail is; trying to pointing two different directories for same namespace is absolutely bad idea. This will be against PSR-4 Autoloading Standard and lot of open source libraries & frameworks including Zend Framework 2 which heavily depends on this standard.
I would look at the problem from a different angle. Just ask: Why I need to point one of my namespaces to the two different directories?
I think actually you mean Domain Entities by "Propel generated models". If this is correct (i mean Bookstore) is an Entity rather than a Model. You may also want to read this great answer.
So, you can try to create an Entity namespace in your Application (or whatever) ZF2 module and write your Entity classes under a sub-namespace inside that. This is perfectly valid. For example:
Application\src\Entity\Bookstore.php - namespace is Application\Entity
Application\src\Entity\Book.php - namespace is Application\Entity
Application\src\Entity\Author.php - namespace is Application\Entity
Or this is also valid scenario too (Bookstore is a module):
Bookstore\src\Entity\Book.php - namespace is Bookstore\Entity
Bookstore\src\Entity\Author.php - namespace is Bookstore\Entity
In both example scenarios, Book.php and Author.php are your auto-generated domain entities and they shares same namespace while not conflicting ZF2 or PSR-4 autoloading mechanisms.
What I want to do is to use different namespaces in a controller. I have a tree scheme like this:
app/
app/controllers/
app/modules/
app/modules/modulename/
app/modules/modulename/controllers/
app/modules/modulename/controllers/modulecontroller.php
app/modules/modulename/models/
app/modules/modulename/models/modulemodel.php
What I want to do is to call a model from a controller in app/controllers/ folder. Therefore I am supposed to add namespace as follows:
use App\Modules\Facebook\Controllers\Facebook;
The problem is that when I add a namespace and use App::() function at the sametime, I get the following error:
Class 'App\Modules\Modulename\Controllers\App' not found
I think it is looking the App::() function in module folder. How can I solve this problem?
if you use App inside your App\Modules\Facebook\Controllers namespace, it will be interpreted as App\Modules\Facebook\Controllers\Facebook\App class.
since you don't want to have the previous namespace, you use a \ before App like:
\App::()
or put a use statement of top the class like use App;
You probably are creating an unusual namspace scheme. It appears you are namespacing every class from your module differently. You should namespace your code within your module only, like so:
// Adding Onur to the namespace prevents any future namespace collisions.
<?php namespace Onur\Facebook;
After creating your namespace you should add all classes that are outside of your namespace that you want to use as followed.
use Eloquent, Input, Validate, Etc;
This prevents you from adding a \ in front of every class instance, making your code hard maintain and prone to errors. It also gives you a good overview on all the classes you are using in the current class.
if you say
use App\Modules\Facebook\Controllers\Facebook;
then you are supposed to use Facebook instead of App... Or donĀ“t I understand your problem correctly?
if you say
use App\Modules\Facebook\Controllers\Facebook as FacebookController;
the you can use FacebookController in your file
if you need Access to the root App, you need to to root it using a leading \
\App::make()