Laravel How to reference model outside of package? - php

I'm using laravel 8 with a custom package. I have models in this package and outside this package, for example User (from default auth) and thread model (in a package). I've got thread-user relationship belongsToMany for "like"-system that I need to have working. here is a piece of code, of thread model.
namespace LaraChan\Core\Models;
use Illuminate\Database\Eloquent\Model;
use LaraChan\Core\Traits\Renderable;
use LaraChan\Core\Traits\Uuids;
use LaraChan\Core\Traits\Image;
use App\Models\User;
class Thread extends Model
{
use Uuids, Image, Renderable;
protected $fillable = [
'id',
'board',
'title',
'image',
'body',
'user_author'
];
public function userlikes(){
return $this->belongsToMany(User::class, 'threads_liked', 'thread_id', 'user_id');
}
}
it does not seem to me that relationship is working. I've used Larachan package. https://github.com/anthonybudd/LaraChan

In order to reference a model outside of a package in Laravel, you can use the full namespace of the model.
For example, if your model is located in the App\Models namespace, you can reference it like this:
$model = App\Models\MyModel::find(1);

Related

Laravel / Mongdb - DB::collection() is not working

I am following this Laravel/Mongodb package: https://github.com/jenssegers/. Here if you go to this section https://github.com/jenssegers/laravel-mongodb#basic-usage-2 you can see that they are using DB::collection() method and passed the collection name to that.
Now, in my controller, I am trying to do this:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\Import;
use App\Models\Projects;
use Jenssegers\Mongodb\Collection;
use Jenssegers\Mongodb\Query\Builder;
class ImportController extends Controller
{
public function get_all_products() {
// Predefined key
$predefined_keys = [ 'image_link', 'title', 'price', 'brand', 'link' ];
// Get all the products
//$get_products = Import::paginate(10);
$get_products = DB::collection('products_1')->get();
return response()->json($get_products, 200);
}
}
but I don't get any result. Can you tell me what I am missing here?
My goal is to set the collectioin name directly in this controller not in Model.
Update:.
Here is my Import Mode:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Jenssegers\Mongodb\Eloquent\Model;
class Import extends Model
{
protected $connection = 'mongodb';
protected $collection = 'products_46';
// protected $table = 'projects';
}
Something is wrong with how you have configured this project.
From the documentation that you linked:
When using MongoDB connections, Laravel will automatically provide you with the corresponding MongoDB objects.
Yet in the comments you report that DB::collection('products_1')->get(); results in:
message": "Method Illuminate\\Database\\MySqlConnection::collection does not exist."
This error message is referencing MySQL rather than MongoDB. It seems you are using MySQL for other portions of your application per this question.
In any case, I think the answer is to be sure to load the packages appropriately (and perhaps also to disambiguate between namespaces if DB is separately defined in Illuminate\Support\Facades and is in scope for this portion of the code).

Laravel - Retrieving associated model using all function

I am writing a program that has a many-to-many relationship between clients and concerns. I have configured my models to use the belongsToMany() function as outlined in the Laravel documents. Please see the code for the two models below:
Client.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Client extends Model
{
use HasFactory;
protected $fillable = [
'first_name',
'last_name',
'email',
'preferred_day',
'preferred_time',
'presenting_concerns',
'is_active',
];
public function invoices() {
return $this->hasMany(Invoice::class);
}
public function concerns() {
return $this->belongsToMany(Concern::class);
}
}
Concern.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Concern extends Model
{
use HasFactory;
protected $guarded = [
'concern',
];
public function clients() {
return $this->belongsToMany(Client::class);
}
}
I was able to create some sample data using factories and php artisan tinker. I am now in the process of building out my views. However when I call
$clients = Client::all()->concerns()
in my controller, I get a concerns does not exist error message. I did a dd on just Clients::all(), and I don't see the concerns attached to the returned model. From my understanding, with just the call to all() function, I just return the client model. However, I was hoping by calling the concerns() function, I would be able to return the concerns as well. Is it possible to retrieve all clients and their concerns in one call?
Please note that I can use Client::find(2)->concerns() but that does not help me in my case because that only returns the concerns for client with ID 2.
Yes you can do this. You need to eager load your relation of interest.
If you do the following, you will load the relation and will be able to see it when doing dd().
$clients = Client::with('concerns')->get();

spatie/laravel-medialibrary change primary key

I'm using the package spatie/laravel-medialibrary and I want to change the primaryKey on their modal called Media, without editing the package src file.
In my project, I'm using uuids as primary keys for all my models, so naturally, I want to do the same thing for the Media.php model offered by this package.
I already changed the migration to reflect that, by removing the line $table->bigInteger('id') and changing the line $table->uuid('uuid')->nullable(); to table->uuid('uuid')->unique()->primary();
However, now I also want to let the model know I'm using a different key, by setting up protected $primaryKey = 'uuid'; and protected $keyType = 'string'; but I can't find a way to do this outside the packages src file for the Media.php model
Basically, what I want to end up doing is just implementing the HasMedia interface and using the InteractsWithMedia trait on my Profile model, like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class Profile extends Model implements HasMedia
{
use InteractsWithMedia;
}
Any suggestions on how to achieve this?
Thanks.
Spatie's medialibrary package gives you the option to use your own media model, as described in their docs.
Just create your custom model and extend the library's Media model. You can then modify that csutom model to fit your needs.
use Spatie\MediaLibrary\MediaCollections\Models\Media as BaseMedia;
class Media extends BaseMedia
{
protected $primaryKey = 'uuid';
protected $keyType = 'string';
public $incrementing = false;
// ...
}
Remember to set the media_model key in config/media-library.php to your model's FQCN.
'media_model' => App\YourMediaModel::class,

How can I mock a different model to retrieve a polymorphic relationship?

I have 3 data models, one of which extends the other:
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Opinion extends Model
{
public function reactions()
{
return $this->morphMany('App\Models\Reaction', 'reactable');
}
...
}
namespace App\Models\Activity;
use App\Models\Opinion;
class ActivityOpinion extends Opinion
{
...
}
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Reaction extends Model
{
public function reactable()
{
return $this->morphTo();
}
...
}
The App\Models\Opinion model has a polymorphic relationship with the App\Models\Reaction model. I can retrieve all of the App\Models\Opinion reactions no problem, so I know the relationship works great.
My question is, how can I retrieve the same set of reactions from the App\Models\Activity\ActivityOpinion model? Because right now, it is looking for App\Models\Activity\ActivityOpinion as the relationship but I need it to look for App\Models\Opinion. Is it possible to mock another model in a polymorphic relationship?
This is because in a Polymorphic Relationship in the stored data (if leaved as default) the relationship type gets the class namespace (sort of) to specify wich model needs to be returned. That's why when you try to access to your reactions() relationship from ActivityOpinion it will look up for the App\ActivityOpinion value in the reactable_type.
You can customize the morph class to search in the model addind this:
Opinion.php
protected $morphClass = 'reaction';
This should be enough, if not, add it also in the ActivityOpinion model.
Note
This could breake some things when trying to search results using Eloquent. Check this other answer in order to address this possible inconviniance.
Update
I've just found out that you could do all this even easier with MorphMap. From the docs:
Custom Polymorphic Types
By default, Laravel will use the fully qualified class name to store
the type of the related model. For instance, given the one-to-many
example above where a Comment may belong to a Post or a Video,
the default commentable_type would be either App\Post or
App\Video, respectively. However, you may wish to decouple your
database from your application's internal structure. In that case, you
may define a "morph map" to instruct Eloquent to use a custom name for
each model instead of the class name:
use Illuminate\Database\Eloquent\Relations\Relation;
Relation::morphMap([
'posts' => 'App\Post',
'videos' => 'App\Video',
]);
You may register the morphMap in the boot function of your
AppServiceProvider or create a separate service provider if you
wish.

How to overwrite an vendor class

How can i overwrite a vendor class?
I'm using Laravel Spark and i wanna have Uuid for all models. Due Spark manage some models inside the package and i don't see a possibility to use my own model for Notifications etc. i would like to overwrite the base Model class from Illuminate\Database\Eloquent\Model, so i could include there my uuid trait.
I tried over the ServiceProvider with:
public function boot()
{
//
$this->app->bind('Illuminate\Database\Eloquent\Model', 'App\Models\Model');
}
But it didn't worked.
Is it possible or maybe exist a better way?
Thanks for any help.
Create a custom model class which will extend the eloquent model.
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class CustomModel extends Model {
// Your implementation
}
And then rest of the models you extend your custom model.
class Test extends CustomModel {
}

Categories