James
James

Reputation: 5169

Laravel Interface to multiple models

I'm writing a system around an existing database structure using Laravel 4.1. The current system is based around two websites which use their own table, a and b, both of which are identical. This is an unavoidable problem until we rewrite the other system.

I need to be able to query both tables at the same time using Eloquents Query Builder, so I may need to get a list of rows from both tables, or INSERT or UPDATE from either at any time.

Currently we have a model for both tables, but no way to link between them and implement the missing methods such as all or find.

Our thought is to have an Interface which will bind these results together, however we're not sure how to go about this at all.

<?php

    interface HotelInterface {
        public function all();
        public function find();
    }

    use Illuminate\Database\Model;

    class Hotel implements HotelInterface {

    }

?>

Is all we have so far.

Upvotes: 2

Views: 1721

Answers (3)

James
James

Reputation: 5169

I asked on the Laravel forums and got the answer I was looking for! I'm reposting here incase.

What we're actually after is a Repository which would look like this:

<?php
    class HotelRepository {
        public $A;
        public $B;

        public function __construct(A $A, B $B) {
            $this->A = $A;
            $this->B  = $B;
        }

        public function find($iso = NULL, $hotelid = NULL) {
            $A = $B = NULL;

            if($iso !== NULL) {
                $A = $this->A->where('country', $iso);
                $B  = $this->B->where('country', $iso);

                if($hotelid !== NULL) {
                    $A = $A->where('id', $hotelid);
                    $B = $B->where('id', $hotelid);
                }
            }

            if($hotelid !== NULL) {
                if($A->first()) {
                    return $A->first();
                }
                if($B->first()) {
                    return $B->first();
                }
            }else{
                return $A->get()->merge($B->get());
            }
        }

        public function all() {
            $aCollection = $this->A->all();
            $bCollection  = $this->B->all();
            return $aCollection->merge($bCollection);
        }
    }

Now in the controller where I want to call this, I just add:

<?php
    class HomeController extends BaseController {
        public function __construct(HotelRepository $hotels) {
            $this->hotels = $hotels;
        }
    }

And I can now use $this->hotels to access the find and all method that I created.

Upvotes: 2

beech
beech

Reputation: 1064

If the tables are identical you should only need one model, the connection is the only thing that needs to change. Have a read here: http://fideloper.com/laravel-multiple-database-connections.

There's a Eloquent method on() for specifying the connection, here's an example:

The Eloquent example looks like what you need:

$results = Model::on('mysql')->find(1);

Add both connections to your database config and then change the on() part depending on which DB you need to query.

Update: misunderstood the question

If you only need to change the table and not the database, you can use setTable()

$model = new Model
$model->setTable('b');
$model->find(1);

Although that may get confusing.

Instead, you could also define a base model and then extend it with the only difference being the table protected $table = 'b';

Upvotes: 1

Dennis Braga
Dennis Braga

Reputation: 1478

You can always change the default database for the one you need. I use this Config::set('database.default', 'chronos');, where chronos is one of my databases. When I need to change to the "other", I just change de database name. You can call it wherever you want. I think that what you're looking for is just switch between the databases.

You need to have two different models, one for each table on each database, though.

Let me know if I got it wrong.

Upvotes: 0

Related Questions