One To Many Polymorphic relationship - Call to undefined method getConnectionName() - laravel

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

Related

Laravel Authentication using different model rather than the user model

All about laravel authentication is based on users, but I have deleted the user model and replaced that with a company model, so, basically, I want my users (laravel authentication users) to be companies.
Laravel doesn't like this, it gives me
Type error: Argument 1 passed to Illuminate\Auth\SessionGuard::login() must be an instance of Illuminate\Contracts\Auth\Authenticatable, instance of App\company given, called in /home/dhiraj1site/Desktop/Documents/blog/vendor/laravel/framework/src/Illuminate/Auth/AuthManager.p
This error, and if I import authenticable class as suggested in similar questions. Laravel hates this and gives me a blank page.
I have companies model and a companies table, I want the users to sign up as companies, and login as companies. How should I go about this, I am really confused and stuck on this stage, please help me understand how authentication works (I have read authentication documentation several times) and how should I change 'Users' to 'companies'.
There are a couple of ways to skin this cat zuif. The 'Laravel' way would be to edit the settings in app/config/auth.php
In that file you'll need to change the line: 'model' => 'App\User' to 'model' => 'App\Company'.
The 'gotcha' with Laravel is that you must remember to implement the right interfaces in your new 'user' class, Company:
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Company extends \Eloquent implements UserInterface, RemindableInterface
{
...
}
Or for newer versions of Laravel, its' just one interface:
use Illuminate\Foundation\Auth\User as Authenticatable;
class Company extends Authenticatable
I've done this before and it worked well for me. You could also get creative with extending the User class, but I think above is what you are hunting for.
HTH

Codeigniter Model extends CI_MODEL

I have a problem,
I want to create 2 different model extends CI_Model in core folder
for example
class MY_FirsModel extends CI_Model {
}
class MY_SecondModel extends CI_Model {
}
is it posible when using codeigniter
thank you
According to Codeigniter's Documentation, when extending a core class, you need to give the same name to your class, only changing CI_ by MY_.
When the loader class is fetching all core classes it looks for specific matching names such as Model, Controller, Exceptions and so on. It starts looking by the application/core folder, with prefixes MY_ and then goes to system/core if a extended class was not found.
If you need to maintain the names MY_FirsModel and MY_SecondModel, you can create these models in the application/libraries folder and the require these files in the classes you will use them.
require_once APPPATH.'libraries/MY_FirsModel.php';
and
require_once APPPATH.'libraries/MY_SecondModel.php';
it is possible to have it like that way. This will going to work. I read it once on CI forum (I don't remember the exact link as it's been long time) that some admins like to use this kind of style but many people are in favor of separating them into 2 different file

Composer package - use custom model if exists

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.

How do I register a model observer in a service provider?

The Laravel documentation states that you can register a model server in a service provider, however it says nothing in the way of how that is done that I have seen. All of my searches through google have turned up nothing useful. I attempted to write some code like this:
namespace name;
use /path/to/ServiceProvider;
use path/to/UserObserver;
class UserObserverServiceProvider extends ServiceProvider{
public function boot(){
User::observe(new UserObserver);
}
public function register{}
}
}
which was the only suggestion that implied it should work I could find in my searches, however, it says the User class is not found when i attempt to run it. I tried to put a path to the User model, but it doesn't recognize the models directory as a path to anything...
hoping someone can help clear this up for me.
figured out that the names of the model classes were all that was needed to specify the path in the use command, it works now, I just had to specify
use User;

Laravel model containing multiple classes

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.

Resources