I'm trying to access a Model in Laravel app through its Class Name, but I'm getting the following error:
Class 'Asset' not found
Though, I've already imported this Model.
Here's my code:
<?php
namespace App\Services;
use App\Models\Asset as Asset;
use App\Models\Benefit\BenefitGroup as BenefitGroup;
use App\Models\Benefit\EmployeeDependent as EmployeeDependent;
use App\Models\Country as Country;
use App\Models\Employee\Education as Education;
use App\Models\Employee\EducationType as EducationType;
use App\Models\Employee\Employee as Employee;
use App\Models\Employee\EmployeeVisa as EmployeeVisa;
use App\Models\Employee\VisaType as VisaType;
use App\Models\Note as Note;
use App\Models\PaidTimeOff\Policy as Policy;
use App\Models\PaidTimeOff\TimeOffType as TimeOffType;
use Illuminate\Database\Eloquent\Model;
class ACLService
{
public function getDefaultPermissions($roleType)
{
//Array to append all default permissions in single array without extra indexing
$permissions=[];
$models=['Asset', 'Employee', 'Education', 'EducationType', 'VisaType', 'EmployeeVisa', 'BenefitGroup', 'EmployeeDependent',
'Policy', 'TimeOffType','Country', 'Note'];
foreach ($models as $model) {
$permissions=$this->getModelPermissions($model, $roleType, $permissions);
}
}
public function getModelPermissions($model, $roleType, $currentPermissions)
{
$data=$model::getDefaultPermissionsForThisModel($roleType, $currentPermissions);
return $data;
}
}
If I pass
App\Models\Asset
instead of
Asset
then the error gets resolved but I don't want to pass data in this format because it'll increase the work amount if we ever get to change (in future) the Model's location in the project.
This is an incomplete project and we'll definitely change the models' location.
I'm looking for a cleaner solution.
Use the ::class constant to get the correctly namespaced class name. This will also make it easier if you ever move the files. Smart IDE's will be able to detect the reference.
$models=[
Asset::class,
Employee::class,
...
];
This presumes all classes have been imported at the top of your PHP file.
Related
I am using Laravel 5.8 and I'm attempting to modify a package class from the Vendor directory. To acheive this, I have created a new class which extends the Vendor class, and I can replace the named functions within it- all working great.
However, the original class 'uses' a class, which I have mimicked in my new class, as follows:
use VendorName\PackageName\OriginalController
// use VendorName\PackageName\SomeClass as StoreRequest; How can I replace this...
use App\Http\Requests\NewRequestClass as StoreRequest; // ... with this..? (not working)
class NewController extends OriginalController {
private function somefunction(StoreRequest $request){ // This doesn't work; it is still using the StoreReqest defined in OriginalController
// ...
}
}
See comments- Is it possible to override this?
Its generally not possible modify/delete class or function. Not without extensions like Classkit. But i am not really a fan of this type of code. But you can Check these questions, which might help:
Redefining PHP class functions on the fly?
Deleting entire PHP Class
Redefining PHP function?
i want to know the difference between
use User;
and
/User
in laravel.
In my project i see in a controller say UserController it does this
It adds
use User;
at the top of the controller and in function it uses
User::find($id);
to get query results.
And some other Controller say CompanyController it does not use
use User;
However it does this
/User::find($id);
and gets the same result.
I am confused with its usage. Which should i follow, what does each type do, can ayone please explain.
You should use use User; in combination with User::find($id);
When you have the slash in front of it you basically combine the 2 above into one.
in depth:
The User class (according to your example) appears to have no namespace, yet the file you use it in has one.
In other words, the User class is defined in the root namespace.
Normally you can use classes from the root namespace without use or /, but not when the file you use it in has a namespace.
So you will have to specify the namespace of the object you are trying to use, either with use User; or /User::
While both act identical, most developers opt to use the use variant.
Both have same behavior but different to use.
Use User;
User::all();
is basically a reference to that model class that can be used in any class to get its static methods.
/user::all();
doesn't need to call the reference, this access the model directly so both are basically same.
IN your case you are making a reference to that model class
use User;
User::find(2);
it will call model to find the matching user;
where in Company Controller you didn't use any reference to model. you're accessing that model by just '/'. laravel provides this just for ease.
So Laravel saves it's own session files when someone accesses the website in the /storage/framework/sessions folder. Each of these session file's names are a randomly generated alpha numeric unique name. But, I'd like to somehow rename the files and give my own custom name for it. I've got two options for that.
Change the file name manually once the session file is created (by a create, copy, replace)
Find the function which randomly generates the alphanumeric name and change it with my own way of setting a unique name to each file (this method might come with less complications)
My main end goal is to rename each user's session file to their own userid that's stored in my db. So the names are still unique, the only difference is that I can search through the files easier than if they had random alphanumeric names.
So if anyone knows how I could do any of the above methods or if you can think of a better way to achieve the same, it'd be great. Any help is greatly appreciated!
EDIT: Decided to update here with what I had decided to do finally. I decided not to use the built in session files generated by Laravel and realized it's much easier to make my own file and just have each client access it instead. Thanks to all!
Laravel has several Manager classes that manage the creation of
driver-based components. These include the cache, session,
authentication, and queue components. The manager class is responsible
for creating a particular driver implementation based on the
application's configuration. For example, the SessionManager class can
create File, Database, Cookie and various other implementations of
session drivers.
Each of these managers includes an extend method which may be used to
easily inject new driver resolution functionality into the manager.
To extending Laravel with a custom session driver, we will use the
extend method to register our custom code:
You should place your session extension code in the boot method of your AppServiceProvider.
Implement SessionHandlerInterface
app/Providers/AppServiceProvider.php
<?php
namespace App\Providers;
use Session;
use Illuminate\Support\ServiceProvider;
use App\Handlers\MyFileHandler;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Session::extend('file', function($app)
{
return new MyFileHandler();
});
}
}
Note that our custom session driver should implement the SessionHandlerInterface. This interface contains just a few simple methods we need to implement.
app/Handlers/MyFileHandler.php
<?php
namespace App\Handlers;
use SessionHandlerInterface;
class MyFileHandler implements SessionHandlerInterface {
public function open($savePath, $sessionName) {}
public function close() {}
public function read($sessionId) {}
public function write($sessionId, $data) {}
public function destroy($sessionId) {}
public function gc($lifetime) {}
}
Or you can extend MyFileHandler from FileSessionHandler and override relevant methods.
Extend FileSessionHandler
app/Providers/AppServiceProvider.php
<?php
namespace App\Providers;
use Session;
use Illuminate\Support\ServiceProvider;
use Illuminate\Session\FileSessionHandler;
use App\Handlers\MyFileHandler;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Session::extend('file', function($app)
{
$path = $app['config']['session.files'];
return new MyFileHandler($app['files'], $path);
});
}
}
app/Handlers/MyFileHandler.php
<?php
namespace App\Handlers;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Session\FileSessionHandler;
class MyFileHandler extends FileSessionHandler
{
public function __construct(Filesystem $files, $path)
{
parent::__construct($files, $path);
}
}
You can find more in Session section of Extending the framework document.
https://laravel.com/docs/5.0/extending#session
If your final goal is searching on session file names; you don't need to change them.
You can save session file names in a database table ( or another file your choice). You can use this link to get file names.
One column -> store session file names
other columns -> store another informations that you want
In this way you can search and find faster files with using SQL.
use middleware for the request
\Illuminate\Session\Middleware\StartSession::class
Route::group(['middleware' => [\Illuminate\Session\Middleware\StartSession::class]], function () {
});
sorry if it is a noob question, but I'm trying to learn laravel on laracast and can't solve this by my own.
there is a store function on my ArticlesController like this:
public function store(ArticleRequest $request)
{
$article = new Article($request->all());
Auth::user()->articles()->save($article);
return redirect('articles');
}
and it returns a blank page, making clear that is some error, but if I change to
\Auth::user()->articles()->save($article);
it works as expected, saving the article with the user_id field.
I tried import with use App\Http\Controllers\Auth\AuthController; but I think this is not the way.
*obs: Laravel 5.0
In modern PHP, if you see the following at the top of a file
namespace App\Foo\Bar;
it means all the code inside that file in part of the App\Foo\Bar namespace. If you try to use a namespaceless class inside this file
$object = new Auth;
PHP will assume you want to use the class. In other words, it's the same as saying
$object = \App\Foo\Bar\Auth;
When you say
\Auth
you're telling PHP "use the global, top level namespace class named Auth.
This is a perfectly valid use of PHP, by the way. However, if you don't like using the global \ -- you can import the \Auth class into your PHP file (sometimes referred to as a "module" in other languages") by using the use statement.
namespace App\Foo\Bar;
//pull in the global class `Auth`
use Auth;
//...
$foo = new Auth;
Good day!
The more I read, the more I get confused about this. What is the difference between a Facade and Aliases?
I have this Class:
/app/libraries/Project/Data.php
namespace PJ;
class Data {
// It is much like a data container, with static methods and properties for saving info
}
And the corresponding facade, so I can access by using just PJD:: .
According to some webpage around:
... Laravel Facades are proxies. They wrap around and call functions
on the underlying true implementation of the code. Further, in the
context of a Laravel application, these Facades are accessed by
assigning them to aliases. This use of the Dependency Injection
container allow you to reference something like
Illuminate\Support\Facades\Filesystem by simply calling File.
(http://ryantablada.com/post/proxies-service-locators-alias-facades-and-war)
But, I've also found and successfully tested that adding something like:
__app/config/app.php__
'aliases' => array(
//....,
'PJD' => 'PJ\Data',
),
I can also access my class the same way.
So, what's the difference?
Thanks
EDIT #01
I have created a class named Data in /app/libraries/Project/Data.php
namespace PJ;
class Data {
// It is much like a data container, with static methods and properties for saving info
}
I have a Facade Class for this Class Data /app/libraries/Project/DataFacade.php
use Illuminate\Support\Facades\Facade;
class PJD extends Facade {
protected static function getFacadeAccessor() {
return 'PJData';
}
}
And I have a Service Provider for them: /app/libraries/Project/DataServiceProvider.php
use Illuminate\Support\ServiceProvider;
class DataServiceProvider extends ServiceProvider {
public function register() {
$this->app->singleton('PJData', function() {
return new PJ\Data;
});
}
}
I also have added to /app/config/app.php:
'providers' => array(
// ....
'DataServiceProvider',
),
and in composer.json I've added a psr-4 line to direct PJ namespace to /app/libraries/Project
"psr-4": {
"PJ\\": "app/libraries/Project"
},
By doing all this, I can access my class from anywhere in the project just by PJD:: instead of PJ\Data::.
However, I've also noticed that just by adding to /app/config/app.php
'aliases' => array(
//....,
'PJD' => 'PJ\Data',
),
I get exactly the same result without all that facades and ServiceProviders. So, what's the point of one or another?
Thanks, and sorry for the large post.
Facade and Alias are two totally different concepts.
you can not access PJ\Data\ by PJD:: unless you have setup alias in the service provider while binding.
If you are accessing it, without defining it in config/app.php, then you have set it up in the service provider file itself.
Definition of alias,
used to indicate that a named person is also known or more familiar under another specified name.
It simply means you are giving a different name to the class so that it will be easier to call.
e.g.
if you have a class like this: Foo\Bar\AVeryLongNamespaceClassName\Data, you can just give an alias, (e.g. PJD) and access its methods and properties by this alias.
Note:
Unit testing is an important aspect of why facades work the way that they do. In fact, testability is the primary reason for facades to even exist.