I have a scenario that I'm struggling to find a clean solution to. In my CakePHP app, I have a User and Survey model. The idea is that the admin can create surveys, and assign them to users. Users can then respond to the surveys (multiple times) and those responses get stored.
Now, I'm planning to make a Responses model, and associate the Responses with Users via hasMany/belongsTo. Easy. The problem comes in assigning Surveys to Users. Since users will be able to respond to multiple surveys, it makes no sense to try and add "survey_id" columns to my Users table for associations.
What makes the most sense is a new survey_assignments table, that has id, survey_id, and user_id columns.
The problem is I'm unclear how to handle that kind of intermediary association table cleanly, sticking to CakePHP best practices. What I need to do is fairly standard in straight php/mysql, but I want to avoid straight SQL queries, and keep things in line with CakePHP convention.
What's the cleanest way to go about creating and working with a (potentially model-less) association table, while avoiding manual queries?
Of course I found the answer after posting:
a HABTM association with a join table!
Related
I am getting started in microservices architectures and I have a couple of questions about the data persistence and databases.
So my understanding is each microservice has it's own database (not necessarily, but usually). But given that case, consider a usual social media platform with users, posts and comments. There will be two microservices, a user's microservice and a posts' microservice. The user's database have a users table and the posts' database has posts and comments tables.
My question is on the posts microservice, because each post and comment has an author, so usually we would create the foreign key pointing to the user's table, however this is in a different database. What to do then? From my perspective there are 2 options:
Add the authorId entry to the table but not the foreign key constrain. If so, what would happen in the application whenever we retrieve that user's data from the user's microservice using the authorId and the user's data is gone?
Create an author's table in the posts' database. If so, what data should that table contain other than the user's id?
It just doesn't feel right to duplicate the data that is already in the user's database but it also doesn't feel right to use the user's id without the FK constraint.
One thing to note, data growth is quite different
Users -> relatively static data.
Posts & Comments -> Dynamic and could be exponentially high compared to users data.
Two microservices design looks good. I would prefer option-1 from your design.
Duplication is not bad, In normal database design this is normal to have "Denormalization" for better read performance. This is also helping in decoupling from users table , may help you to choose different database if require. some of your question what if users data is missing and posts is available, this can be handle with business logic and API design.
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
I am working on my first web project. I have referenced many tutorials and pdfs but all those had simple examples for the login and sign-up feature for a webpage, which only used a single database. I am having a massive confusion on whether or not, the login and sign-up should have separate databases.
My main question is : The project intakes user's personal information(name, email, address, telephone number, etc.) along with information specific to their vehicles (model, company, make, manufacture date, etc.). And after logging into the website, both these data's are important but only some of them are in use like, the user's name, his/her address, the model of vehicle, and the company. So should I maintain separate databases for both of them and reference each element with a foreign key while working on databases ?? Or should i just bother less and use a single database and complete my login and sign-up function ??, because with the no. of columns that I have apparently is very large.
This might be a bit too academic, but a word you'll want to learn well is normalization. Here is a link to a pretty stiff definition: https://en.wikipedia.org/wiki/Database_normalization
This being your first web project, my advice would the following:
Don't be afraid to make mistakes. I would strongly encourage trying approaches you think are good and then don't be afraid to change your mind. The lessons learned will stick with you.
Keep everything simple up front. Only add complexity when you need it.
Definitely don't be afraid to grow horizontally with tables (add more and more tables). When I first started working with databases I was afraid to have too many tables because it felt wrong. Try to resist the temptation to cram everything in one table.
Definitely separate login, users and vehicle information. Not a bad idea to also separate out user address information since people can have more than one address.
You must use the same database for holding all the information for your project. Two different database is not really good idea , you can create many tables in an database. and each table is designed to hold different information.In case of your example you may choose the following tables in the same database
UserLogin [store login information]
User [ store personal info]
Vehicle
and so on
There must be one to one relationship between UserLogin and User table and one to many in user - Vehicle table
One user may have many Vehicle
Hopefully it will help
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.
So I've just read a bunch of the Cakephp model saving related data questions here on stack, but I am not finding what I'm looking for. Beyond the obvious technical issue, I have the distinct feeling that I am doing it wrong. My question is this: If you have an organizations table, and a users table, and you want to link them with a lookup table, so that neither is associated with another except by the linking association in the lookup table, how would you do it? Is a lookup table advisable in Cakephp, or is that a horrible hold-over from my sql days that needs to die? What is best practice here? HABTM what I need? Furthermore, how do you learn this stuff? I try things I think might work, but they turn out kludgy at best.