code igniter datamapper join get() - codeigniter

I am using this join in my code igniter model
$this->db->select('e.name, p.projects');
$this->db->from('example as e');
$this->db->join('procure as p', e.id = p.id');
$this->db->where('e.cityid', '1');
$this->db->where('e.status', '0');
I do not have separate table for join. Here is my data mapper, this is not giving any output.
I have two tables and I want to write a join query on them.I have this in my controller.
$example = new Example();
$example ->where_join_field('procure', FALSE);
Update
can you show me the snippet for joining three tables using data mapper.

Generally you don't do joins by hand with DMZ models (the sql generated will use joins nonetheless). The thing you are looking for is Relations.
You have to set up your model's relations, using the $has_one and $has_many attributes, keeping the naming conventions, creating the necessary tables for many-to-many and so on. You can read about these in the docs here and here.
Once you got your models set up, you can use the where_related and include_related methods where you have used joins before:
where_related is for when you want to filter the models you are querying on some related model's field values. So if you have a related project set up on your Example class, you can write ->where_related('project', 'procure', false); and it will filter the returned Example instances based on their related project's procedure field. So basically it's the same conditionals that you would put into the where SQL clause.
include_related is for when you want to include fields from related models or even whole instance. So if you write ->include_related('project', 'projects') when you query Example instances you will end up with a project_projects attribute on the returned instances. There are many options to control how these attributes should be created. Basically these are the fields you would have put into the select SQL clause.
There are magic methods created for every named relation and many other options, i refer you to the Get (Advanced) page of the documentation for start and free to explore the other pages describing relations.

Related

How to create a GraphQL query that returns data from multiple tables/models within one field using Laravel Lighthouse

Im trying to learn GraphQL with Laravel & Lighthouse and have a question Im hoping someone can help me with. I have the following five database tables which are also defined in my Laravel models:
users
books
user_books
book_series
book_copies
I'd like to create a GraphQL endpoint that allows me to get back an array of users and the books they own, where I can pull data from multiple tables into one subfield called "books" like so:
query {
users {
name
books {
title
issue_number
condition
user_notes
}
}
}
To accomplish this in SQL is easy using joins like this:
$users = User::all();
foreach ($users as $user) {
$user['books'] = DB::select('SELECT
book_series.title,
book.issue_number
book_copies.condition,
user_books.notes as user_notes
FROM user_books
JOIN book_copies ON user_books.book_copy_id = book_copies.id
JOIN books ON book_copies.book_id = books.id
JOIN book_series ON books.series_id = book_series.id
WHERE user_books.user_id = ?',[$user['id']])->get();
}
How would I model this in my GraphQL schema file when the object type for "books" is a mashup of properties from four other object types (Book, UserBook, BookCopy, and BookSeries)?
Edit: I was able to get all the data I need by doing a query that looks like this:
users {
name
userBooks {
user_notes
bookCopy {
condition
book {
issue_number
series {
title
}
}
}
}
}
However, as you can see, the data is separated into multiple child objects and is not as ideal as getting it all in one flat "books" object. If anyone knows how I might accomplish getting all the data back in one flat object, Id love to know.
I also noticed that the field names for the relationships need to match up exactly with my controller method names within each model, which are camelCase as per Laravel naming conventions. Except for my other fields are matching the database column names which are lower_underscore. This is a slight nitpick.
Ok, after you edited your question, I will write the answer here, to answer your new questions.
However, as you can see, the data is separated into multiple child objects and is not as ideal as getting it all in one flat "books" object. If anyone knows how I might accomplish getting all the data back in one flat object, Id love to know.
The thing is, that this kind of fetching data is a central idea of GraphQL. You have some types, and these types may have some relations to each other. So you are able to fetch any relations of object, in any depth, even circular.
Lighthouse gives you out of the box support to eloquent relations with batch loading, avoiding the N+1 performance problem.
You also have to keep in mind - every field (literally, EVERY field) in your GraphQL definition is resolved on server. So there is a resolve function for each of the fields. So you are free to write your own resolver for particular fields.
You actually can define a type in your GraphQL, that fits your initial expectation. Then you can define a root Query field e.g. fetchUsers, and create you custom field resolver. You can read in the docs, how it works and how to implement this: https://lighthouse-php.com/5.2/the-basics/fields.html#hello-world
In this field resolver you are able to make your own data fetching, even without using any Laravel/Eloquent API. One thing you have to take care of - return a correct data type with the same structure as your return type in GraphQL for this field.
So to sum up - you have the option to do this. But in my opinion, you have to write more own code, cover it with tests on you own, which turns out in more work for you. I think it is simpler to use build-in directives, like #find, #paginate, #all in combination with relations-directives, which all covered with tests, and don't care about implementation.
I also noticed that the field names for the relationships need to match up exactly with my controller method names within each model, which are camelCase as per Laravel naming conventions.
You probably means methods within Model class, not controller.
Lighthouse provides a #rename directive, which you can use to define different name in GraphQL for your attributes. For the relation directives you can pass an relation parameter, which will be used to fetch the data. so for your example you can use something like this:
type User {
#...
user_books: [Book!]! #hasMany(relation: "userBooks")
}
But in our project we decided to use snak_case also for relations, to keep GraphQL clean with consistent naming convention and less effort

How to use Query Builder to make a relation in an array? Laravel

I would like to make a relation with query builder... I have three tables, and I would like to join the tables for work with the function.. I'm working in a model.. not in a controller
This is my function
public function map($contactabilidad): array
{
$relation = DB::table('tbl_lista_contactabilidad')
->join('tbl_equipo_postventaatcs', 'tbl_equipo_postventaatcs.id', '=', 'tbl_lista_contactabilidad.postventaatc_id')
->join('users', 'users.id', '=', 'tbl_equipo_postventaatcs.asesor_id')
->get();
return [
$contactabilidad->$relation->name,
$contactabilidad->postventaatc_id,
$contactabilidad->rif,
$contactabilidad->razon_social,
$contactabilidad->fecha_contacto,
$contactabilidad->persona_contacto,
$contactabilidad->correo_contacto,
$contactabilidad->numero_contacto,
$contactabilidad->celular_contacto,
$contactabilidad->comentarios,
$contactabilidad->contactado,
$contactabilidad->respuesta->respuesta
];
}
Query\Builder is best thought of as the primary tool used by Eloquent, but is, nontheless, a completely different package. Query\Builder's purpose is to decouple SQL syntax from the logic that feeds into it, whereas Eloquent's purpose is to decouple that logic from table structures and relationships. So only Eloquent supports Model and Relation classes, Query\Builder does not. And what you're asking for has to do with Relations, so in short, you're kind of barking up the wrong tree.
By the way, I'm differentiating 'Query\Builder' here because Eloquent also has its own wrapper for that class called Eloquent\Builder that shares most of the same syntax. For better or for worse, Eloquent attempts to allow the developer to interact with it in a way that's familiar; not having to track a new set of method names even if you've been seamlessly dropped out of Eloquent and into a Query\Builder object via a magic __call method. It also does something similar regarding Eloquent\Collections vs. Support\Collections. But that can make things very confusing at first, because you have to just kind of know what package you're talking to.
So, to answer your question...
Build a Model class for each of your three tables
Apply relationship methods to each one to pre-configure the model with an awareness of your foreign keys
Call on them using lazy or eager-loading
Something else to note is that with() does not ask Eloquent to perform a JOIN. All it does is run the parent query, extract the key values from the result, run the child query using them in an IN() statement, and marrying the results together afterwards. That's what results in nested results. Speaking from experience, it's kind of a mess generating true JOIN statements off Model Relations and keeping the table aliases unique, so it makes sense this package just skips trying to do that (except with pivot tables on many-to-many relations). This also has the added benefit though, that your related tables don't need to live in the same database. A Query\Builder join() on the other hand, as you have there, would present all fields for all tables at the top-level.

How to navigate many-to-many relationships in entity framework core

According to Microsoft Docs
https://learn.microsoft.com/en-us/ef/core/modeling/relationships#other-relationship-patterns
Many-to-many relationships without an entity class to represent the
join table are not yet supported.
Ok, this leads to a nightmare when you need to migrate apps with several many-to-many relationships that were handled perfectly by EF5.
Now I have Keyword, Tag and KeywordTag entities set up as described in the link.
If I have a keyword entity, which is the correct syntax to retrieve all tags associated with such keyword?
In EF5 it was
var kwd = _context.Keywords.Find(my_kwd_id);
var tagList = kwd.Tags;
Which is the equivalent with EF Core?
Intellisense allows me to write
kwd.KeywordTags
but not
kwd.KeywordTags.Tags
...so I cannot find how to access Tags in any way...
Please don't tell me that i have to explicitly search then loop the KeywordTag entity to extract Tags ...
Since EF Core does not have exact parity with older versions of EF, you need to write bit different code. You would need to do what #Ivan suggested in comments. You also need to eager load your collection because lazy loading is not available. That means you need to do database query explicitly.
Method 1: Instead of using Find you query database directly and bring in related data. (kwd/tagList) would have same data as you are seeing in EF5.
var kwd = db.Keywords.Include(k => k.KeywordTags)
.ThenInclude(kt => kt.Tag)
.FirstOrDefault(k => k.Id == my_kwd_id);
var tagList = kwd.KeywordTags.Select(kt => kt.Tag).ToList();
Alternatively, you can use find but load navigations explicitly. This is somewhat similar to lazy loading but since it is not available you ask EF to load navigations. This will have really bad perf as you will send 1 query to fetch all entries from join table & then 1 query for each related tag in tags table. If you are interested in knowing the way to write it, I can post code for that too.
Tags is an IEnumerable<Tag>. You can iterate over Tags with a foreach loop.

Laravel Eloquent model data from 2 tables

I've just started using Laravel and I'm coming from a different system using an existing database. In this system there are 2 users table, one stock with the CMS and one custom one.
I want to create an Eloquent model which retrieves data from both tables into one model. I know I can use the following to create a relationship.
$this->hasOne('App\SecondUser', 'id', 'id);
But this results in 2 sql queries, and I want to join results from 2 tables before returning the model, in one join statement. How do I do this?
That might be a bit more complicated that you would expect.
First of all you have to use \DB facade to join the two collections(arrays) and then recreate the Eloquent collection from these arrays using Collection's make method.
More info about the Collection class here
An easier way might be to join them using standard laravel relationships and user something like Model::user->with('relation')->get.
But this will still create 2 queries (still relatively fast).

Magento - Custom model one to many relationship

I'm writing a custom module for Magento and I need to implement a one-to-many relationship between two tables.
The easyest solution is to create one model for each table and save data separately, but I think this approach has some limitations (I prefer saving data in one single transaction instead of two, I want to load the combined data when I load the collection, ecc).
What is the best way to handle this kind of situation? Is it possible to have one model class that retrieves data from multiple tables?
Thank you
If the 1-n relationship is strictly a data construct rather than an entity construct, then there is no need for a full ORM representation for the adjacent table.
It's often good to find inspiration and examples in the core code, so please refer to the cms/page and cms/block entities, particularly to their resource models. Take the Mage_Cms_Model_Resource_Page::_getLoadSelect() method as an example, as this method is called by the resource model to load data:
protected function _getLoadSelect($field, $value, $object)
{
$select = parent::_getLoadSelect($field, $value, $object);
$storeId = $object->getStoreId();
if ($storeId) {
$select->join(
array('cps' => $this->getTable('cms/page_store')),
$this->getMainTable().'.page_id = `cps`.page_id'
)
->where('is_active=1 AND `cps`.store_id IN (' . Mage_Core_Model_App::ADMIN_STORE_ID . ', ?) ', $storeId)
->order('store_id DESC')
->limit(1);
}
return $select;
}
Note the join, and note that they have one entity table each (cms_page and cms_block) respectively - this is what the ORM expects, by the way - but there are additional tables which contain cms-entity-to-store data. (cms_page_store and cms_block_store). The records in these latter two tables are not represented by their own ORM classes, rather, they are updated, removed, or joined for loads by the cms/page and cms/block models' resource classes.
Again, the deciding factor on whether to handle the SQL through designated ORM classes comes from the business domain - if the records in the 'many' tables represent things which need presentation or complex representation in your business domain, access them through ORM.

Resources