How to Declare a Different Database Connection in laravel Controller - laravel

I have a Controller and I need to set the Database for my Query Builder,
all is working but when I create new function I need to redeclare a connection,
What I need is to declare the connection so that the whole controller will be connecting with that database.
class CompanyInformationController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function firstFunction()
{
$connection = DB::connection('fdis_1');
return $connection->getDatabaseName();
}
public function secondFunction()
{
// This is redundant
$connection = DB::connection('fdis_1');
return $connection->getDatabaseName();
}
}

in a class on controller
private $connection;
public function __construct()
{
$this->connection = DB::connection('fdis_1');
}
now use into your method like
$this->connection->getDatabaseName();

Related

PhpStorm 2022.2.2 Laravel Model Relationships and Attributes recognised as magic methods

How can I declare my model relationships and custom attributes properly so that they will be available from auto-completion and have the warning "property accessed via magic method" disappear?
I have nothing above my Model class and I've tried a few examples but none seems to work. i.e #method, #param or I just can't figure out the proper syntax for it.
quantity_remaining is a custom attribute for my Model.
I have it like this ATM:
class MyModel extends Model
{
/**
* #return HasOne
*/
public function packages(): HasOne{
return $this->hasOne(Package::class, 'related_id', 'related_id');
}
public function getQuantityRemainingAttribute(): Int{
//more codes here but not needed for this example
return 1;
}
}
You might want to define properties in the class doc block. I renamed the packages relationship to package, because it is a hasOne relationship.
/**
* #property Package $packages
* #property int quantity_remaining
*/
class MyModel extends Model
{
public function package(): HasOne{
return $this->hasOne(Package::class, 'related_id', 'related_id');
}
public function getQuantityRemainingAttribute(): Int{
return 1;
}
}
You will need to define fields in model class like:
public mixed $name;
public mixed $surname;
public mixed $email;
public mixed $password;
while your fillables are:
protected $fillables = ['name', 'surname', 'email', 'password'];

Can not get Request data in custom service?

I have custom service:
<?php
namespace App\Library\Services;
use Illuminate\Http\Request;
class RegisterCustomerService
{
private $request;
public function constructor(Request $request)
{
$this->request = $request;
}
public function register($role)
{
dd($this->request);
}
}
Why I can not get dd($this->request); when I do POST request:
$customer = $registerCustomerService->register('customer');
My service provider is:
class RegisterCustomerServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* #return void
*/
public function register(Request $request)
{
$this->app->bind('App\Library\Services\RegisterCustomerService', function ($app) {
return new RegisterCustomerService($request);
});
}
/**
* Bootstrap services.
*
* #return void
*/
public function boot()
{
//
}
}
You don't need to bind the instance in the container because Laravel can automatically resolve the namespace and the class dependencies if you resolve an object through the container.
You can the remove the binding from the service provider and use:
$customer = app('App\\Library\\Services\\RegisterCustomerService')->register('customer');
In this way the container will resolve the Register customer service and will create that with all the needed dependencies (the request object in your example).

Model event is not triggered on laravel

I have a class that inherits a base class and uses a trait ... I will put the code below ..
The base class is using basically to do a validation before the rescue, using for this the saving event in the boot.
The trait is to tell the class to use uuid in the id attribute .. this trait uses the creating event of the boot.
In the class itself, the boot saving event is used to check if an active record exists.
In this code the trait creating event is not being triggered ... I can not do a save because uuid is not generated ... if I take the boot method in the final class the creating event is executed ...
something I'm not seeing ... does anybody have any idea what may be happening?
MAIN CLASS
class AcademicYear extends BaseModel
{
use UseUuid;
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::saving(function($model)
{
if($model->attributes['disable'] == false){
$model->searchActiveRecord();
}
});
}
public function searchActiveRecord(){
if ($this::where('disable', false)->count() >= 1){
throw new \App\Exceptions\OperationNotAllowed('operation not allowed', 'there is an active record', '422');
}
return true;
}
}
BASE MODEL
class BaseModel extends Model
{
/**
* If the model will be validated in saving
*
* #var bool
*/
protected static $validate = true;
/**
* Rules that will be used to validate the model
*
* #var array
*/
protected $validationRules = [];
/**
* Create a new base model instance.
*
* #param array $attributes
* #return void
*/
public function __construct($attributes = [])
{
parent::__construct($attributes);
}
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::saving(function($model)
{
if ($model::$validate) {
$model->validate();
}
});
}
/**
* Execute validation of model attributes.
*
* #return void
*/
public function validate()
{
$validator = Validator::make($this->attributesToArray(), $this->validationRules);
if($validator->fails()) {
throw new \App\Exceptions\OperationNotAllowed('validation failed', $validator->messages(), '422');
}
return true;
}
}
TRAIT
trait UseUuid
{
/**
* The "booting" method of the model.
*
* #return void
*/
protected static function boot()
{
parent::boot();
static::creating(function ($model)
{
$model->incrementing = false;
$model->keyType = 'string';
$model->{$model->getKeyName()} = Str::uuid()->toString();
});
static::retrieved(function ($model)
{
$model->incrementing = false;
});
}
}
Your model's boot method is conflicting with the trait's boot method, because they have the same name.
From the PHP.net manual on Traits:
An inherited member from a base class is overridden by a member inserted by a Trait. The precedence order is that members from the current class override Trait methods, which in turn override inherited methods.
Current class: AcademicYear
Trait: UseUuid
Inherited class: BaseModel
If you want to use a boot method on an individual model, you'll have to alias the trait's method to something different:
class AcademicYear extends BaseModel
{
use UseUuid {
boot as uuidBoot;
}
// ...
protected static function boot()
{
static::uuidBoot();
// Your model-specific boot code here.
}
}
Be careful with where you place parent::boot(). If you call parent::boot() in both your trait and your model, BaseModel::boot() will be called more than once.

How can I create a controller constructor in Laravel that takes in two concrete implementations of the same interface?

Background
Note: this is using Laravel 5.3, Please don't judge.
We are trying to use dependency injection with our laravel controllers and push as much business logic into repos that are injected to controllers upon the controller instantiation.
We already have this functioning example:
class AcmeController extends Controller
{
protected $repository;
public function __construct(AcmeInterface $repository)
{
$this->repository = $repository;
}
}
inside app/Providers/RepositoryServiceProvider.php we do the binding:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->bind(\App\Repositories\Contracts\AcmeInterface::class, \App\Repositories\OpCity\AcmeRepo::class);
}
}
and then the AcmeRepo naturally implements the AcmeInterface:
class AcmeRepo implements AcmeInterface
Question
right now we have a case where some of the data of the same model is persisted in a memory type storage (redis) and the rest is persisted in relational db storage (psql). We would like to have two separate repos where each repo is specific to its storage type, ie RedisAcmeRepo and SqlAcmeRepo
How is it possible to do this in the AcmeController constructor?
public function __construct(AcmeInterface $sqlRepo, AcmeInterface $redisRepo)
{
$this->sqlRepo = $sqlRepo;
$this->redisRepo = $redisRepo;
}
For example you may do this:
$this->app->bind(AcmeController::class, function ($app) {
return new AcmeController($app->make(sqlRepo::class), $app->make(redisRepo::class));
});
Or this:
$this->app->when(AcmeController::class)
->needs('$sqlRepo')
->give($app->make(sqlRepo::class));
$this->app->when(AcmeController::class)
->needs('$redisRepo')
->give($app->make(redisRepo::class));
based on the answers above I came up with this solution, that kind of uses the composite pattern as well (I changed the name of the repos from Acme to ShopperLogs):
<?php
interface ShopperLogInterface
{
public function getLogs($from, $to, $shopper);
}
class ShopperLogsController extends Controller
{
/**
* service
*
* #var \App\Repositories\Contracts\ShopperLogInterface
* #access protected
*/
protected $manager;
public function __construct(ShopperLogInterface $manager)
{
$this->manager = $manager;
}
}
class ShopperLogManager implements ShopperLogInterface
{
protected $sqlRepo;
protected $redisRepo;
public function __construct(ShopperLogInterface $sqlRepo, ShopperLogInterface $redisRepo)
{
$this->sqlRepo = $sqlRepo;
$this->redisRepo = $redisRepo;
}
public function getLogs($from, $to, $shopper)
{
$todayRange = //get the today part of from -- to
/**
* array of ShopperLogs
*/
$todaysLogs;
if ($todayRange) {
$this->redisRepo->getLogs($todayRange->start, $todayRange->finish, $shopper);
}
$legacyRange = //get the part of from -- to that excludes today's range
/**
* array of ShopperLogs
*/
$legacyLogs;
if ($legacyLogs) {
$this->sqlRepo->getLogs($todayRange->start, $todayRange->finish, $shopper);
}
return merge($todayRange, $legacyRange);
}
}
class ShopperLogsSqlRepo implements ShopperLogInterface
{
/**
* #var /Illuminate\Database\Eloquent\Model/ShopperLogs
*/
protected $model;
/**
* #param /Illuminate\Database\Eloquent\Model/ShopperLogs $model
*/
public function __construct(ShopperLogs $model)
{
$this->model = $model;
}
public function getLogs($from, $to, $shopper)
{
$this->model->whereLogs //do eloquent sql stuff here
}
}
class ShopperLogsRedisRepo implements ShopperLogInterface
{
/**
* #var \Redis\Model\Class
*/
protected $model;
/**
* #param \Redis\Model\Class $model
*/
public function __construct(ShopperLogs $model)
{
$this->model = $model;
}
public function getLogs($from, $to, $shopper)
{
$this->model->whereLogs //do redis stuff
}
}
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class RepositoryServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
$this->app->bind(\App\Repositories\Contracts\ShopperLogInterface::class, \App\Managers\ShopperLogManager::class);
$this->app->bind(ShopperLogsController::class, function ($app) {
return new ShopperLogsController($app->make(ShopperLogManager::class));
});
$this->app->bind(\App\Repositories\Contracts\ShopperLogInterface::class, function() {
return new \App\Managers\ShopperLogManager(new \App\Repositories\ShopperLogsSqlRepo(new \App\ShopperLog), new \App\Repositories\ShopperLogsRedisRepo(new \App\ShopperLog));
});
}
}

many-to-many relationschop in laravel eloquent does not work with pluck()

I have a many to many relationshhip between 2 tables in laravel.
I just want to get the name of the afdeling with user_id=45.
I tried
$afdelingen = User::find(45)->afdelingen->pluck('name');
but is does not work. It works without the pluck but then i get a long string:
[{"id":3,"afdelingen":"Personeelszaken","user_id":0,"pivot":{"user_id":45,"afdeling_id":3}}]
How can i just get
Model 1 code:
<?php
class Afdeling extends Eloquent {
protected $guarded = array();
public static $rules = array();
protected $connection = 'mysql2';
protected $table = 'afdelingen';
public function users(){
return $this->belongstoMany('User','afdeling_user','afdeling_id');
}
}
Model 2 code:
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends Eloquent implements UserInterface, RemindableInterface {
/**
* The database table used by the model.
*
* #var string
*/
protected $connection = 'mysql2';
protected $table = 'users';
//public function safetyreports(){
// return $this->hasMany('Safetyreport');
//}
public function afdelingen(){
return $this->belongstoMany('Afdeling','afdeling_user','user_id');
}
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password');
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return $this->email;
}
}
Since it's a many to many relationship, $afdelingen = User::find(45)->afdelingen->pluck('name'); will have a collection of afdelingen, not just one.
You can get the first one by using $afdelingen = User::find(45)->afdelingen()->first()->pluck('name');
Additionally, you can loop to grab all their names.
foreach(User::find(45)->afdelingen as $item) {
$afdelingen = $item->pluck('name');
}
Or if you want an array of the names...
$afdelingen = User::find(45)->afdelingen()->lists('name');

Resources