Yii2 - Using Junction table with relations - yii2

I have a table Book and a table Cover. The relation between Book and Cover is one-to-many, meaning that each book can have more than one cover. I thus have a third table connecting the two, book-cover-relation.
Translating those to models means I have 3 models,
Book,
Cover,
BookCoverRelation
Now In the Book model, I have the following relation for the related BookCoverRelations
public function getBookCoverRels() {
return $this->hasMany(BookCoverRelation::className(), ['book' => 'id']);
}
What I want though, is a to be able to get all the Covers. Is there way through which I can do this without first getting the relations and then iterating through them?

You should create a relation with viaTable in Books Model
public function getCovers(){
return $this->hasMany( Covers::class,['id'=>'cover_id'])->viaTable('{{%book_cover_relation}}',['book_id'=>'id']);
}
and use it like
$qu = Books::findOne (['id'=>1]);
foreach($qu->covers as $cover){
echo $cover->name;
}

You can use viaTable() method to get all the Cover models "passing through" your BookCoverRelations junction table, as stated in the Definitive Guide to Yii 2.0: https://www.yiiframework.com/doc/guide/2.0/en/db-active-record#junction-table

Related

Namespacing with polymorphic relationships Laravel 5

Upgraded to L5 and loving it! However currently facing an issue with polymorphing a relationship. In my userable column in the Users table I need to include the namespaced value (e.g. "App\Employee" rather than just "Employee") for the polymorph relationship to work.
Feels like I am missing something.. How do I avoid forcing to store namespaced values in the table? :)
PS: Well aware others are struggling with similar issues (e.g. Laravel 5 namespaces) but have not seen anything relating to avoiding to store the namespacing in the tables..
BaseController
<?php namespace App\Http\Controllers;
use App\Client;
use App\User;
...
HomeController
$user = User::with('userable')->get();
foreach ($user as $u){
var_dump($u->userable->mobile);
}
User model
public function userable()
{
return $this->morphTo();
}
Client model
public function user()
{
return $this->morphOne('App\User', 'userable');
}
Employee model
public function user()
{
return $this->morphOne('App\User', 'userable');
}
Ended up creating a separate column in the User table. One for role (e.g. Admin, Employee etc.) and another column for the userable_type (e.g. '\App\Admin')
protected $morphClass
Seemed promising
(Polymorphic Eloquent relationships with namespaces) but has known bugs in the inversed relationship (Laravel 5 namespaces)
And even the latter does not work quite elegantly - so until it is resolved, I'll go for the two column approach - hopes this helps others!

Yii model relationship, how is it important?

It is my first time to use yii and unlike my old programming style, i notice that it use relationship automatically in its model.
public function relations()
{
return array(
'author'=>array(self::BELONGS_TO, 'User', 'author_id'),
'categories'=>array(self::MANY_MANY, 'Category',
'tbl_post_category(post_id, category_id)'),
);
}
I'm not used in doing this MySQL relationship. my old programming habit is connecting/manipulating the data to the php program itself.. To clarify my question, is this yii model relationship important? if i dont use this method, will i encounter problems?
Yii relations are very useful and if you work with it you will see that it will make you do less coding and make your code more readable.
while it is so much used in Yii applications, if you don't use relations, you won't get into any trouble, it is supposed to help you code and develop faster.
like if you looked at Yii blog, you have relation between Post model and Comments model, and you could go like this:
$post = Post::model()->findByPk( $id ); // find one post
$allCommentsRelated = $post->comments; // just one line for all search query and instanciating models
BTW in relations, there are two type of loading:
lazy loading (this is default mechanism)
eager loading
you have to know your scenario, and choose one that suites that scenario best

MVC3 and EF: How to handle CRUD operations of nested entities (Parent, Child and Grandchild)

I'm new to MVC 3 and Entity Framework so I'd like to know what is the best approach.
Basically, I have 3 entities: Course, Module and Chapter. Each is a parent of the next with a one to many relationship (A Course has many Modules and a Module has many Chapters). I have a column SortOrder for Modules and Chapters to have them ordered sequentially.
My idea was is to use partial views for the child entities when updating the parent.
I have 3 views in mind:
Create/Update Course: all basic details for a course
Course Modules (basically a different view for Update Course) which has an option to add multiple partial views, each creating a Module
Course Timeline (still a different view for update course) which lists all Modules (on separate divs) and has the option to add multiple partial views, each creating a Chapter
Does my plan sound right and plausible? I plan to use hidden fields to store IDs. I also want the saves to occur asynchronously.
Any piece of advise or information would be highly appreciated. Thanks!
I think this is what your after but not sure. For handling persistence of child/grandchild entities, you can do this in several ways. You can either perform crud operations on each entity separately. So that will involve for example saving the modules by themselves with a reference to the course, probably courseId.
Or you can look at saving just the aggregate root, which in this case looks like its your Course entity. This will involve Loading the course, populating the modules on the course, and for each module populate the chapters. Then when you `db.Courses.Add(newCourse); db.SaveChanges(); all the entities will be persisted. You have to make sure your foreign key and model references are setup correctly.
For example, to save child entities:
public ActionResult DoSomething(int courseId, Module newModule)
{
var course = someService.LoadCourse(courseId);
course.Modules.Add(newModule);
using (var db = new MyDbContext())
{
db.Courses.Add(course);
db.SaveChanges();
}
return RedirectToAction("Success");
}
Or you can save individually:
public ActionResult DoSomething(Module newModule)
{
using (var db = new MyDbContext())
{
//You will need to make sure newModule.CourseId is set correctly
db.Modules.Add(newModule);
db.SaveChanges();
}
return RedirectToAction("Success");
}
Depending on your views, you will be able to judge which way is best to go. Regarding asynchronous saving, you will be able to call these endpoints with jquery posting the models as json. On a side note, one thing to look at would be to create a custom Anti Forgery Token validator for json requests, example.

EF4.1 Code First, Navigation Property across multiple mapping joins

In SQL, I have a 1:1 relationship defined between 2 tables which are linked by 2 mapping tables, four in total. I have no influence on the database schema.
I'd like to reflect this in my Code First model so that I can say Foo.Bar and Bar.Foo rather than Foo.Mapping1.Mapping2.Bar (or similar). Is this possible using the Fluent API? I know you can specify a many to many relationship using the designer which results in Foo.Bars and Bar.Foos so hopefully this is possible.
I don't know that you can map it with Fluent API but I know you can create an extension class and create an extension to handle the mapping like so:
public static class FooExtension
{
public static Bar Bar(this Foo)
{
var bar = Foo.Mapping1.Mapping2.Bar;
return bar;
}
}
Then you would call the extension method
var foosBar = Foo.Bar()

How to map more than one table to a class with SQLAlchemy

I'm new to sqlalchemy and am trying to map several tables to a class.
The tables are constructed like so:
Types
-typeID
-typeName
-groupID
...
TypeAttributes
-typeID
-attributeID
-attributeValueInt
-attributeValueFloat
The idea is to have sqlalchemy map a from TypeAttributes to normal class attributes.
As added complexity attributeValueInt and attributeValueFloat are exclusive. By which I mean each attributeID will have either an int or a float assossiated and the other will be null.
Any ideas how this could be done? or advice on a better way to do it (I have no control over the Database itself).
Have a look at this question: How to map one class against multiple tables with SQLAlchemy?