laravel-medialibary - addMedia() saves to wrong database connection when model connection set dynamically - laravel

I have an issue with laravel-medialibrary saving the database record to the incorrect database connection, it seems calling the addMedia() method always connects to the default mysql connection?
I've searched and can't see any refernce in the documentation and the only search relating I could find is Laravel-medialibrary working with multiple databases, however I am dynamically setting the database connection with a static method within my modal:
public static function connect($connection)
{
DB::purge($connection);
return (new static)->setConnection($connection);
}
When dumping $this->student->getConnectionName() set on my model instance, it is correctly set to the correct connection. However adding media like below saves to default connection.
this->student
->addMedia($this->avatar->getRealPath())
->toMediaCollection('avatar');
where $this->student is set:
$this->student = Student::connect('school_' . $host->id)
->where('student_reference_code', $this->student_reference_code)
->first();
I am assuming that the addMedia must return a new static instance of the model, where the connection wouldn't be set? I have the same issue if I was to query some eloquent methods such as:
$this->student = Student::connect('school_' . $host->id)->all()
since the all() returns the below:
return static::query()->get(
is_array($columns) ? $columns : func_get_args()
);
Any help on how I can store media within the correct database connection would be appreciated.

Related

View Share doesn't return updated data, how then to share live data?

I currently have a model which access data like so:
$currentSessionID = session()->getId();
$displayCart = Cart::where('session_id', $currentSessionID)->get();
return view('layouts.cart')->with('cartDetails', $displayCart);
This model correctly retrieves the data in a current session.
To access this same data in a header file I'm using View::Share in the AppServiceProvider like so:
public funciton boot()
{
$currentSessionID = session()->getId();
$inCartDetails = Cart::where('session_id', $currentSessionID)->get();
View::share('inCartDetails', $inCartDetails);
}
In my blade the $inCartDetails returns empty. I get [].
My suspicion is that this function ONLY gets called at boot. Hence the name :) and that it's empty cause at the time of starting the session it's empty since user hasn't selected anything. If this is correct how would I then pass live data to multiple views?
The session is not available in the boot method of the service providers. You should create a middleware for this. Check out this answer here: How to retrieve session data in service providers in laravel?

Laravel Error while retrieving a Model with a custom connection

I have a Model Correo with a custom connection that changes dinamically.
The problem is that when I want to retrieve results from the database like this: Correo::on(session('conexion'))->get(), session('conexion') has the connection name, the following error appears:
Call to a member function newCollection() on null
I can get the results using this: DB::connection(session('conexion'))->table('correos')->get(), but I need the Model's methods and the previous one just returns a generic Collection.
Thanks!
You can use setConnection function
$correo = new Correo;
$correo->setConnection('yourConnectionName');
$data = $correo->find(1);
dd($data);
So based on the session ( if you don't have that many remote connections )
if (session('xyz')) {
$correo->setConnection('xyz');
} else {
$correo->setConnection('pqr');
}
`
Well, I solved it, when I created the model I wrote every property and then created every getter and setter, apparently it didn't like the new setConnection setter. I don't know why, but it stopped me from using it.

Laravel DatabaseTransactions for PHPunit have no effect

Writing tests for an existing API, there are many cases where the database has been modified. What I have been doing is something as follows:
public function testPut()
{
//setup
/*Copy an existing record and take its data as an array.
* the function being tested will take an array of data
* and create a new record. Using existing data guarantees
* the data is valid.
*/
$customerObj = Customer::getInstance(); //regular instantiation disabled in this api
$cust = ArCust::first()->toArray();
$oldNum = $cust['CUST_NO'];
unset($cust['CUST_NO']);
$custNo = rand(1, 9999999999999);
//test
/*put() creates a new customer record in the database
and returns the object.
*/
$this->assertInternalType('object', $customerObj->put($custNo, $cust));
//cleanup
/*manually remove the newly created record.
*/
ArCust::whereNam($cust['NAM'])->whereNotIn('CUST_NO', [$oldNum])->delete();
}
I am now running into instances where the API creates or updates many tables based on foreign keys. It would take far too much time to go through and manually reset each table.
The DatabaseTransaction trait provided by Laravel is supposed to take care of resetting everything for you. However, when I use it, I still find the test-created records in the database.
Here is how I have used it:
class CustomerTest extends TestCase
{
use DatabaseTransactions;
public function testPut()
{
//setup
$customerObj = Customer::getInstance();
$cust = ArCust::first()->toArray();
$oldNum = $cust['CUST_NO'];
unset($cust['CUST_NO']);
$custNo = rand(1, 9999999999999);
//test
$this->assertInternalType('object', $customerObj->put($custNo, $cust));
}
}
Am I using this incorrectly? Getting DatabaseTransactions to work correctly will save an incredible amount of time, as well as make the testes more readable to other people.
The issue was that we had multiple database connections defined in config > database.
In the database.php conf file, I changed the default connection to the correct database using its name as defined in the setup:
$connection = 'counterpoint';
and DatabaseTransactions now works.
This next step to this solution is to direct the connection of each test to the appropriate database rather than change the global connection.

disconnect current database connection in controller function and connect another database in codeigniter

in my application/config/database.php i have multiple database connections..now currently database connection will be make as per in which city i get logged in.As per the city database connection will be created successfully...now what i have to do is inside a particular function i need to connect a replication database(for only that function i have connected the replication database)...i will connected that replication database connection successfully but the problem is it will connect for throughout my whole application..i need replication database connection for that function only...for rest of the controllers and functions i need to connect the database which i have connected as per the city.
This will solve your problem, I believe. By this you can open a connection to replication server and can access both DB servers.
Place the code inside the function where you want.
public function replication_test()
{
echo "<pre>";
$query = $this->db->query("SELECT id FROM users ORDER BY id DESC LIMIT 0, 1");
$result = $query->row_array();
print_r($result);
$db_repli = $this->load->database('replication_db', true);
$query = $db_repli->query("SELECT id FROM repli_users ORDER BY id DESC LIMIT 0, 1");
$result = $query->row_array();
print_r($result);
// Close the DB
$db_repli->close();
}
Here i have come up with the solution of my problem i.e loading the replication database inside the constructor function of model instead of controller's constructor function which allows to load the replication database connection whenever it is needed.

Is the database class in Laravel use the "Singleton Pattern"?

I am new to Laravel. Does the Laravel create a database connection every time for each query of the program or use the same database object throughout the program using the "Singleton" Pattern? Does the strategy have an impact on performance, especially for Enterprise Level Applications?
Short answer
No, it's not a singleton, but a factory pattern. However the same connection will be reused if possible and you don't manually request it to reconnect. There is no performance hit.
Long answer
At the beginning of ever request lifecycle, in app/bootstrap/start.php an instance of Illuminate\Foundation\Application gets created. This servers as IoC container.
Shortly after creating the application all service providers will be loaded. The service providers are defined in app/config/app.php
'providers' => array(
// ...
'Illuminate\Database\DatabaseServiceProvider',
// ...
),
Let's have a look at the Illuminate\Database\DatabaseServiceProvider shall we? The important part is the register function
$this->app->bindShared('db', function($app)
{
return new DatabaseManager($app, $app['db.factory']);
});
An instance of DatabaseManager gets bound to db. This instance will stay the same over the whole request and will be used for every database request.
Example from "reverse" direction
Say you call
DB::table('users')->get();
First, the DB facade will resolve to the instance of DatabaseManager that gets bound in the DatabaseServiceProvider using bindShared('db')
protected static function getFacadeAccessor() { return 'db'; }
Then the table('users') call gets forwarded because the method doesn't exist in Database Manager
public function __call($method, $parameters)
{
return call_user_func_array(array($this->connection(), $method), $parameters);
}
It is called on the return value of $this->connection()
public function connection($name = null)
{
list($name, $type) = $this->parseConnectionName($name);
// If we haven't created this connection, we'll create it based on the config
// provided in the application. Once we've created the connections we will
// set the "fetch mode" for PDO which determines the query return types.
if ( ! isset($this->connections[$name]))
{
$connection = $this->makeConnection($name);
$this->setPdoForType($connection, $type);
$this->connections[$name] = $this->prepare($connection);
}
return $this->connections[$name];
}
With if (!isset($this->connections[$name])) it will check if the connection already has been established and will only make a new connection if not.
Then it returns the connection and table('users')->get() will be executed.

Resources