How do I link models across different Datasources? - cakephp

At first glance I am assuming the answer is no simply because when I look at the queries Cake creates, there is no way for one datasource to know how to build queries for the associated tables. At least to me. What I have is a UserModel that hasOne TwitterProfileModel via User.twitter_profile_id. My UserModel uses MySQL and my TwitterProfileModel uses MongoDB. The only solution I can think of is fetching the TwitterProfile data via my UserModel's afterFind callback. I am curious to know if there is a solution more native to CakePHP and if the way I am planning of approaching this issue is the best way. I've looked at the documentation and I see no mentioning of a situation like mine.
EDIT:
I am aware that datasources do not talk to each other. My question is what steps can I follow in order to be able to retrive an associated model that is from a different datasource

This is not related to CakePHP at all but to databases: You can not associate different db systems tables by joins. Use the same db system for both tables if you really have to use sql joins if not you'll need to fetch the records in the afterFind() as you already do it.

Related

Managing multiple datasources in CakePHP

I'm planning to develop a web application in CakePHP that shows information in graphics and cards. I chose CakePHP because the information that we need to show is very structured, so the model approach makes easier to manage data; also I have some experience with MVC from ASP.NET and I like how simple is to use the routing.
So, my problem is that the multiple organizations that could use the app would have their own database with a different schema that the one we need. I can't just set their string connection in the app.php file because their database won't match my model.
And the organization datasource couldn't fit my model for a lot of reasons: the tables don't have the same name, the schema is different, the fields of my entity are in separated tables, maybe they have the info in different databases or also in different DBMS!
I want to know if there's a way to make an interface that achieves this
In such a way that cakephp Model/Entity can use data regardless of the source. Do you have any suggestions of how to do that? Does CakePHP have an option to make this possible? Should I use PHP with some kind of markup language like JSON or XML? Maybe MySQL has an utility to transform data from different sources into a view and I can make CakePHP use the view instead of the table?
In case you have an answer be as detailed as you can.
This other options are possible if it's impossible to make the interface:
- Usw another framework that can handle this easier and has the features I mentioned above.
- Make the organization change their database so it matches my model (I don't like this one, and probably they won't do it).
- Transfer the data in the application own database.
Additional information:
The data shown in graphics are from students in university. Any university has its own database with their own structure and applications using the db, that's why isn't that easy to change structure. I just want to make it as easy as possible to any school to configure their own db.
EDIT:
The version is CakePHP 3.2.
An important appointment is that it doesn't need all CRUD operations, only "reading". Hope that makes the solution easier.
I don't think your "question" can be answered properly, it doesn't contain enough information, not enough details. I guess there is something that will stay the same for all organizations but their data and business logic will be different. But I'll try it.
And the organization datasource couldn't fit my model for a lot of reasons: the tables don't have the same name, the schema is different, the fields of my entity are in separated tables, maybe they have the info in different databases or also in different DBMS!
Model is a whole layer, so if you have completely different table schemas your business logic, which is part of that layer, will be different as well. Simply changing the database connection alone won't help you then. The data needs to be shown in the views as well and the views must be different as well then.
So what you could try to do and what your 2nd image shows is, that you implement a layer that contains interfaces and base classes. Then create a Cake plugin for each of the organizations that uses these interfaces and base classes and write some code that will conditionally use the plugin depending on whatever criteria (guess domain or sub-domain) is checked. You will have to define the intermediate interfaces in a way that you can access any organization the same way on the API level.
And one technical thing: You can define the connection of a table object in the model layer. Any entity knows about it's origin but you should not implement business logic inside an entity nor change the connection through an entity.
EDIT: The version is CakePHP 3.2. An important appointment is that it doesn't need all CRUD operations, only "reading". Hope that makes the solution easier.
If that's true either use the CRUD plugin (yes, you can use only the R part of it) or write some code, like a class that describes the organization and will be used to create your table objects and views on the fly.
Overall it's a pretty interesting problem but IMHO to broad for a simple answer or solution that can be given here. I think this would require some discussion and analysis to find the best solution. If you're interested in consulting you can contact me, check my profile.
I found a way without coding any interface. In fact, it's using some features already included in the DBMS and CakePHP.
In the case that the schema doesn't fit the model, you can create views to match de table names and column names from the model. By definition, views work as a table so CakePHP searches for the same table name and columns and the DBMS makes the work.
I made a test with views in MySQL and it worked fine. You can also combine the data from different tables.
MySQL views
SQL Server views.
If the user uses another DBMS you just change the datasource in app.php, and make the views if it's necessary
If the data is distributed in different DBMS, CakePHP let's you set a datasource for each table, you just add it to app.php and call it in the table if it's required.
Finally, in case you just need the "reading" option, create a user with limited access to the views and only with SELECT privileges.
USING:
CakePHP 3.2
SQL SERVER 2016
MySQL5.7

What NoSQL database to use?

I am developing an app that has many-to-many relationship between its entities and also need to store files (pdfs, emails, images, etc). I will be using Java code. I would like to know which NoSQL database to use. I was thinking of using Neo4J for the many-to-many relationship with gridfs to store the files. Has anyone done something like this before? Need to store the complex relationship between entities and also files (which can be huge.. 16MB-1ooMB).
Not sure that i help you, but i try to use mongo for model many-to-many.
And my experience is terrible...
because, official mongo documentation says: for model many-to-many use DBRef.
And when i use DBRef i need dereference my documents references.
And i don't found any working example how to do it....
I wrote own - but it provides many bugs...
Perhaps i'm looser, and don't understand how works with it, but i think when you will be look to mondo think about it.

Grails: Best approach to dealing with an existing database

I'm writing a Grails application that will be pulling data from an existing Oracle database. If I were designing this from scratch I could hold all the information in two or three domain models because logically that's how the data should be arranged. However, this is a pre-existing database that has the data I need spread across approximately 25-30 tables. So I am wondering which of the following approaches would be considered best. I don't want to do tons of extra work to take advantage of what Grails has to offer, but at the same time I'd like to take advantage of as much of Grails as possible.
Create domain models for all 25-30 tables and then gather the data into two or three classes.
Create the two or three domain models and populate them "manually" with SQL calls
Since I'm new to Grails and how it handles data, something else that I haven't thought of yet.
There is one answer to all of your queries:
database-reverse-engineer plugin
You can configure the way you want to reverse engineer the tables to domain classes. Refer docs as well.

Doctrine ORM in CodeIgniter - pros and cons?

I'm looking into Doctrine as my ORM for an upcoming CodeIgniter project. I've never used an ORM before, but based on what I have read so far, it's a great thing. So, I'd like to get my hands in it.
Questions:
In your experience, what are the benefits of Doctrine?
I noticed that I can identify certain tables to include created_at and updated_at columns. How beneficial is it to know when a record was created and last updated? Should I do this for all my tables?
Thanks.
I haven't personally used Doctrine, but have been told it works well. My understanding is that it requires a significant amount of setup, and works magically after that.
The ORM I typically use with CodeIgniter is called DataMapper ORM, which is a native CodeIgniter solution. Installation is simple (copying a couple files), setting up models is stupidly easy, the tables are simple, and it uses the existing application's database settings. For all the magic without the setup, I'd recommend DataMapper.
Regarding the use of created_at and updated_at columns, only add those columns when you need to track that anyway, such as a blog post or a system user. Specifying those columns lets the ORM handle those fields, so you don't need to, so whenever you create or update objects created from the database, those fields are updated automatically.

Can I use RavenDB (NoSQL) or should I just be using MySQL(RDBMS)?

I am starting on a ASP.NET MVC 3 General Management System (Project Management being the first component). Now I have been reading up a bit on RavenDB and it sounds pretty interesting. One of the biggest things that I like about it is the fact I would not need any type on ORM to handle the data from the DB. This will make my code a lot cleaner and quicker. However coming from a background working exclusively with MySQL for the past 6+ years, I tend to think very relationally with my data. There are a few things that seems like NoSQL would not be good for. I want to throw these things out there and maybe these issues can be handle in a NoSQL solution and I am just think too relationally (then again, maybe this project should be done with MySQL). These are the issues I am thinking of:
Unique Idenifiers: I am going to want to be able to have unique identifiers for a lot of things. For stuff like projects, the name should be unique and could use that however when it come to tasks under a project, the title may not be unique and this is where I would use a quto-increment field but I can do that in RavenDB (from what I can tell)
Linking: Using for fields like status and type I would just use a linking with a foreign key. Now for one-to-many relationships, I can just use the text instead of trying to link a foreign key (which you don't have in NoSQL) but with many-to-many linking, that because a problem. For example, I intend to have a tagging system (like on here) where most items can have 1 to many tags attached to it and then I can perform searches on those tag for the items. Is there a way to do this in NoSQL?
Is a RDBMS really the best tool for the job here or am I just not properly think the "NoSQL" way and I can accomplish this with NoSQL (RavenDB)?
I know this is an old post. Perhaps the docs weren't as good when originally written. But for reference in case other stumble here:
Raven comes with a HiLo document id generation strategy by default. Storing a new document without specifying an id yourself will get an auto incrementing id such as "projects/1", "projects/2", etc. Read more here.
The best guidance on the different ways to handle document relationships is here in the documentation. For the situation you described, you don't really need a separate document at all. You can simply embed a string array of tag names into each item. Documents are not flat, they can be structured. And yes, you can still query on them.
Hopefully you've discovered this on your own since the original post.
Ayende wrote a post "Modeling reference data in RavenDB" which answers some of your questions re Linking. You will have copies of the data between the reference document and your other documents and that redundancy is "ok" for document databases. You can still build indexes or query based on the on either Id or text that you store.
I would favor SQL for a transaction system such as Accounts Receivable application where you need to perform ad hoc queries. With document database you really need to think through how you will be fetching your data and build indexes up front to answers those questions. With RavenDB there is also a dynamic indexing function that learns from and caches the queries that are fired at the database.
For project management where the majority of items would be tasks I would think a RavenDB would fit your needs.

Resources