ãšã³ããªãŒ
YiiãšNode.jsã®ãã¡ã³ã§ãããã¹ãŠã®Khabrovitesã«ããã«ã¡ã¯ã
ããã¯ã Jiiãã¬ãŒã ã¯ãŒã¯ïŒ GitHub ïŒã«é¢ãã2çªç®ã®èšäºã§ãã ååã®èšäºã§ã¯ãããŒã¿ã¢ã¯ã»ã¹ãªããžã§ã¯ããšã¯ãšãªãã«ããŒã«ã€ããŠèª¬æããŸããã
çŽæã©ããããã®èšäºã§ã¯Active Recordã®äœ¿çšã«ã€ããŠèª¬æããŸãã
ã¢ã¯ãã£ããªèšé²
Active Recordã¯ãããŒã¿ããŒã¹ã«ä¿åãããããŒã¿ã«ã¢ã¯ã»ã¹ããŠæäœããããã®ãªããžã§ã¯ãæåã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããŸãã Active Recordã¯ã©ã¹ã¯ããŒã¿ããŒã¹ããŒãã«ã«é¢é£ä»ããããã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã¯ãã®ããŒãã«ã®è¡ã«å¯Ÿå¿ããå±æ§ã¯ãã®è¡ã®ç¹å®ã®åã®å€ã§ãã SQLã¹ããŒãã¡ã³ããæ瀺çã«èšè¿°ãã代ããã«ãããŒã¿ãæäœããActive Recordã®å±æ§ãšã¡ãœããã«ã¢ã¯ã»ã¹ã§ããŸãã
ããŒãã« `customer`ã«é¢é£ä»ããããActive Recordã¯ã©ã¹` app.models.Customer`ãããã `name`ã¯ããŒãã«` customer`ã®åã®ååã ãšããŸãã 次ã®ã³ãŒããèšè¿°ããŠã `customer`ããŒãã«ã«æ°ããè¡ãè¿œå ã§ããŸãã
var customer = new app.models.Customer(); customer.name = 'Vladimir'; customer.save();
ããã¯ã次ã®ã³ãŒããšåçã§ãããã®ã³ãŒãã§ã¯ãæžã蟌ã¿æã«ããã«ãã¹ãç¯ããããããŸããŸãªã¿ã€ãã®ããŒã¿ãšã®éäºææ§ãããå ŽåããããŸãã
db.createCommand('INSERT INTO `customer` (`name`) VALUES (:name)', { ':name': 'Vladimir', }).execute();
ã¢ã¯ãã£ãã¬ã³ãŒãã¯ã©ã¹ã®å®£èš
å§ããã«ã¯ã Jii.sql.ActiveRecordãç¶æ¿ããŠActive Recordã¯ã©ã¹ã宣èšããŸãã åActive Recordã¯ã©ã¹ã¯ããŒã¿ããŒã¹ããŒãã«ã«é¢é£ä»ããããŠããããããã®ã¯ã©ã¹ã§ã¯ãéçãªJii.sql.ActiveRecord.tableNameïŒïŒã¡ãœããããªãŒããŒã©ã€ãããŠãã¯ã©ã¹ãé¢é£ä»ããããŠããããŒãã«ã瀺ãå¿ èŠããããŸãã
次ã®äŸã§ã¯ãããŒãã« `customer`ã«å¯ŸããŠ` app.models.Customer`ãšããååã®ã¯ã©ã¹ã宣èšããŸãã
var Jii = require('jii'); /** * @class app.models.Customer * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Customer', /** @lends app.models.Customer.prototype */{ __extends: Jii.sql.ActiveRecord, __static: /** @lends app.models.Customer */{ tableName: function() { return 'customer'; } } });
Active Recordã¯ã©ã¹ã¯ã¢ãã«ãªã®ã§ãéåžžã¯Active Recordã¯ã©ã¹ã `models`åå空éã«é 眮ããŸãã
Jii.sql.ActiveRecordã¯ã©ã¹ã¯Jii.base.Modelãç¶æ¿ããŸãã ã€ãŸã ãå±æ§ãæ€èšŒã«ãŒã«ãããŒã¿ã·ãªã¢ã«åãªã©ã®ã¢ãã«ã®æ©èœããã¹ãŠ*ãã¹ãŠç¶æ¿ããŸãã
ããŒã¿ããŒã¹æ¥ç¶ã®äœæ
ããã©ã«ãã§ã¯ãActive Record㯠`db` ã¢ããªã±ãŒã·ã§ã³ã³ã³ããŒãã³ãã䜿çšããŸã ãããã«ã¯Jii.sql.BaseConnectionã®ã€ã³ã¹ã¿ã³ã¹ãå«ãŸããŠãããããŒã¿ããŒã¹å ã®ããŒã¿ãèªã¿åããå€æŽããŸãã åã®èšäºã®ãããŒã¿ããŒã¹ã¢ã¯ã»ã¹ãªããžã§ã¯ããã»ã¯ã·ã§ã³ã§èª¬æããããã«ã次ã®ããã« `db`ã¢ããªã±ãŒã·ã§ã³ã³ã³ããŒãã³ããèšå®ã§ããŸãã
return { components: { db: { className: 'Jii.sql.mysql.Connection', host: '127.0.0.1', database: 'testdb', username: 'demo', password: 'demo', charset: 'utf8', } } };
å¥ã®ããŒã¿ããŒã¹æ¥ç¶ã䜿çšããå Žåã¯ã Jii.sql.ActiveRecord.getDbïŒïŒã¡ãœããããªãŒããŒã©ã€ãããå¿ èŠããããŸãã
/** * @class app.models.Customer * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Customer', /** @lends app.models.Customer.prototype */{ __extends: Jii.sql.ActiveRecord, __static: /** @lends app.models.Customer */{ STATUS_INACTIVE: 0, STATUS_ACTIVE: 1, // ... getDb: function() { // use the "db2" application component return Jii.app.db2; } } });
ããŒã¿ãµã³ããªã³ã°
Active Recordã¯ã©ã¹ã宣èšããåŸãããã䜿çšããŠã察å¿ããããŒã¿ããŒã¹ããŒãã«ããããŒã¿ãã¯ãšãªã§ããŸãã
ãããè¡ãã«ã¯ã次ã®3ã€ã®ã¢ã¯ã·ã§ã³ãå®è¡ããå¿ èŠããããŸãã
1. Jii.sql.ActiveRecord.findïŒïŒã¡ãœãããåŒã³åºããŠãæ°ããã¯ãšãªãªããžã§ã¯ããäœæããŸãã
2.èŠæ±ãäœæããããã®ã¡ãœãããåŒã³åºããŠãèŠæ±ãªããžã§ã¯ããçæããŸãã
3.ã¯ãšãªã¡ãœããã®1ã€ãåŒã³åºããŠãã¢ã¯ãã£ãã¬ã³ãŒãã¬ã³ãŒãã®åœ¢åŒã§ããŒã¿ãååŸããŸãã
ãããã®ã¢ã¯ã·ã§ã³ã¯ãã¯ãšãªãã¶ã€ãã§äœæ¥ãããšãã®ã¢ã¯ã·ã§ã³ãšéåžžã«äŒŒãŠããŸãã å¯äžã®éãã¯ããªã¯ãšã¹ããªããžã§ã¯ããäœæããã«ã¯ã Jii.sql.ActiveRecord.findïŒïŒã¡ãœãããåŒã³åºãå¿ èŠãããã `new`ãä»ããŠã€ã³ã¹ã¿ã³ã¹ãäœæããå¿ èŠããªãããšã§ãã
Active Queryã䜿çšããŠããŒã¿ãååŸããæ¹æ³ã瀺ãããã€ãã®äŸãèŠãŠã¿ãŸãããã
// ID 123 // SELECT * FROM `customer` WHERE `id` = 123 app.models.Customer.find() .where({id: 123}) .one() .then(function(customer) { // ... }); // , ID // SELECT * FROM `customer` WHERE `status` = 1 ORDER BY `id` app.models.Customer.find() .where({status: app.models.Customer.STATUS_ACTIVE}) .orderBy('id') .all() .then(function(customers) { // ... }); // // SELECT COUNT(*) FROM `customer` WHERE `status` = 1 app.models.Customer.find() .where({status': app.models.Customer.STATUS_ACTIVE}) .count() .then(function(count) { // ... }); // , ID // SELECT * FROM `customer` app.models.Customer.find() .indexBy('id') .all() .then(function(customers) { // ... });
IDã«ããã¢ãã«ã®ååŸãç°¡çŽ åããããã«ãã¡ãœãããäœæãããŸããïŒ
- Jii.sql.ActiveRecord.findOneïŒïŒ ïŒã¯ãšãªçµæã®æåã®è¡ã«å¯Ÿå¿ããã¢ã¯ãã£ãã¬ã³ãŒãã€ã³ã¹ã¿ã³ã¹ãè¿ããŸãã
- Jii.sql.ActiveRecord.findAllïŒïŒ ïŒã¯ãšãªçµæã®è¡ã«å¯Ÿå¿ããè€æ°ã®ã¢ã¯ãã£ãã¬ã³ãŒãã®é åãŸãã¯ãªããžã§ã¯ããè¿ããŸãã
äž¡æ¹ã®ã¡ãœããã¯ã次ã®åœ¢åŒã®æåã®åŒæ°ãåãå ¥ããŸãã
- ã¹ã«ã©ãŒå€ïŒå€ã¯ãæ€çŽ¢ãããŠããäž»ããŒã®å€ãšèŠãªãããŸãã äž»ããŒã¯ãããŒã¿ããŒã¹ã¹ããŒãããèªåçã«æ±ºå®ãããŸãã
- ã¹ã«ã©ãŒå€ã®é åïŒé åã¯ãæ€çŽ¢ãããäž»ããŒã®å€ãšèŠãªãããŸãã -ããŒãåã®ååã§ãããå€ãæ€çŽ¢ãããåã®å€ã«å¯Ÿå¿ãããªããžã§ã¯ãã
次ã®äŸã¯ããããã®ã¡ãœããã®äœ¿çšæ¹æ³ã瀺ããŠããŸãã
// ID 123 // SELECT * FROM `customer` WHERE `id` = 123 app.models.Customer .findOne(123) .then(function(customer) { // ... }); // ID 100, 101, 123 124 // SELECT * FROM `customer` WHERE `id` IN (100, 101, 123, 124) app.models.Customer .findAll([100, 101, 123, 124]) .then(function(customers) { // ... }); // ID 123 // SELECT * FROM `customer` WHERE `id` = 123 AND `status` = 1 app.models.Customer .findOne({ id: 123, status: app.models.Customer.STATUS_ACTIVE }) .then(function(customer) { // ... }); // // SELECT * FROM `customer` WHERE `status` = 0 app.models.Customer .findAll({ status: app.models.Customer.STATUS_INACTIVE }) .then(function(customers) { // ... });
æ³šïŒ Jii.sql.ActiveRecord.findOneïŒïŒãJii.sql.ActiveQuery.oneïŒïŒããSQLåŒã«ãLIMIT 1ããè¿œå ããŸããã ãªã¯ãšã¹ããæ¬åœã«å€ãã®ããŒã¿ãè¿ãããšãã§ããå Žåãå¶éãèšå®ããããã«ãããšãã° `app.models.Customer.findïŒïŒãLimitïŒ1ïŒ.oneïŒïŒ`ã®ããã«ã `limitïŒ1ïŒ`ãåŒã³åºãå¿ èŠããããŸãã
ãŸããéåžžã®SQLã¯ãšãªã䜿çšããŠããŒã¿ãååŸããActive Recordã«å ¥åããããšãã§ããŸãã ãããè¡ãã«ã¯ã Jii.sql.ActiveRecord.findBySqlïŒïŒã¡ãœããã䜿çšããŸãã
// var sql = 'SELECT * FROM customer WHERE status=:status'; app.models.Customer .findBySql(sql, {':status': app.models.Customer.STATUS_INACTIVE}) .all() .then(function(customers) { // ... });
Jii.sql.ActiveRecord.findBySqlïŒïŒãåŒã³åºããåŸãã¯ãšãªäœæã¡ãœãããåŒã³åºããªãã§ãã ããããããã¯ç¡èŠãããŸãã
ããŒã¿ã¢ã¯ã»ã¹
åè¿°ã®ããã«ãã¢ã¯ãã£ãã¬ã³ãŒãã€ã³ã¹ã¿ã³ã¹ã«ã¯SQLã¯ãšãªã®çµæããã®ããŒã¿ãå ¥åãããã¯ãšãªçµæã®åè¡ã¯1ã€ã®ã¢ã¯ãã£ãã¬ã³ãŒãã€ã³ã¹ã¿ã³ã¹ã«å¯Ÿå¿ããŸãã Active Recordå±æ§ãä»ããŠåã®å€ã«ã¢ã¯ã»ã¹ã§ããŸããããšãã°ã
// "id" "email" "customer" app.models.Customer .findOne(123) .then(function(customer) { var id = customer.get('id'); var email = customer.get('email'); });
ãªããžã§ã¯ãã®ããŒã¿ãååŸãã
ããŒã¿ãã¢ã¯ãã£ãã¬ã³ãŒããšããŠååŸããã®ã¯äŸ¿å©ã§ãããã¢ã¯ãã£ãã¬ã³ãŒãã€ã³ã¹ã¿ã³ã¹ã®äœæã«è²»ããããã¡ã¢ãªæ¶è²»ã倧ãããããæé©ã§ãªãå ŽåããããŸãã ãã®å Žåãããããéåžžã®ãªããžã§ã¯ããšããŠååŸã§ããŸãããã®ããã«ã¯ã Jii.sql.ActiveQuery.asArrayïŒïŒã¡ãœãããåŒã³åºãå¿ èŠããããŸãã
å®éãJavaScriptã§ã¯ããªããžã§ã¯ãã§æºããããé åãååŸããŸãã ãããã£ãŠã asObjectïŒïŒã¡ãœãããåŒã³åºãæ¹ãããé©åã§ããããã®ãããªã¡ãœããïŒå矩èªïŒããããŸãã ããããYii 2 APIãä¿åããããã«ã asArrayïŒïŒã¡ãœããã¯æ®ãããŠããŸãã
// , // app.models.Customer.find() .asArray() // alias is asObject() .all() .then(function(customers) { // ... });
ããŒã¿ä¿å
Active Recordã䜿çšããŠã次ã®æé ã«åŸã£ãŠããŒã¿ããŒã¹ã«ããŒã¿ãä¿åã§ããŸãã
- Active Recordã®ã€ã³ã¹ã¿ã³ã¹ãååŸãŸãã¯äœæããŸãã
- å±æ§ã«æ°ããå€ãèšå®ãã
- Jii.sql.ActiveRecord.saveïŒïŒã¡ãœãããåŒã³åºããŠããŒã¿ãä¿åããŸãã
äŸãã°
// var customer = new app.models.Customer(); customer.set('name', 'James'); customer.set('email', 'james@example.com'); customer.save().then(function(success) { return app.models.Customer.findOne(123); }).then(function(customer) { // customer.set('email', 'james@newexample.com'); return customer.save(); }).then(function(success) { // ... });
Jii.sql.ActiveRecord.saveïŒïŒã¡ãœããã¯ãã¢ã¯ãã£ãã¬ã³ãŒãã®ç¶æ ã«å¿ããŠãè¡ããŒã¿ãè¿œå ãŸãã¯æŽæ°ã§ããŸãã ã€ã³ã¹ã¿ã³ã¹ããnewãæŒç®åã䜿çšããŠäœæãããå Žåãã¡ãœããã¯æ°ããè¡ãè¿œå ããŸãã ã€ã³ã¹ã¿ã³ã¹ãfindïŒïŒã¡ãœãããä»ããŠååŸãããããã«é¡äŒŒããŠããå ŽåããŸãã¯saveïŒïŒã¡ãœããã以åã«åŒã³åºãããå Žåã saveïŒïŒã¡ãœãã
ããŒã¿ãæŽæ°ããŸãã
ããŒã¿æ€èšŒ
Jii.sql.ActiveRecordã¯ã©ã¹ã¯Jii.base.Modelãç¶æ¿ããŠãããããããŒã¿æ€èšŒã䜿çšã§ããŸãã Jii.sql.ActiveRecord.rulesïŒïŒã¡ãœããããªãŒããŒã©ã€ãããŠå®è£ ã«ãŒã«ãèšå®ãã Jii.sql.ActiveRecord.validateïŒïŒã¡ãœãããä»ããŠå€ãæ£ããããšã確èªã§ããŸãã
Jii.sql.ActiveRecord.saveïŒïŒã¡ãœãããåŒã³åºããšãããã©ã«ãã§ã Jii.sql.ActiveRecord.validateïŒïŒã¡ãœãããèªåçã«åŒã³åºãããŸãã æ€èšŒæžã¿ã®ããŒã¿ã®ã¿ãããŒã¿ããŒã¹ã«ä¿åããå¿ èŠããããŸãã ããŒã¿ãæ£ãããªãå Žåãã¡ãœããã¯ã false ããè¿ãã Jii.sql.ActiveRecord.getErrorsïŒïŒã¡ãœãããªã©ãéããŠãšã©ãŒãåãåãå ŽåããããŸãã
è€æ°ã®å±æ§ãå€æŽãã
éåžžã®ã¢ãã«ãšåæ§ã«ãActive Recordã€ã³ã¹ã¿ã³ã¹ã¯ãªããžã§ã¯ã転éã«ããå±æ§ã®å€æŽããµããŒãããŠããŸãã ãã®ã¡ãœããã䜿çšãããšã1ã€ã®ã¡ãœãããåŒã³åºãããšã«ãããè€æ°ã®ã¢ã¯ãã£ãã¬ã³ãŒãå±æ§ã®å€ãå²ãåœãŠãããšãã§ããŸãã å®å šãªå±æ§ã®ã¿ã倧èŠæš¡ã«å²ãåœãŠãããšãã§ããããšã«æ³šæããŠãã ããã
var values = { name: 'James', email: 'james@example.com' }; var customer = new app.models.Customer(); customer.setAttributes(values); customer.save();
å€æŽãããå±æ§
Jii.sql.ActiveRecord.saveïŒïŒã¡ãœãããåŒã³åºããšãå€æŽãããActive Recordå±æ§ã®ã¿ãä¿åãããŸãã å€ãå€æŽãããå Žåãå±æ§ã¯å€æŽããããšèŠãªãããŸãã å€æŽãããå±æ§ã®ååšã«é¢ä¿ãªããããŒã¿æ€èšŒãå®è¡ãããããšã«æ³šæããŠãã ããã
Active Recordã¯ãå€æŽãããå±æ§ã®ãªã¹ããèªåçã«ä¿åããŸãã å€ãããŒãžã§ã³ã®å±æ§ãä¿åããææ°ããŒãžã§ã³ãšæ¯èŒããŸãã å€æŽãããå±æ§ãååŸããã«ã¯ã Jii.sql.ActiveRecord.getDirtyAttributesïŒïŒã¡ãœããã䜿çšããŸãã
å€ãå±æ§å€ãååŸããã«ã¯ã Jii.sql.ActiveRecord.getOldAttributesïŒïŒãŸãã¯Jii.sql.ActiveRecord.getOldAttributeïŒïŒã¡ãœãããåŒã³åºããŸãã
ããã©ã«ãå€
ããŒãã«ã®äžéšã®åã«ã¯ãããŒã¿ããŒã¹ã§å®çŸ©ãããããã©ã«ãå€ãå«ãŸããŠããå ŽåããããŸãã Jii.sql.ActiveRecord.loadDefaultValuesïŒïŒã¡ãœãããåŒã³åºãããšã«ããããããã®å€ãActive Recordã«äºåå ¥åã§ããŸãã ãã®æ¹æ³ã¯åæçã§ã ããŒã¿ããŒã¹ã¹ããŒãã¯ãæ¥ç¶ãéããããšãã«ããªããŒããããŸãã
var customer = new app.models.Customer(); customer.loadDefaultValues(); // customer.get('xyz') `xyz` - `xyz`.
è€æ°ã®è¡ãæŽæ°ãã
äžèšã®ã¡ãœããã¯ãActive Recordã€ã³ã¹ã¿ã³ã¹ã§æ©èœããŸãã è€æ°ã®è¡ãäžåºŠã«æŽæ°ããã«ã¯ãéçãªJii.sql.ActiveRecord.updateAllïŒïŒã¡ãœãããåŒã³åºããŸãã
// UPDATE `customer` SET `status` = 1 WHERE `email` LIKE `%@example.com%` app.models.Customer.updateAll({status: app.models.Customer.STATUS_ACTIVE}, {'like', 'email', '@example.com'});
ããŒã¿åé€
ããŒãã«ããè¡ãåé€ããã«ã¯ããã®è¡ã«å¯Ÿå¿ããActive Recordã€ã³ã¹ã¿ã³ã¹ã§Jii.sql.ActiveRecord.deleteïŒïŒã¡ãœãããåŒã³åºãå¿ èŠããããŸãã
app.models.Customer .findOne(123) .then(function(customer) { customer.delete(); });
éçã¡ãœããJii.sql.ActiveRecord.deleteAllïŒïŒãåŒã³åºããŠãæ¡ä»¶ããšã«å€ãã®è¡ãåé€ã§ããŸãã
äŸãã°
app.models.Customer.deleteAll({status: app.models.Customer.STATUS_INACTIVE});
é¢é£ããŒã¿ãæäœãã
Active Recordã¯ãåã ã®ããŒã¿ããŒã¹ããŒãã«ã§ã®äœæ¥ã«å ããŠããã©ã€ããªããŒã¿ãä»ããŠããŒã¿ããªã³ã¯ã§ããŸãã ããšãã°ã顧客ããŒã¿ã泚æã«é¢é£ä»ããããšãã§ããŸãã Active Recordã§å¯Ÿå¿ããæ¥ç¶ââã宣èšãããšãåŒãcustomer.loadïŒ 'orders'ïŒãã䜿çšããŠé¡§å®¢æ³šæã«é¢ããæ å ±ãååŸã§ããåºåã§ã¯ãapp.models.Orderãã®ã€ã³ã¹ã¿ã³ã¹ã®é åãååŸã§ããŸãã
äŸåé¢ä¿ã®å®£èš
Active Recordã䜿çšããŠãªã¬ãŒã·ã§ãã«ããŒã¿ãæäœããã«ã¯ãæåã«Active Recordã¯ã©ã¹ã§ãªã¬ãŒã·ã§ã³ã宣èšããå¿ èŠããããŸãã äŸãã°
/** * @class app.models.Customer * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Customer', /** @lends app.models.Customer.prototype */{ // ... getOrders: function() { return this.hasMany(app.models.Order.className(), {customer_id: 'id'}); } }); /** * @class app.models.Order * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Order', /** @lends app.models.Order.prototype */{ // ... getCustomer: function() { return this.hasOne(app.models.Customer.className(), {id: 'customer_id'}); } });
äžèšã®ã³ãŒãã§ã¯ãã¯ã©ã¹ `app.models.Customer`ã«å¯ŸããŠãªã¬ãŒã·ã§ã³` orders`ããã¯ã©ã¹ `app.models.Order`ã«å¯ŸããŠãªã¬ãŒã·ã§ã³` customer`ã宣èšããŸããã
åãªã¬ãŒã·ã§ã³ã¡ãœããã¯ã `getXyz`ïŒget +å°æåã®æåã®æåã§ãªã¬ãŒã·ã§ã³ã®ååïŒãšããŠååãä»ããå¿ èŠããããŸãã ãªã¬ãŒã·ã§ã³ã·ããåã¯*倧æåãšå°æåãåºå¥ããããšã«æ³šæããŠãã ãã*ã
é¢é£ããŠã次ã®æ å ±ãæäŸããå¿ èŠããããŸãã
- éä¿¡ã®å€éåºŠïŒ Jii.sql.ActiveRecord.hasManyïŒïŒãŸãã¯Jii.sql.ActiveRecord.hasOneïŒïŒã¡ãœãããåŒã³åºããšãã«æå®ãããŸãã äžèšã®äŸã§ã¯ã顧客ã«ã¯å€æ°ã®æ³šæãããã泚æã«ã¯é¡§å®¢ã1人ããããŸããã
- é¢é£ä»ããããã¯ã©ã¹Active RecordïŒã®ååã¯ãäžèšã®ã¡ãœããã®æåã®ãã©ã¡ãŒã¿ãŒãšããŠç€ºãããŸãã `Xyz.classNameïŒïŒ`ãä»ããŠã¯ã©ã¹åãååŸãããŸãé¢ä¿ãæ§ç¯ãã段éã§ã¯ã©ã¹ã®ååšã確èªãã次ã«IDEãæžã蟌ã¿æã«ã¯ã©ã¹åãéç¥ããããšããå§ãããŸãã
- 2ã€ã®ããŒãã«ã¹ããŒãéã®é¢ä¿ïŒ2ã€ã®ããŒã¿åããªã³ã¯ãããåãå®çŸ©ããŸãã ãªããžã§ã¯ãå€ã¯ãã©ã€ããªããŒã¿åã§ãããããŒã¯é¢é£ããŒã¿åã§ãã
é¢é£ããŒã¿ãžã®ã¢ã¯ã»ã¹
é¢ä¿ã宣èšããåŸãé¢ä¿ã®ååã䜿çšããŠé¢é£ããŒã¿ã«ã¢ã¯ã»ã¹ã§ããŸãã é¢é£ããŒã¿ããã§ã«ã¢ã¯ãã£ãã¬ã³ãŒãã«ããŒããããŠããããšã確å®ãªå Žåã¯ã getïŒïŒã¡ãœãããä»ããŠãªããžã§ã¯ãã®ããããã£ã«ã¢ã¯ã»ã¹ããã®ãšåãæ¹æ³ã§é¢é£ã¢ã¯ãã£ãã¬ã³ãŒããååŸã§ããŸãã ãã以å€ã®å Žåã¯ã Jii.sql.ActiveRecord.loadïŒïŒã¡ãœããã䜿çšããŠé¢é£ããŒã¿ãããŒãããããšããå§ãããŸããããã«ãããåžžã« `Promise`ãªããžã§ã¯ããè¿ãããŸãããæ¥ç¶ã以åã«ããŒããããŠããå Žåã¯è¿œå ã®ãªã¯ãšã¹ãã¯ããŒã¿ããŒã¹ã«éä¿¡ãããŸããã
// SELECT * FROM `customer` WHERE `id` = 123 app.models.Customer .findOne(123) .then(function(customer) { // SELECT * FROM `order` WHERE `customer_id` = 123 return customer.load('orders'); }) .then(function(orders) { // orders - `app.models.Order` });
ãªã¬ãŒã·ã§ã³ãJii.sql.ActiveRecord.hasManyïŒïŒã¡ãœããã«ãã£ãŠå®£èšãããŠããå Žåããããã®ãªã¬ãŒã·ã§ã³ã¯Active Recordã€ã³ã¹ã¿ã³ã¹ã®é åïŒãŸãã¯ç©ºã®é åïŒã§è¡šãããŸãã Jii.sql.ActiveRecord.hasOneïŒïŒã¡ãœããã®å Žåããããã®ãªã¬ãŒã·ã§ã³ã¯Active Recordã€ã³ã¹ã¿ã³ã¹ãŸãã¯ããŒã¿ãå©çšã§ããªãå Žåã¯ãnullãã«ãã£ãŠè¡šãããŸãã
åããŠãªã¬ãŒã·ã§ã³ã«ã¢ã¯ã»ã¹ãããšãäžèšã®äŸã«ç€ºãããã«ãããŒã¿ããŒã¹ã§SQLã¯ãšãªãå®è¡ãããŸãã ç¹°ãè¿ãã®ç°è°ç³ãç«ãŠã§ã¯ããªã¯ãšã¹ãã¯å®è¡ãããŸããã
è¿œå ã®ããŒãã«ïŒãžã£ã³ã¯ã·ã§ã³ããŒãã«ïŒãä»ãããªã¬ãŒã·ã§ã³
ããŒã¿ããŒã¹ãã¢ãã«åãããšãã«ã2ã€ã®å€å¯Ÿå€ããŒãã«éã«ãªã¬ãŒã·ã§ã³ã·ãããããå Žåãéåžžãè¿œå ã®ããŒãã«- ãžã£ã³ã¯ã·ã§ã³ããŒãã«ãè¿œå ãããŸãã ããšãã°ãããŒãã«ãorderããšããŒãã«ãitemãã¯ãããŒãã«ãorder_itemãã䜿çšããŠãªã³ã¯ã§ããŸãã
ãã®ãããªé¢ä¿ã宣èšãããšãã¯ãè¿œå ã®ããŒãã«ã§Jii.sql.ActiveQuery.viaïŒïŒãŸãã¯Jii.sql.ActiveQuery.viaTableïŒïŒã¡ãœãããåŒã³åºãå¿ èŠããããŸãã ãããã®æ¹æ³ã®éãã¯ãåè ã¯çŸåšã®é¢ä¿åã®èŠ³ç¹ããé·ç§»è¡šã瀺ãã®ã«å¯ŸããåŸè ã¯è¡šãçŽæ¥è£å®ããããšã§ãã äŸãã°
/** * @class app.models.Order * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Order', /** @lends app.models.Order.prototype */{ // ... getItems: function() { return this.hasMany(app.models.Item.className(), {id: 'item_id'}) .viaTable('order_item', {order_id: 'id'}); } });
ãŸãã¯ä»£ããã«
/** * @class app.models.Order * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Order', /** @lends app.models.Order.prototype */{ // ... getOrderItems: function() { return this.hasMany(app.models.OrderItem.className(), {order_id: 'id'}); }, getItems: function() { return this.hasMany(app.models.Item.className(), {id: 'item_id'}) .via('orderItems'); } });
è¿œå ã®ããŒãã«ã§å®£èšãããé¢ä¿ã®äœ¿çšã¯ãéåžžã®é¢ä¿ã«äŒŒãŠããŸãã äŸãã°
// SELECT * FROM `order` WHERE `id` = 100 app.models.Order .findOne(100) .then(function(order) { // SELECT * FROM `order_item` WHERE `order_id` = 100 // SELECT * FROM `item` WHERE `item_id` IN (...) return order.load('items'); }) .then(function(items) { // items - `app.models.Item` });
é 延èªã¿èŸŒã¿ãšè²ªæ¬²ãªèªã¿èŸŒã¿
é¢é£ããŒã¿ã¢ã¯ã»ã¹ã»ã¯ã·ã§ã³ã§ã¯ã getïŒïŒãŸãã¯loadïŒïŒã¡ãœããã䜿çšããŠActive Recordãããªã¬ãŒã·ã§ã³ã«ã¢ã¯ã»ã¹ããæ¹æ³ã«ã€ããŠèª¬æããŸããã SQLã¯ãšãªã¯ãé¢é£ä»ããããããŒã¿ã«æåã«ã¢ã¯ã»ã¹ãããšãã«ã®ã¿ããŒã¿ããŒã¹ã«éä¿¡ãããŸãã ãã®ãããªããŒã¿ã®èªã¿èŸŒã¿æ¹æ³ã¯ãé 延èªã¿èŸŒã¿ãšåŒã°ããŸãã
äŸãã°
// SELECT * FROM `customer` WHERE `id` = 123 app.models.Customer .findOne(123) .then(function(customer) { // SELECT * FROM `order` WHERE `customer_id` = 123 customer.load('orders').then(function(orders) { // SQL return customer.load('orders'); }).then(function(orders2) { // , <i>get()</i>. var orders3 = customer.get('orders'); }); });
é 延ããŒãã¯éåžžã«äŸ¿å©ã«äœ¿çšã§ããŸãã ãã ããActive Recordã®è€æ°ã®ã€ã³ã¹ã¿ã³ã¹ã®é¢é£ã¬ã³ãŒãã«ã¢ã¯ã»ã¹ããå¿ èŠãããå Žåãããã¯ããã©ãŒãã³ã¹ã®åé¡ãåŒãèµ·ããå¯èœæ§ããããŸãã 次ã®ã³ãŒãäŸãèããŠã¿ãŠãã ãããããã€ã®SQLã¯ãšãªãå®è¡ãããŸããïŒ
// SELECT * FROM `customer` LIMIT 100 app.models.Customer.find() .limit(100) .all() .then(function(customers) { return Promise.all(customers.map(function(customer) { // SELECT * FROM `order` WHERE `customer_id` = ... return customer.load('orders'); })); }).then(function(result) { var firstOrder = result[0][0]; // ... });
ãã®äŸã§ã¯ã101åã®SQLã¯ãšãªãå®è¡ãããŸãïŒ ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ããšã«åå¥ã®ãªã¯ãšã¹ããåä¿¡ããããã§ãã ãã®ããã©ãŒãã³ã¹ã®åé¡ã解決ããã«ã¯ã以äžã«ç€ºã*欲匵ã*ã¢ãããŒãã䜿çšã§ããŸãã
// SELECT * FROM `customer` LIMIT 100; // SELECT * FROM `orders` WHERE `customer_id` IN (...) app.models.Customer.find() .with('orders') .limit(100) .all() .then(function(customers) { customers.forEach(function(customer) { // SQL var orders = customer.get('orders'); }); });
ãã¹ã¿ãŒã¬ã³ãŒããšãšãã«1ã€ä»¥äžã®é¢ä¿ãã¢ããããŒãã§ããŸãã ããã«ãã¹ããããé¢ä¿ãã¢ããããŒãããããšãã§ããŸãã ããšãã°ããapps.models.Customerãããordersããšããé¢ä¿ãéããŠãapp.models.Orderãã«é¢é£ä»ãããããapp.models.OrderãããitemsããããItemãã«é¢é£ä»ããããŠããå Žåã§ãã `app.models.Customer`ããªã¯ãšã¹ããããšãã withïŒïŒã¡ãœãã㧠` orders.items`ãæå®ããããšã§ãããã« `items`ãªã¬ãŒã·ã§ã³ãããŒãã§ããŸãã
次ã®ã³ãŒãã¯ã Jii.sql.ActiveQuery.withïŒïŒã®ããŸããŸãªäœ¿çšæ³ã瀺ããŠããŸãã ã¯ã©ã¹ `app.models.Customer`ã«ã¯` orders`ãš `country`ã®2ã€ã®é¢ä¿ããããã¯ã©ã¹` app.models.Order`ã«ã¯ `items`ã®é¢ä¿ããããšä»®å®ããŸãã
// "orders" "country" app.models.Customer.find() .with('orders', 'country') .all() .then(function(customers) { // ... }); // app.models.Customer.find() .with(['orders', 'country']) .all() .then(function(customers) { // SQL var orders = customers[0].get('orders'); var country = customers[0].get('country'); }); // "orders" "orders.items" app.models.Customer.find() .with('orders.items') .all() .then(function(customers) { // // SQL var items = customers[0].get('orders')[0].get('items'); });
ãabcdããªã©ã®åŒ·å¶çã«ãã¹ããããé¢ä¿ãããŒãã§ããŸãã ãã¹ãŠã®èŠªé¢ä¿ã匷å¶çã«ããŒããããŸãã
é¢ä¿ã貪欲ã«ããŒãããå Žåãå¿åé¢æ°ãæž¡ãããšã«ããã察å¿ãããªã¯ãšã¹ããã«ã¹ã¿ãã€ãºã§ããŸãã äŸãã°
// // SELECT * FROM `customer` // SELECT * FROM `country` WHERE `id` IN (...) // SELECT * FROM `order` WHERE `customer_id` IN (...) AND `status` = 1 app.models.Customer.find() .with({ country: 'country', orders: function (query) { query.andWhere({'status': app.models.Order.STATUS_ACTIVE}); } }) .all() .then(function(customers) { // ... });
éä¿¡çšã®ãªã¬ãŒã·ã§ãã«ã¯ãšãªãèšå®ããå Žåããªããžã§ã¯ãã®ããŒãšããŠãªã¬ãŒã·ã§ã³ã·ããã®ååãæå®ãã察å¿ãããªããžã§ã¯ãã®å€ãšããŠå¿åé¢æ°ã䜿çšããå¿ èŠããããŸãã å¿åé¢æ°ã®æåã®åŒæ°ã¯ã Jii.sql.ActiveQueryãªããžã§ã¯ãã§ããã¯ãšãªãã©ã¡ãŒã¿ãŒã«ãªããŸãã äžèšã®äŸã§ã¯ã泚æã®ã¹ããŒã¿ã¹ã«è¿œå ã®æ¡ä»¶ãè¿œå ããŠãªã¯ãšã¹ããå€æŽããŸãã
éé¢ä¿
Active Recordã¯ã©ã¹éã®é¢ä¿ã¯ããã°ãã°äºãã«éã®é¢ä¿ã«ãããŸãã ããšãã°ãã¯ã©ã¹ãapp.models.Customerãã¯ãªã¬ãŒã·ã§ã³ãordersããä»ããŠãapp.models.Orderãã«ãªã³ã¯ãããã¯ã©ã¹ãapp.models.Orderãã¯ãªã¬ãŒã·ã§ã³ã·ãããcustomerããä»ããŠã¯ã©ã¹ãapp.models.Customerãã«ãªã³ã¯ãããŸãã
/** * @class app.models.Customer * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Customer', /** @lends app.models.Customer.prototype */{ // ... getOrders: function() { return this.hasMany(app.models.Order.className(), {customer_id: 'id'}); } }); /** * @class app.models.Order * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Order', /** @lends app.models.Order.prototype */{ // ... getCustomer: function() { return this.hasOne(app.models.Customer.className(), {id: 'customer_id'}); } });
次ã«ã次ã®ã³ãŒãã¹ããããã«ã€ããŠèããŸãã
// SELECT * FROM `customer` WHERE `id` = 123 app.models.Customer .findOne(123) .then(function(customer) { // SELECT * FROM `order` WHERE `customer_id` = 123 return customer.load('orders'); }).then(function(orders) { var order = orders[0]; // SELECT * FROM `customer` WHERE `id` = 123 return order.load('customer'); }).then(function(customer2) { // "not the same" console.log(customer2 === customer ? 'same' : 'not the same'); });
ãcustomerããªããžã§ã¯ããšãcustomer2ããªããžã§ã¯ãã¯åãã§ãããšæ³å®ããŠããŸãããå®éã«ã¯ããã§ã¯ãããŸããããããã¯ç°ãªãã€ã³ã¹ã¿ã³ã¹ã§åãããŒã¿ãå«ãã§ããŸãããorder.customerãã«ã¢ã¯ã»ã¹ãããšãè¿œå ã®SQLã¯ãšãªãå®è¡ãããæ°ãããªããžã§ã¯ããcustomer2ããååŸãããŸãã
äžèšã®äŸã§æåŸã®SQLã¯ãšãªã®åé·ãªå®è¡ãé¿ããããã«ãJii.sql.ActiveQuery.inverseOfïŒïŒã¡ãœããã䜿çšããŠã `customer`ã* ordersã«*éã«äŸå*ããããšã瀺ãå¿ èŠããããŸãã
/** * @class app.models.Customer * @extends Jii.sql.ActiveRecord */ Jii.defineClass('app.models.Customer', /** @lends app.models.Customer.prototype */{ // ... getOrders: function() { return this.hasMany(app.models.Order.className(), {customer_id: 'id'}).inverseOf('customer'); } });
ãããã®å€æŽåŸã以äžãåãåããŸãã
// SELECT * FROM `customer` WHERE `id` = 123 app.models.Customer .findOne(123) .then(function(customer) { // SELECT * FROM `order` WHERE `customer_id` = 123 return customer.load('orders'); }).then(function(orders) { var order = orders[0]; // SELECT * FROM `customer` WHERE `id` = 123 return order.load('customer'); }).then(function(customer2) { // "same" console.log(customer2 === customer ? 'same' : 'not the same'); });
泚ïŒãªãã·ã§ã³ã®ãžã£ã³ã¯ã·ã§ã³ããŒãã«ã§å®£èšãããå€å¯Ÿå€ãªã¬ãŒã·ã§ã³ã·ããã§ã¯ãéãªã¬ãŒã·ã§ã³ã·ããã¯æ©èœããŸããã
äŸåé¢ä¿ã®ä¿å
ãªã¬ãŒã·ã§ãã«ããŒã¿ã䜿çšããå Žåãå€ãã®å Žåãç°ãªãããŒã¿éã«ãªã¬ãŒã·ã§ã³ã·ãããè¿œå ããããæ¢åã®ãªã¬ãŒã·ã§ã³ã·ãããåé€ããå¿ èŠããããŸãããããè¡ãã«ã¯ãé¢ä¿ãå®çŸ©ããåã«æ£ããå€ãèšå®ããŸããActive Recordã䜿çšãããšã次ã®ãããªããšãã§ããŸãã
app.models.Customer .findOne(123) .then(function(customer) { var order = new app.models.Order(); order.subtotal = 100; // ... // , "customer" `app.models.Order` . order.customer_id = customer.id; order.save(); });
Active Recordã¯Jii.sql.ActiveRecord.linkïŒïŒã¡ãœãããæäŸããŸããããã«ãããããããããšã¬ã¬ã³ãã«è¡ãããšãã§ããŸãã
app.models.Customer .findOne(123) .then(function(customer) { var order = new app.models.Order(); order.subtotal = 100; // ... order.link('customer', customer); });
Jii.sql.ActiveRecord.linkïŒïŒã¡ãœããã¯ããªã¬ãŒã·ã§ã³ã·ããã®ååãšãã¬ã³ãŒããæ¥ç¶ãããã¢ã¯ãã£ãã¬ã³ãŒãã€ã³ã¹ã¿ã³ã¹ãäºæããŸãããã®ã¡ãœããã¯ãã¢ã¯ãã£ãã¬ã³ãŒãã®2ã€ã®ã€ã³ã¹ã¿ã³ã¹ãæ¥ç¶ããããããããŒã¿ããŒã¹ã«ä¿åããŸããäžèšã®äŸã§ã¯ã `customer_id`å±æ§ã` app.models.Order`ã«èšå®ããŸãã
泚ïŒæ°ããäœæããã2ã€ã®Active Recordã€ã³ã¹ã¿ã³ã¹ããªã³ã¯ããããšã¯ã§ããŸããã
Jii.sql.ActiveRecord.linkïŒïŒã¡ãœããã䜿çšããå©ç¹ã¯ãè¿œå ã®ããŒãã«ã䜿çšããŠãªã¬ãŒã·ã§ã³ã·ããã決å®ããããšããã«æçœã«ãªããŸããããšãã°ã次ã®ã³ãŒãã䜿çšããŠããapp.models.Orderãã®ã€ã³ã¹ã¿ã³ã¹ããapp.models.Itemãã«é¢é£ä»ããããšãã§ããŸãã
order.link('items', item);
ãã®ã³ãŒãã¯ãããŒãã« `order_item`ã«è¡ãèªåçã«è¿œå ããŠãªã³ã¯ãäœæããŸãã
Active Recordã®2ã€ã®ã€ã³ã¹ã¿ã³ã¹ã®ãªã³ã¯ã解é€ããã«ã¯ãJii.sql.ActiveRecord.unlinkïŒïŒ| unlinkïŒïŒã¡ãœããã䜿çšããŸãã
äŸãã°
app.models.Customer.find() .with('orders') .all() .then(function(customer) { customer.unlink('orders', customer.get('orders')[0]); });
ããã©ã«ãã§ã¯ãJii.sql.ActiveRecord.unlinkïŒïŒã¡ãœããã¯ãªã¬ãŒã·ã§ã³ãæå®ããããŒã®å€ããnullãã«èšå®ããŸãããã ããããŒãã«ããè¡ãåé€ããã«ã¯ããisDeleteããã©ã¡ãŒã¿ãŒããtrueããšããŠæž¡ãããšãã§ããŸãã
çµè«ãšããŠ
çŸæç¹ã§ã¯ããã©ã³ã¶ã¯ã·ã§ã³ã¯Jiiã®Active Recordã«å®è£ ãããŠããŸããããã®ããšã¯å¿ èŠã§ããããããã£ãŠãä»åŸè¡šç€ºãããã§ããããåã®èšäºã§
è¿°ã¹ãããã«ãJiiã¯ãªãŒãã³ãœãŒã¹ãããžã§ã¯ãã§ãã®ã§ã誰ããJiiã®éçºã«åå ããŠãããããšãŠãå¬ããã§ããaffka@affka.ruã«æžã蟌ã¿ãŸãããŠã§ããµã€ãã®ãã¬ãŒã ã¯ãŒã¯- jiiframework.ru GitHubã®- github.com/jiisoft
èšäºã®ããã²ãŒã·ã§ã³