I have built a MySQL database with multiple tables and complex relationships, but when I go through the vapor documentation, specifically, in the building the model phase, there is a method for creating the table (that my model class will interact with).
static func prepare(_ database: Database) throws {
try database.create("users") { users in
users.id()
users.string("name")
}
}
However, I don't want to use it because the table that I already have contain foreign keys and types like DATETIME (which I don't know how to declare within the swift context.) is there a way to link my already built tables with vapor?
This is somewhere Vapor (or more correctly Fluent, which is the database level of Vapor) is a bit limited.
Yes, you can use your existing tables. In your prepare(_:) method, you can simply leave the implementation empty without creating a table at all. You should also leave revert(_:) empty as well.
In your init(node:in:) initialiser and makeNode(context:) method, you will need to map between the column names and types in your table and the property types in your Swift model.
In the model object class (User here), the prepare method can be left unimplemented since we don't need to create the tables explicitly from the code. So should be like
static func prepare(_ database: Database) throws {
...
}
But should add a static variable named entity which will map the table name in db without model class, like following
final class User: Model {
static let entity = "users"
...
}
And finally, we should add the model to the droplet's preparations array with drop.preparations.append(User.self)
So that we can use any existing table in a database which has complex relationships, to map from a model object in Vapor.
Related
We inherited a 3rd party database schema where several tables use a database
design pattern in which tables do not define foreign keys directly, but in
a way where some tables do so by a combination of two columns:
a column specifying name of table:
either directly (ENUM type)
or by means of another table (type_id referencing table types, which then contains table name in a varchar column)
a column specifying PK value from said table (e.g. type_value)
This results in a scenario where one row references one table while another
row may reference a completely different table.
We can use query builder and define JOIN and WHERE clauses manually for each
scenario, but it'd be more practical to have one property for each foreign
table and use WHERE clause to filter target table results only, e.g.:
class Foo {
private $id; // PK for Foo
private $type; // string (enum), e.g. 'bar' or 'baz'
private $type_id; // contains PK of Bar or Baz, respectivelly
private $bar; // references entity Bar
private $baz; // references entity Baz
}
The closest thing to what we need which I managed to find is to use Criteria API
to update the WHERE clause dynamically in getter methods (as seen here).
However I'm completely lost in terms of how to setup Doctrine annotations in
this case. Does Doctrine support a DB schema such as this one, or do we have to
fall back to building each query manually via query builder or DQL?
I'm building a Flask app, which, at startup, should read some number of tsv files, each of which has the same schema, put them in tables (one for each file), and then users will specify which table/file they want to query, and some number of keys.
I'm not sure how to do this, but the best way seems to be to specify one schema and then, once the app starts, read the files and dynamically create tables for each file. I can't find anywhere in the SQLalchemy docs any mention of how to use the same schema multiple times. Perhaps I need to extend my schema class, but i'm not sure how to do this at startup.
Thanks in advance!
-- EDIT --
It looks like this answers half of my question:
Flask-SQLAlchemy. Create several tables with all fields identical
So my question now is: Can you do the above in Flask, and can you do it as the app starts?
You can take 2 approaches.
Sub-classing - You create a base Mixin for schema and subclass it for each concrete tables. This approach is useful, if you expect that in future the schema for different tables might diverge. If a new field needs to be added in only one table you can add it only in sub-class. (variables db, Model etc is used from flask sqlalchemy quickstart)
class BaseMixin(object):
name = db.Column(String(80), unique=True)
field2 = db.Column ...
class SubClass1(BaseMixin, db.Model)
pass
class Subclass2(BaseMixin, db.Model)
additional_field_for_subclass2 = db.Column(...
pass
Common table for all - If you are confident that the schema will remain the same for all tables. I would suggest you create one table for all you data, with a additional field data_source which will indicate where the row/data came from.
class CommonTable(db.Model):
data_source = db.Column(String(100) ..)
field1 = ...
field2 = ...
I am using django and have three objects: Customer, Location and Department. Each has a related Setting object.
Is it better form to create a single table with optional/null foreign keys?
Or to create a different setting object/table for each of the 3 entities?
There are a few options
Create a separate Settings table and have a nullable ForeignKey from all of your objects to the Settings table. If you choose this option, you should create an abstract base class that has a ForeignKey to the Settings table and inherit from that abstract base class. That way you don't have to add the ForeignKey every time you create a new model.
Create a separate Settings table and use GenericForeignKeys from the Settings table to reference your object (Customer, Location, and Department). This has the advantage of not having an extra column in all of your tables that need settings. However, you can't do DB joins with GenericForeignKeys via the Django ORM's normal API. You'd have to use raw sql. Also, select_related doesn't work on GenericForeignKeys so you'd have to use prefetch_related instead.
Store the settings in a column in the database. You should interact with the data in some format (I like JSON) and then serialize it to a string to store in the DB. Then to read the settings, you could deserialize the string back into JSON and interact with it. With this method, you wouldn't need to join with another table to get settings, and wouldn't need to run migrations every time you added new settings. You also wouldn't need a separate Settings table. However, constructing a query to find objects with certain settings would be a pain the query would probably be slow as well.
Each option has its pros and cons; so, pick your poison ;)
In the controller of my module in catalog/controller/module/my_module.php, I'd like to read data of another module (such as affiliate or slideshow module) that is stored in the setting table.
In the controller, I have something like this:
class ControllerModuleMyModule extends Controller {
protected function index($setting) {
....
....
}
}
where $setting gives me access to my current module's data from the setting table. Is there an easier way in Opencart (perhaps a built-in function) to access data of another module?
If it's another modules data not yours that you want to access, the easiest way is to query the setting table for it unless you know exactly the key you want, in which case using
$this->config->get('module_name_setting_name');
For example, to get the featured product list of ID's, use
$ids = $this->config->get('featured_product');
which will provide you with a CSV of product ID's
I have a table Object that has 2 fields that are foreign keys (user_id and teacher_id). After generating the Entities for the X table, the entity only contain the $user and $teacher properties, which forces me to use the associated objects instead of id. So supposing I know the user_id and teacher_id for my object, instead of doing:
$object->setUserId(1)
I have to do:
$user = $this->getDoctrine()->getRepository('MyBundle:Users')->find(2);
$object->setUser($user)
is there no way to work directly with the ids to avoid retrieving the entire object associated to each id?
The framework suggests to use objects when setting the association value. Still – are you sure the record isn't loaded in the memory already? If it is, it will not cause additional SQL statement execution.
If you really need to update the association without loading the object, you can
run native SQL;
try creating Doctrine Proxy object manually and setting it instead.
You can get the proxy object using EntityManager method getReference:
$object->setUser($this->getDoctrine()->getReference('MyBundle:Users', 2));