How to addMedia to another database using laravel-medialibrary - laravel

so i am trying to override laravel-medialibrary so that when i run
$modelA
->addMedia($attachment)
->withCustomProperties(['model_id' => $modelA->id])
->toMediaCollection('attachments_a');
, it adds a record into another specified database eg: database1_mysql
However, it is now currently adding into my current database(database2) instead..
I have created a Media model which has a connection already to another database
namespace App\Domains\Test\Models\Media;
class Media extends Model
{
protected $connection = 'database1_mysql';
}
And the model im relating the media to, i also have overriden the relationship to refer to the media that is connected to another table.
use App\Domains\Test\Models\Media;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
class ModelA extends Model implements HasMedia
{
use InteractsWithMedia;
public function media(): MorphMany
{
return $this->morphMany(Media::class, 'model');
}
}

found a way.
https://spatie.be/docs/laravel-medialibrary/v8/advanced-usage/using-your-own-model#breadcrumb
just swap the model in config

Related

Override vendor model in laravel 6.X

I want to override the model inside of vendor. I tried bellow code. But not working.
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function register()
{
//
}
public function boot()
{
$this->app->bind('VendorName\Models\User', 'App\Models\User');
}
}
Extending model is not an option, as i have to override all controller change model path and write all methods again, its not worth it.
Binding a class in the container like this isn't going to override direct references to the class you're trying to override if the object isn't being resolved using the service container.
So for example, something like $user = new \VendorName\Models\User; isn't going to be affected because it's simply not using the container.
I think the only sensible solution is to refactor your code so you're using a class that extends the base User class.

Accessing involved models in MorphPivot class on boot methods

I have morph many-to-many relation between Tag vs Video and Thread, I'm using a custom model to represent the intermediate table of my relationships, I created a model which extends MorphPivot, So my question is, How to get models on boot method ? For example:
use Illuminate\Database\Eloquent\Relations\MorphPivot;
class TagResource extends MorphPivot
{
protected static function boot()
{
parent::boot();
self::created(function ($model){
dd($model);
});
}
}
I want whenever there is a relationship between my models is created i get them with created event on boot method, But when i dd($model) in the method it just returns the table attributes of TagResource and not the Tag or Video model, Is there a way to get involved models instances ?

Enforce Global Scope Across all models

we are developing an application based on Laravel Spark. as part of this we want to tie resources to a specfic team.
I know that we can add a global scope such as:
<?php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class TeamScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* #param \Illuminate\Database\Eloquent\Builder $builder
* #param \Illuminate\Database\Eloquent\Model $model
* #return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('team_id', '=',Auth()->user()->currentTeam->id );
}
}
but according to the docs we have to add that to each model that we want to restrict like so:
protected static function boot()
{
parent::boot();
static::addGlobalScope(new TeamScope);
}
my issue with this is that it will be possible to create future models and forget to apply this code. Which could give us a security hole?
is there any way to enforce the scope across the board?
I am not sure if there's a way to globally add the Scope.
In my particular application, we have had to add more responsiblities to our Models. So we created a BaseModel class that extends Laravel's Illuminate\Database\Eloquent\Model.
All new Models then extends the BaseModel instead of Laravel's one.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class BaseModel extends Model
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(new TeamScope);
}
}
For example:
<?php
namespace App;
class Attribute extends BaseModel
{
}
You could also have a trait that you can just use to add this scope to your Model. For example:
trait HasTeamScope
{
protected static function boot()
{
parent::boot();
static::addGlobalScope(new TeamScope);
}
}
}
... and then you can easily re-use that in your Model.
For example:
<?php
namespace App;
class Attribute extends BaseModel
{
use HasTeamScope;
}
Now, based on your question, you might also forget to extend the BaseModel in the first instance or add the Trait in the second one whenever you create a new model.
To solve this, you could easily create a new command to produce models that will use your own stub (which extends the BaseModel or adds the trait whenever you create a new model)
You could create your own base model with the desired global scope that future models would extend.
You should create trait with boot function. Trait named BelongsToTeam.
And in all models add only: use BelongsToTeam;

Laravel 5.5 connect your class in the controller

There is a file "MyClasses.php" in the folder "App":
namespace App;
use Illuminate\Database\Eloquent\Model;
class Model1 extends Model {}
class Model2 extends Model {}
How to connect it in the controller using use?
I suggest you to read about PSR-4 standards:
https://www.php-fig.org/psr/psr-4/
MyClasses.php is not a valid name for a model in this case, because a) none of the classes defined inside of it are called MyClasses and b) there are numerous class definitions in this file.
// App/Model1.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Model1 extends Model {
protected $table = 'some_table';
}
// Controller
use App\Http\Controllers\Controller;
use App\Model1;
class SomeController extends Controller
{
public function index()
{
$record = Model1::where('some_field', 1)->get();
}
}
EDIT: to clarify.
Both models should be in their own files, called Model1.php and Model2.php under the App folder. Also, you model names * should * correspond to the table names they are accessing. So if for example Model1 is going to be bound to table user_confirmations you should rename your file and class to UserConfirmations - this would be considered best practice.

Issue in creating REST Service using laravel

We are trying to develop an Android app that required a REST API to show data from web server.
We tried to use Laravel resource to create REST service like below:
Route::resource('list', 'ListController');
namespace App\Http\Controllers;
use mymodel
class ListController extends Controller
{
public function getShow($id)
{
$Jsondata=list($id);
return $JsonData;
}
}
But it's not working as expected need some token key or some other authentication and authorization need to know how to set.
We should utilize the Repository / Gateway design pattern:
For example, when dealing with the User model, first create a User Repository. The only responsibility of the user repository is to communicate with the database (performing CRUD operations). This User Repository extends a common base repository and implements an interface containing all methods we require:
class EloquentUserRepository extends BaseRepository implements UserRepository
{
public function __construct(User $user) {
$this->user = $user;
}
public function all() {
return $this->user->all();
}
public function get($id){}
public function create(array $data){}
public function update(array $data){}
public function delete($id){}
// Any other methods we need go here (getRecent, deleteWhere, etc) }
Then, create a service provider, which binds your user repository interface to your eloquent user repository. Whenever you require the user repository (by resolving it through the IoC container or injecting the dependency in the constructor), Laravel automatically gives you an instance of the Eloquent user repository you just created. This is so that, if you change ORMs to something other than eloquent, you can simply change this service provider and no other changes to your codebase are required:
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider {
public function register() {
$this->app->bind(
'lib\Repositories\UserRepository', // Assuming you used these
'lib\Repositories\EloquentUserRepository' // namespaces
);
}}
Next, create a User Gateway, who's purpose is to talk to any number of repositories and perform any business logic of your application:
use lib\Repositories\UserRepository;
class UserGateway {
protected $userRepository;
public function __construct(UserRepository $userRepository) {
$this->userRepository = $userRepository;
}
public function createUser(array $input)
{
// perform any sort of validation first
return $this->userRepository->create($input);
}}
Finally, create our User web controller. This controller talks to our User Gateway:
class UserController extends BaseController
{
public function __construct(UserGatway $userGateway)
{
$this->userGateway = $userGateway;
}
public function create()
{
$user = $this->userGateway->createUser(Input::all());
}}
By structuring the design of your application in this way, you get several benefits: you achieve a very clear separation of concerns, since your application will be adhering to the Single Responsibility Principle (by separating your business logic from your database logic) . This enables you to perform unit and integration testing in a much easier manner, makes your controllers as slim as possible, as well as allowing you to easily swap out Eloquent for any other database if you desire in the future.
For example, if changing from Eloquent to Mongo, the only things you need to change are the service provider binding as well as creating a MongoUserRepository which implements the UserRepository interface. This is because the repository is the only thing talking to your database - it has no knowledge of anything else. Therefore, the new MongoUserRepository might look something like:
class MongoUserRepository extends BaseRepository implements UserRepository
{
public function __construct(MongoUser $user) {
$this->user = $user;
}
public function all() {
// Retrieve all users from the mongo db
}}
And the service provider will now bind the UserRepository interface to the new MongoUserRepository:
$this->app->bind(
'lib\Repositories\UserRepository',
'lib\Repositories\MongoUserRepository'
);
Throughout all your gateways you have been referencing the UserRepository, so by making this change you're essentially telling Laravel to use the new MongoUserRepository instead of the older Eloquent one. No other changes are required.
Number one is that what is not working? if you mean that the response is not showing then its because your function actually doesn't even seem to be going any where, and number two are you new to Laravel?
Okay if this is what you have:
namespace App\Http\Controllers;
use mymodel;
class ListController extends Controller
{
public function getShow($id)
{
$Jsondata=list($id); return $JsonData;
}
}
Then I can be safe to say a lot of things is wrong.
To my understanding using Route::resource('list', 'ListController'); in your routes file creates show, edit, update and destroy paths, and also expects to see these functions too (I have not proven this to the core though) but thats my understanding.
so you can simply start laravel life by doing having your routes with
Route::get('list', 'ListController#show')
Then change your ListController to something like this:
namespace App\Http\Controllers;
use mymodel;
class ListController extends Controller
{
public function show($id)
{
$jsonData= ['my' => 'json data'];
return $jsonData;
}
}
If this works for you, then cool else so many thing might already be wrong with your setup.
Note: you might need to take your time to learn to use laravel from the documentation page. If API is your interest then try DIngo api. Also try to learn to use markup :)
Hope this helps :)

Resources