I am porting a Postgres-backed web app to Laravel 4.2, and I can't see a way to utilize the existing eight or so summation views which are built in the psql db. These views preform various aggregation and averaging functions, and as such are properly part of the schema as they illustrate the relationships between the table entities.
Surely someone has had to use db views with the active record style interface of Laravel? How do you go about it?
Your question is about database views and if I'm not wrong then you are talking about the dynamic table that gets created on the fly, for example, in MySql, it's possible to create a View using something like this:
CREATE VIEW students AS SELECT * FROM profiles where type='student' ORDER BY id;
So, it'll allow to query the dynamic table which is the students view here, for example:
select * from students;
This will return the filtered data from students view. So, if I'm right about your question then I think you are able to use Eloquent just like you use for real tables, for example, to create an Eloquent model for students view you can simply create it using something like this:
class ViewStudent extends Eloquent {
protected $table = 'students';
}
So, now you can use this model as usully you may use for other tables, for example;
$students = ViewStudent::all();
It's just the same way. Since you asked for psql so I'm not sure about the syntax of that or how it works in that system but I believe it's possible same way.
Related
I've created migrations and also their relationships. looks like I'm using polymorphic relations, because in one table, I could have the value of one model or i could have the value of another model. as you might guess, I have something like this
ID Mappable_type Mappable_id value
Mappable_type could be one or many other models. mappable_id will be appropriate id from that model. I needed this because I'm creating dynamic form builder and that's how I designed a database.
Now I need to fetch some records from 5 tables together, so I gotta use joins. the table where I have mappable_type is at the third place from those 5 joins. now What should I do also to only fetch data from these 5 joins that have specific model type that is in that morph table? I'm doing something like that for now:
$final = Dynamic::join('dynamic_properties_values','dynamic_properties_values.dynamic_id','=','dynamic.id')
->join('dynamic_properties_mapping','dynamic_properties_mapping.id','=','dynamic_properties_values.mapping_id')
->where('dynamic_properties_mapping.mappable_type','=','App\Driver')
->get();
As you see, I have written by hand something like
"App\Driver"
. It doesn't matter I have written it by hand or had it saved into a variable and than used it here. WHat really bothers me is that let's say when I was inserting data into these morph tables, Model got saved as "App\Driver". what if I make a mistake and when fetching with joins, I write something like App\Http\Driver? or what If I changed the location of the model itself in my code project?
What's the best practice not to make those kind of errors by the time my project reaches huge amount of users?
I apologize if this is a silly question. This is probably well out of standard practice, but I'm looking to be able to join data from a MS-SQL database with that of MySQL in Laravel 5.2.
I'm not sure if it's possible to do something like...
\DB::connection('sqlsrv')->table('mstable')
->leftJoin(\DB::connection('mysql')->table('mysqltable'),
'mysqltable.shared_id',
'=',
'mstable.shared_id');
My thinking is that if Laravel is converting the query early enough into a PHP object, it should be able to. Otherwise, is there a fallback to being able to use the two database types together?
I'm pretty sure that a join won't be possible. What you can do though, is using relations on different databases. Depending on your situation this might be an applicable workaround. I am currently using this approach to query entities from different databases and "chunk" them so that I only keep a couple of thousand entities in the memory. It's still an efficient way to iterate over all entities, because I'm using eager loading, so that Laravel / Eloquent only triggers two requests per chunk: One to get the primary models and the second to get the relation (by default this is done by an IN statement on the relation's table using the keys obtained from the primary models table).
A "simple" way to set this up is to fill the protected $connection property of the Eloquent Models like this:
class Foo extends Model{
protected $connection = "mysql";
public function bar(){
return $this->hasOne(Bar::class);
}
}
class Bar extends Model{
protected $connection = "ms-sql";
}
Foo::with("bar")->get();
Using Laravel 5.1, I have created an Eloquent Model:
class Divisions extends Model
{
}
I have a table and a view in my database which are relevant to this model.
divisions_info - The table, it will have INSERT and UPDATE queries run, but will never have a SELECT run on it.
divisions_view - The view, it will have SELECT queries run only (obviously).
The reason for the segmentation is that the divisions_view view joins with data from the divisions_info table and from another relevant, read-only table in an adjacent database.
I would like to utilize one model for everything that deals with divisions, but direct any UPDATE/INSERT queries on the divisions_info table and all SELECT queries on the divisions_view view.
The Laravel documentation allows you to override the assumed table name, like so:
protected $table = 'divisions_info';
However, this takes precedence over the entire model. I would like to be able to utilize all the built in methods that come with using the Eloquent model, but have it split accordingly across SQL statements.
Is this possible? If so, what is the right way to achieve it?
If it is not possible, without diving into opinion, what is the most logical/Laravel-esque way to work with the same data in two different locations?
This might be a solution:
use Illuminate\Database\Eloquent\Model;
class Division extends Model {
public function scopeFromView($query)
{
return $query->from('divisions_view');
}
}
Just call the fromView() method in any part of the query like this:
Division::fromView()->get();
I have two data domains, Student and Course, and relative data mappers, StudentMapperMySQL and CourseMapperMySQL. Now I want to implement a third data mapper for fetching both data, especially for taking advantage of SQL JOIN (SELECT ... FROM students JOIN courses ON .... WHERE ...). What should the select()/fetch() method return? and how should it work via a repository pattern implementation?
It looks like you are creating new aggregate root just for query purpose, which is totally fine if you would like to use CQRS.
Every AR should have its own repository, so you should make AR StudentCourses and StudentCoursesRepository (something from your ubiqutious language).
You should call that repository to get student course data repo.getCoursesForStudent(student_id) or for all at once repo.getStudentsWithCourses().
Repositories should return only aggregate roots, so in return you would get an aggregate root or list of them.
Such AR would look like that:
class StudentCourses:
studentName Name (VO)
studentId AggregateId (VO)
courseList Course[0..*] (Entity)
class Course:
your course data
What is important here is that you have different models for command and for query, so you can have two different Course model entities in your system. Course in command model is probably an aggregate root, while in query model it's not.
I suppose that this answer might be a bit hard to understand, but I did my best. Anyway I'm not a DDD expert so there might be other ways to do that.
If I have a class representing access to one table in my database in a class:table relationship, so I can hide table details in one class. But as any useful application I have to query several tables. How can I accomodate this using the class:table design?
There's a couple of different ways you can achieve this, however, which one you choose really depends on your circumstances.
1) Break the connection between your objects and your database
Write your objects to have no connection with your database tables. First normalise your database tables, then, look at how the user of your application will interact with your data. Model the data to objects, but don't tie each object to the table (ie with a Zend_DB_Table_Abstract class)
Once you have established your objects, then write mapper classes which map your objects back to the relevant tables in your database. These are the classes which extend Zend_DB_Table (if appropriate).
You can handle joins in two ways, either map the joins through the Zend_DB_Table relationship functionallity, or, (IMHO a better choice) just use Zend_DB_Select to make the relevant methods within your your mapper class.
So you've then got two classes (probably per table, but not always)
Person
PersonMapper
In your code, when you want to work with some objects, either create a new object
$person = new Person();
$person->setName('andrew taylor');
Then write pass it to the mapper to save it:
$personMapper = new PersonMapper();
$pesonnMapper->save($person);
Or, do it the other way:
$personMapper = new PersonMapper();
$person = personMapper->load(29);
$person->setName('joe bloggs');
$personMapper->save($person);
The next step on from here would be a collection class based on the SPL:
$personList = $personMapper->loadAllMen();
foreach($personList AS $person) {
echo $person->getName();
}
Where $personMapper->loadAllMen() is a method like:
$select = $this->select();
$select=>where('gender = "Male"');
$zendDbRows = this->fetchAll($select);
return new PersonList($zendDbRows);
2) MySQL Views
If you have a lot of joined tables where there is one row per join, so, you're joining customer information based on an id in your orders table, and you're doing it read-only (so you don't want to update any information through the Zend_DB_Table adaptor) you create your normalised tables, then, a single view across the top. The view handles the joins behind the scenes so through Zend it feels like you're connecting to a single table.
There are some caveats with this, MySQL views do have some performance problems (which is why it's best on single row FK joins), and, they're strictly read only.