I'm new to laravel, coming from Codeigntier. I am trying to get to grips with the model/classes/eloquent convention that Laravel uses. I know that I can make a table in my database called, say, "categories". Then I can make a file in my models folder called category.php containing just the following code:
Class Category extends Eloquent { }
which automatically connects with the table name with the plural version of the name ("categories") and gives me access to all the Eloquent commands in my controller like Category::All();
Here's what I don't get: Do I need to make a new model for every table in my database? In that case I will end up with a bunch of files in my models folder with names like resource1.php, resource2.php, etc, each just containing the same code as above (replacing the name of the class).
Can't I just make one model called, say, "database_handler.php" and then just put all these classes into it in the same place?
Yes, you can create a database_handler.php file and do:
<?php
Class Category extends Eloquent { }
Class Post extends Eloquent { }
Class Client extends Eloquent { }
You can do whatever PHP let's you do, and add many classes to a single .php file is something you can do. But this is not a good practice and Laravel is all about developing application using the best ones.
To load this file automatically, you can do one of many things:
1) Add this file to your app/models folder.
2) Add an entry for it on your composer.json:
"autoload": {
"files": [
"app/database_handler.php"
]
},
And then you'll have to
composer dump-autoload -o
3) Create a different folder for it and also add it to composer json autoload section.
You choose, Laravel will let you free to do whatever you want.
Related
I have followed the documentation very closely but something isn't working
https://laravel.com/docs/9.x/eloquent-relationships#one-to-many-polymorphic-relations
I am trying to add permissions into my code which will give a User access to a File or a Folder. I understand this needs a one-to-many polymorphic relationship as each Permission has one permissionable, while each File or Folder might have many permissions.
$table->morphs('permissionable'); in a migration adds the permissionable_type(string) and permissionable_id(integer) columns to the permissions table
The Permission model has been created with the relevant fillable columns and the permissionable method containing a morphTo():
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\File;
class Permission extends Model
{
use HasFactory, SoftDeletes;
protected $fillable = [
'user_id',
'permissionable_type',
'permissionable_id',
'privilege',
];
/**
* Get the parent object (file or folder).
*/
public function permissionable()
{
return $this->morphTo();
}
}
The Folder and File models have both had the following methods added:
public function permissions()
{
return $this->morphMany(Permission::class, 'permissionable');
}
A Permission is going to be created which will share a File with a User
And then the Permission is found and it's permissionable is requested
dd(Permission::find(1)->permissionable);
Except this is where the area happens:
I have tried to follow the documentation religiously and all the answers I see online just say to check namespace or ensure that all Models have an extends Model which I have already done.
Let me know if there is any more information I need to provide, thanks in advance.
i think you just changes model File class name, it's ok.
because this model's name conflict with Facades File class name
Thanks to Noah and Erik for their answers. You both helped me find the solution which was on the following site.
https://laracasts.com/discuss/channels/general-discussion/polymorphic-relations-gives-class-staff-not-found
The types need to include the paths in the database
love the Resources function in Laravel 5.5 which creates at resource prettier for a Model, but I have all my models stored in /App/Models/* instead of directly in the App/*-folder.
This is causing the App/Http/Resources/* not to work.
Results in a "Undefined property: Illuminate\Database\Query\Builder::$map"
This is caused because I stored my Models in a different folder which he can't map to by guessing.
Where and how to define the different placing of the Model?
For what I understand of your problem you have to inject the Model instance in the resource constructor, there is no magical autobinding, i.e.:
use App\Models\User;
use App\Http\Resources\User as UserResource;
Route::get('/user', function () {
return new UserResource(User::find(1));
});
I dont see any problem here, even with namespaced Models.
Not sure of the process you used to move the models to the new Models directory, so check a few things:
Namespace of the models
Each model has:
namespace App\Models;
Check references in these files
app/Http/Controllers/Auth/RegisterController.php
config/auth.php
config/services.php
database/factories/ModelFactory.php
Your Controllers
And change App/ModelExample to App/Models/ModelExample
Update autoload classmap
Add "app/models" to composer.json's classmap autoload section
"autoload": {
"classmap": [
"database",
"app/models"
]
}
Autoload files
Run composer dump-autoload
My apologies if this exists already but my search-fu can not find the answer.
I have a composer package, and want to use my model ONLY IF an existing model doesn't exist (or extend the custom model), but I can't seem to figure out how to specify the "use" command properly inside my composer model. Since I won't know the name of the "app" using the package, I can't extend it.
<?php
namespace MyComposer\Package\Models;
use Illuminate\Database\Eloquent\Model;
class MyPackageModel extends Model
{
If I put it as a config option, I can't use that in the extends i.e class MyPackageModel extends config('custom_model_name')
I had thought I should do the check in the ServiceProvider but I can't seem to find the right code to register the proper model name to use in there.
Thanks.
I've done something similar to this before, I believe. But my approach was slightly different. See if it makes sense:
Create a base class in your own package. This will be the fallback
model which will be used if the "local" package (the one consuming
your package) doesn't have it's own version of it;
Create a config file which states which model will be used. The default is the model inside your own package (i.e. the fallback);
After installing and setting up your package, if a user does nothing they will automatically have your base model available. If they wish to override your base model with a custom local version, they can simply extend your base model and alter the model to be used in their config file.
I've also found that sometimes it's useful for the base model to 1) implement an interface that can be checked in your package's logic without relying on a specific class (which, after all, is meant to be overridden, right?); and 2) have most of it's logic inside a trait which the "local" model can use without ever having to extend your model (crucial if the local model already extends some other class for whatever reason).
How you approach the code would very much depend what you plan to do with that model. Say, for example, you have a supporting class that creates media entries in your database. Here's your packages model:
<?php
namespace Namespace\Package;
class Media
{
//...
}
And here's the default config:
<?php
return [
'model' => \Namespace\Package\Media::class,
];
And here's a sample manipulation, where you actually account for the local app to override your own model:
<?php
namespace Namespace\Package;
class MediaManager
{
protected function getModel()
{
$model = config('package.model');
return new $model;
}
public function createMedia($attributes = [])
{
$media = $this->getModel($attributes);
$media->save();
return $media;
}
}
That is to say, you never reference any Media model literally. You do your manipulations via the MediaManager. Of course the logic is very simplistic, but hopefully it's enough to get the bigger picture.
This question already has answers here:
Troubleshooting referencing a model in a laravel controller
(2 answers)
Closed 6 years ago.
I'm finding the distinction between "Controller" and "Model" in laravel 5.2 to be very blurry.
I use artisan to create a RESTful controller, and in the store method, I try to create a new object.
// store in the database
$car = new App\Models\CarModel;
Then I get the error as follows:
Class 'carfreak\Http\Controllers\App\Models\CarModel' not found
So it all seems to come down to the namespace of the controller, but I don't understand it.
The name space describes the controller, right?
So why is my reference the model, being built on the controllers path? It shouldn't have anything to do with it... right?
EDIT: After trying various suggestions, I've concluded there are three things to look at:
Each class has a namespace set, correctly describing the folder where the class is located
In the controller, have the statement "Use app\models\CarModel"
refer to the model in the controller.
Each seems to be correct, but I still get the error that it cannot find the model
This is a namespace problem in php.
You just use like this.
$car = new \App\Models\CarModel;
or
use App\Models\CarModel;
....
class {
$car = new CarModel;
}
First of all check name space in Model file , Define name space in model file
namespace App\Http\Models;
And then use
use App\Http\Models\CarModel;
Well, here it is. I solved it by asking myself this question: If I'm having so much trouble namespacing, referencing and organising my models, then maybe I can get artisan to do it for me.
The post that got me thinking differently was Mansoor Akhtar's advice here: How do I instruct artisan to save model to specific directory?
Get artisan to make the model in the right place first time.
php artisan make:model Models/CarModel
In the Controller, reference the model correctly
use name-of-app\Models\CarModel;
There may or may not be cache flushing involved in my problem. I was eventially restarting my XAMPP after every change to ensure no caching was involved. I also tried
php artisan cache:clear
You'll need to add a use statement to the top of your class.
Try:
use carfreak\Models\CarModel;
class ...
This assumes that your model is in the carfreak\Models namespace, and in a Models folder within your App / carfreak folder, otherwise you'll just need use carfreak\CarModel;.
I believe you have just ran the artisan command to create the model and you didn't move the CarModel file to Models folder. (Correct me if I'm wrong)
So in your controller add this before class declaration:
use carfreak\CarModel;
Then anywhere in your controller you can access the model like this:
$car = new CarModel;
I need to create own class with methods, that I want to call from diverse controllers.
What it should be: Library, Provider or Helper in Laravel?
1: Create folder app/Helpers
2: In app/Providers create new provider file HelperServiceProvider.php
3: In this file register all helpers classes you need
$this->app->bind('dateHelper', function()
{
return new \App\Helpers\DateHelper;
});
... etc
4: In config/app.php add this new provider
'App\Providers\HelperServiceProvider',
5: Then you need to create Facade to be available to use this helper in view. You find the info about how to create Facade on official laravel.com site
About the providers, you can read the doc
Source: Laravel Forums
You can do this in many ways
Static way
Create a folder your wish Utils or Helpers or Libraries.
Create a Class (ex: Helper Class)
Added static methods here (ex: public static common()).
Added namespace to the call.
Use the name space and call the static function using(Helper::common)
Normal Class
Create class with name space.
Inject the Dependency of that class and use all function inside.
You can follow the simple steps below
Step 1
Create new helper file in app/Helpers directory
Ex. I have created the DemoHelper.php in directory app/Helpers/DemoHelper.php
Step 2
Add the entry of created Helper(DemoHelper.php) to composer.json file in autoload section
"autoload": {
"files": [
"app/Helpers/Helper.php",
"app/Helpers/DemoHelper.php"
]
},
Step 3
Finaly, composer dump-autoload hit this command in terminal.