When generating a table from this model:
function init()
{
parent::init();
$this->addField('person_id')->refModel('Model_Person')->mandatory(true);
$this->addField('username')->mandatory(true);
$this->addField('password')->mandatory(true);
}
I get this SQL statement:
create table users (
id int auto_increment not null primary key,
person_id varchar(255),
person int(11),
username varchar(255),
password varchar(255));
In this SQL statement i get the opposite of what is said in the tutorial:
Calling refModel with a field name ending in "_id" will actually create 2 field definitions. "publisher_id", for instance, will be defined as integer and will have type "reference", and a field "publisher" will also be added, with exactly same properties - but it will be a calculated field and will use sub-select to determine the value.
I want to know:
Is the generated SQL statement correct?
What does this VARCHAR additional generated field do? (I made CRUD and when added new records, the value of this field was saved as NULL).
When using refModel(), if i used the model name only ('Person') i got an error (Unable to include Person.php), i had to use the complete class name ('Model_Person'). Is this ok? shouldn't i be able to use the model name only?
The mandatory() doesn't use NOT NULL, is there way to do this?
The generated SQL statement is not correct. It's a bug in generator. You need just one field o type "int" ending with the _id.
The reason why it does this, is because refModel() actually creates two fields in the model, one of which is used for editing (_id) and other is used for listing data (as a sub-query)
When you use refModel, you should use "Model_Person". The consistency between refModel, setModel and other fields will be improved in 4.2, it's not done due to compatibility reasons.
The SQL Generator by it's nature is incomplete and it can't be complete, so it's better that schema is reviewed anyway. For instance you might have some fields which are not defined in "Model". Also I prefer that developers pay attention to SQL as it might not reflects models precisely, one model may use multiple tables through join or models may inherit each then add more field definitions there.
mandatory() is a model-level requirement which works similarly to other validations. While MySQL could handle the "mandatory" condition, it wouldn't be able to handle others. Besides, you may remove "mandatory" when you inherit models.
I'll try to add a guide on effective use of Models in Agile Toolkit.
Related
I'm converting an older system to laravel/eloquent and I'm still somewhat new to all the 'toys' built in to the ORM. Often I code out something and find out something like it already exists in the back-end code.
What I have is a table of records where the 'name' field has either changed spelling over time, it is occasionally abbreviated, gets changed in API input or is frequently mis-spelled in manual input. (I'm not entirely sure which of the four is the reasoning) So it utilizes additional records and columns to deal with the alternate names and abbreviations.
I would usually code this sort of thing with a second 'aliases' table for the alternate/abbreviated variations pointing back to the primary (proper) named record in the main table. If it's not found by the exact name, check the 'aliases' table and return the record it points to.
Before I code a getByName() set of methods and overrides to some of the standard model methods, I'm wondering if there is anything built in that might already handle this. (I'm aware I could set up a second table with a many-to-one relationship just for names - I'm just wondering if there's anything else hiding out there)
i have a problem with validate my query in mysql using enum. as i know mysql doesnt support with constraint so i use enum
Example code :
alter table jewerly modify gender enum('M','F') NOT NULL DEFAULT 'M';
it run well if i use like above, but i have a problem to validate in another condition.
i want to modify validation with enum for : inputted productID format must like : PR[xxx], xxx means the number. if we use constraint, it will be like 'PR[0-9][0-9][0-9]',
but i dont know how to use in enum.
alter table jewelry modify jewelid enum('PR[0-9][0-9][0-9]') NOT NULL;
i tried this query above but it doesnt work.. any idea?
What you are attempting to do makes no sense in MySQL. You seem to be using a regular expression format for an enum definition.
Although enum can be used for such validation, it has some drawbacks. There are limits to the number of values, for instance. Changing the type can be problematic -- such as fixing a spelling error.
Instead, you might consider use foreign keys for this purpose:
create table ref_jewelid (
jewelid varchar(255)
);
create table jewelry (
. . .
constraint fk_jewelid foreign key (jewelid) references ref_jewelid(jewelid)
);
You would then populate ref_jewelid with the valid values, perhaps using a spreadsheet to generate the names. You might even take this one step further and have jewelid be a bona fide numeric id, with the name being one attribute of it. That is the approach I would probably take.
I'm just trying out foreign keys for the first time and I'm worried I'm getting a little carried away.
For several of my class variables and their corresponding database records, I've got sets of constants which limit the values that can be chosen. These are currently set and validated using PHP.
What I'm wondering is, should I make tables of these constants in MySQL and lock them into foreign keys? Is this worth the trouble, or is the PHP definitions enough?
For example, say I've got a table transactions, with PHP constants defined for 'credit' and 'debit'.
transactions has a type field which indicates whether the transaction was credit or debit.
Should I create another table (transactions_constants or something) that defines the constants used in transactions(type) and foreign-key them together?
Yes, you should. With FK:
Your database has a more specific interface.
The DB has a clear structure (a DB should be readable regardless of code).
You can avoid accidents with inserts/updates by other DB clients (like PMA).
But you can also have copy of table with consts as consts in PHP (I use codegeneration for this).
Yes, you could use enum. But read 8 Reasons Why MySQL's ENUM Data Type Is Evil first.
In your case, creating a separate table for the transaction type is probably overkill. You can make your type column an enum to help with limiting the allowed values on the database side.
If transaction types had more data associated with them that you wanted to store in the database then a separate table and a foreign key relationship would be the way to go.
If your values set change rarely, you should use MySQL ENUM datatype, and you should turn on MySQL restrict mode. For example:
If your table like that:
CREATE TABLE `table` (
id int unsigned primary key auto_increment,
type enum('credit','debit') not null,
);
the strict mode will help you when you execute a query like
update table `table` set `type` = 'credit1 ' where id = 2
# strict mode on: an error will be raised
# strict mode off: `type` will be '' (empty string)
The above query can not be run if your code is perfect. It's up to you.
Building a component, version 1.5 (gonna be cut loose soon, I know, but it's what I need to work with.)
Issue with the /admin/tables/mycom.php file. (In which mycom is whatever the component name is)
I'm not following the use of this file. From reading the walkthrough, it's creating a table class that extends JTables.
Now, some of the DB column names I'm using have 'space' characters in them. ie, 'field 1' instead of 'field1' (don't ask me, it's not my data.)
The sytax for identify these fiels is:
$myfield = null
It says these reference your fields in the mySQL table, but my field names include space which wouldn't work with this syntax.
Any help understanding this class, it's php file and what it's use is would be much appreciated.
By creating a JTable class for your table most of the code for editing your table is done for you. I suggest you familiarize yourself with JTable in the Joomla library so you know what functions are pre-written for you that you can use and override.
As to the issue of your DB column name having spaces... well to be honest it's just a bad idea. Here are some MySQL naming convention best practices for you....
always use lowercase with underscores instead of CamelCase. Goes for both the table and column names. (first_name instead of FirstName, address_1 instead of Address1
every table should have an "id" column as the primary key, don't call it UserID or anything else
the table name should be plural (profiles, supports, etc.)
foreign keys should have the singular name of the related table followed by underscore id. For example: "profile_id" or "support_id".
If you can I would recommend you do some ALTER TABLE updates to the MySQL e.g.
ALTER TABLE `#__example` CHANGE `Field 1` `field_1` VARCHAR(50) NOT NULL DEFAULT 'empty';
As I read J.Gilmore Zend Book (Models section):
class Game extends Zend_Db_Table_Abstract
{
protected $_primary='id'; //line 4
}
[..]Line 4 identifies the table's primary key.By default the framework will
presume the primary key is an automatically incrementing integer named id,so
this line is not necessary [..]
I have a question:
Do I need to manually set primary and foreign key while building a table
(Ex. in phpmyadmin with something like "PRIMARY KEY (id),FOREIGN KEY (post) REFERENCES users (id)
ON DELETE CASCADE")?
Or I can handle tables relationships and fields nature just by referring to Zend code using $_primary,$_dependentTable,$_referenceMap and so on?
thanks
Luca
Both. Although you can get away with an ORM dealing with relations, the database ensures at low-level those relations are respected. Always let the database do its job as much as possible, it is built for handling relations and preventing data corruption. What if your ORM has a bug?
As a somewhat related example, say you have a field declared as int in database, you are responsible as a developper for making sure you use int's in your queries, but the database enforces that rule at a lower level, protecting your data in case you don`t.
You should define the primary/unique keys and any other indexes properly when you create the table.
After you've done this in 99% of cases Zend_Db will understand what's going on as it's able to read the table metadata and derive the primary key from that.