Practical symfony 6 дахь өдөр More with the Model (орчуулсан: Ариунсүлд)

Ариунсүлд -д маш их баярлалаа.  6 дахь өдрийг орчуулсан байна. email: (Ariunsuld_sh@e-map.mn).

Санал: Өөр орчуулах хүсэлтэй мөн орчуулж байгаа хүмүүс байвал erheme318@yahoo.com or erheme318@gmail.com рүү mail илгээгээрэй. Давхардаж орчуулахгүй байх үүднээс орчуулж эхэлсэн бол  ямар  нэгэн байдлаар бие биедээ мэдэгдэж байвал сайн байна.

За ингээд Ариунсүрэнгийн орчуулснаар өнөөдрийн хичээлээ үзээрэй.

More with the Model
Өчигдөр гайхалтай байсан. URL-ийг яаж цэвэрхэн болгох болон symphony
framework-ийн автоматар үүсгэдэг олон зүйлийн талаар үзсэн.
Өнөөдөр бид Jobeet вэбсайтаа кодоор өөрчлөх тухай үзнэ. Үүний тулд эхний 5
өдөр тайлбарласан дадлагын ажлуудтай үзэж танилцсан байх шаардлагатай.

The Doctrine Query Object
Хоёрдахь өдрийн хичээлээс үзсэн байх шаардлагатай зүйлс:
“Jobeet вэбсайт нэвтэрсэн хэрэглэгчид идэвхитэй ажлын байрны жагсаалтыг
харуулна”. Гэвч одоо идэвхитэй идэвхигүй бүх ажлын байрны жагсаалтыг харуулж
байна.
// apps/frontend/modules/job/actions/actions.class.php
class jobActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
$this->jobeet_jobs = Doctrine::getTable(‘JobeetJob’)
->createQuery(‘a’)
->execute();
}
// …
}
$q = Doctrine_Query::create()
->from(‘JobeetJob j’)
->where(‘j.created_at > ?’,
date(‘Y-m-d H:i:s’, time() – 86400 * 30));
$this->jobeet_jobs = $q->execute();
}

Debugging Doctrine generated SQL
Хэдийгээр та SQL илэрхийлэл гараар бичээгүй боловч Doctrine нь Database
engine болон SQL илэрхийллийн тохиргоог ялган хэрэгжүүлж байгааг 3 дахь өдөр
үзсэн. Гэвч зарим тохиолдолд SQL-ийг Doctrine-аар үүсгэх нь илүү дээр байдаг.
Жишээлбэл: query хүлээгдэж буй үед debug нь ажиллахгүй хүлээдэг. Dev орчинд
symphony-ийн эдгээр query-нүүд log/ хавтсанд байрладаг.Энд frontend_dev.log
нэртэй ганц лог файл бүх програм (application) болон орчин (environment)-ийн
боловсруулалтыг зохицуулж байдаг.
# log/frontend_dev.log
Dec 04 13:58:33 symfony [info] {sfDoctrineLogger} executeQuery : SELECT
j.id AS j__id, j.category_id AS j__category_id, j.type AS j__type,
j.company AS j__company, j.logo AS j__logo, j.url AS j__url,
j.position AS j__position, j.location AS j__location,
j.description AS j__description, j.how_to_apply AS j__how_to_apply,
j.token AS j__token, j.is_public AS j__is_public,
j.is_activated AS j__is_activated, j.email AS j__email,
j.expires_at AS j__expires_at, j.created_at AS j__created_at,
j.updated_at AS j__updated_at FROM jobeet_job j
WHERE j.created_at > ? (2008-11-08 01:13:35
Doctrine-д created_at багана байсныг анзаарсан байх (WHERE j.created_at > ?).
Query-д орсон ? тэмдэгт мөр нь Doctrine-д илэрхийлэл үүсгэхэд тусладаг. Яг
үнэндээ ?-ын утга нь (‘2008-11-08 01:13:35’ гэсэн жишээнд) query гүйцэтгэл болон
database engine-ийг ажиллуулна. Бэлтгэсэн илэрхийллийг хэрэглэснээр SQL injection1
дайралтаас хамгаална.
Энэ сайн боловч хэрэглэгч браузер солиход бага зэрэг асуудал тулгардаг. IDE-д
log файл нь чамд тестийг өөрчлөхөд байнга шаардагдана. Symfony-ийн web debug
toolbar нь хэрэгцээт, боломжит бүх зүйлийг браузерт нь гаргана.


Object Serialization
Хэдийгээр дан кодоор (автоматаар үүсгэлгүй) ажиллуулж болох боловч энэ нь 2
дахь өдөр тодорхойлсон эрхийн зарим асуудал дээр бүрэн болж чадахгүй.
“Хэрэглэгч эрхээ дахин сэргээх болон оруулсан ажлын байрны мэдээллээ 30
хоног сунгах боломжтой…”
Гэвч үүнийг created_at –ын утга мэдээлэл оруулсан өдрийг агуулж байгаа тул
найдаж болох ба бид өөрийн санаанд нийцүүлэн өөрчлөх боломжгүй.
Хэрэв та бидний 3 дахь өдөр тодорхойлсон database schema-г санаж байгаа бол
бид expires_at багана тодорхойлсон. Одоогоор түүний утга байнга хоосон байгаа
ба утгыг ашиглахгүй байна. Гэвч ажлын байр үүсгэхэд энэ нь автоматаар
үүсгэснээс хойш 30 дахь өдрийг авна.
Та өгөгдлийг Doctrine-ны тусламжтайгаар автоматаар үүсгэсэн байсан бол
save()-аар өгөгдлийг шинэчилж болно:
// lib/model/doctrine/JobeetJob.class.php
class JobeetJob extends BaseJobeetJob
{
public function save(Doctrine_Connection $conn = null)
{
if ($this->isNew() && !$this->getExpiresAt())
{
$now = $this->getCreatedAt() ?
$this->getDateTimeObject(‘created_at’)->format(‘U’) : time();
$this->setExpiresAt(date(‘Y-m-d H:i:s’, $now + 86400 * 30));
}
return parent::save($conn);
}
// …
1 http://en.wikipedia.org/wiki/Sql_injection

}
isNew() method нь объект тодорхойлогдоогүй үед true (үнэн) утга буцаах ба
бусад үед false (худал) утга буцаана.
Одоо created_at-ийн утгыг expires_at-ийн утгаар сольж ашиглая.
public function executeIndex(sfWebRequest $request)
{
$q = Doctrine_Query::create()
->from(‘JobeetJob j’)
->where(‘j.expires_at > ?’, date(‘Y-m-d H:i:s’, time()));
$this->jobeet_jobs = $q->execute();
}
Бид query-ийг ажил сонгохоор хязгаарлан expires_at-ийг огноонд ашиглав.
More with Fixtures
Jobeet үндсэн хуудсыг вэб хөтлөгч өгөгдлийн санд өөрчлөлт хийж чадахгүй
бөгөөд зөвхөн өгөгдлийн сан дахь өгөгдлүүдийг л нийтэлнэ. Дараахи кодоор
хугацаа дууссан ажлын байрны мэдээллүүдийг сольё.
# data/fixtures/jobs.yml
JobeetJob:
# other jobs
expired_job:
JobeetCategory: programming
company: Sensio Labs
position: Web Developer
location: Paris, France
description: Lorem ipsum dolor sit amet, consectetur adipisicing elit.
how_to_apply: Send your resume to lorem.ipsum [at] dolor.sit
is_public: true
is_activated: true
created_at: ‘2005-12-01 00:00:00’
token: job_expired
email: job@example.com
Кодыг хуулахдаа догол мөрүүдийг алдалгүй (зөвхөн хоосон зай дэмжих ба кодын
мөрийн эх, мөрийн эхнээс авсан зайг алдалгүй) болгоомжтой хуулаарай. Үүнээс өмнө
expired_job мөр нь зөвхөн хоёр хоосон зай л авсан байна.
Fixture файлын мэдээллийг засварлаж, зөв тодорхойлбол created_at-ын утгыг
Doctrine автоматаар дүүргэнэ. Бидний тодорхойлсон нь анхдагч default утга.
Fixture-ыг дахин уншиж, вэб браузерийг дахин ачаалснаар (refresh) хуучин ажлын
байрны мэдээллүүдийг харахгүйг баталгаажуулна.
$ php symfony doctrine:data-load
Доорхи query нь created_at-д байгаа save() method-ор expires_at баганыг
автоматаар дүүргэнэ.
SELECT `position`, `created_at`, `expires_at` FROM `jobeet_job`;
Custom Configuration
JobeetJob::save() method-д ажлын байрны мэдээллийн хаагдах өдөр нь хатуу
зоогдож өгсөн байдаг. Үүнээс гадна 30 хоног сунгах боломжтой байна. Symfony
framework нь програмд зориулан тодорхойлсон app.yml тохиргооны файлтай байна.
Үүний тусламжтайгаар хүссэн тохиргоонуудаа зааж өгөх боломжтой.
# apps/frontend/config/app.yml
all:
active_days: 30
Програмд энэ тохиргоонууд нь sfConfig классаар гүйцэтгэгддэг.
sfConfig::get(‘app_active_days’)
sfConfig класс нь бидний хойно үзэх symphony-ийн тохиргооны хандах эрхийг
агуулдаг тул тохиргоо нь app_ гэж эхэлсэн байдаг.
Дараахи кодоор save() функцыг шинэчилье.
public function save(Doctrine_Connection $conn = null)
{
if ($this->isNew() && !$this->getExpiresAt())
{
$now = $this->getCreatedAt() ?
$this->getDateTimeObject(‘created_at’)->format(‘U’) : time();
$this->setExpiresAt(date(‘Y-m-d H:i:s’, $now + 86400 *
sfConfig::get(‘app_active_days’)));
}
return parent::save($conn);
}
app.yml тохиргооны файл нь таны програмын global settings|Global Settings буюу
тохиргоог төвлөрүүлэх шилдэг арга.
Эцэст нь хэлэхэд төслийн турш хэрэглэх тохиргоонууд хэрэгтэй бол app.yml
файлын symphony project-ийн config хавтсанд үүсгэх хэрэгтэй.
Refactoring
Хэдийгээр бидний бичсэн код сайн ажиллаж байгаа боловч энэ нь хараахан
хангалтта биш. Та асуудлыг шийдвэрлэхэд бэлэн үү?
Doctrine_Query код нь action (Controller layer)-д хамаарахгүй Model layer-т
хамаарна. MVC моделийн хувьд Model нь бүх бизнес логикийг тодорхойлдог ба
Controller нь зөвхөн Model-ийг дуудаж түүний өгөгдлийг авна. Кодын хувьд ажлын
байрны цуглуулга буцаах ба JobeetJobTable класст getActiveJobs() method үүсгэе.
// lib/model/doctrine/JobeetJobTable.class.php
class JobeetJobTable extends Doctrine_Table
{
public function getActiveJobs()
{
$q = $this->createQuery(‘j’)
->where(‘j.expires_at > ?’, date(‘Y-m-d H:i:s’, time()));
return $q->execute();
}
}

Action код нь энэ шинэ method-оор зөвхөн идэвхитэй ажлын байрны жагсаалтыг
харуулна.
public function executeIndex(sfWebRequest $request)
{
$this->jobeet_jobs =
Doctrine_Core::getTable(‘JobeetJob’)->getActiveJobs();
}
Энэ refactoring нь өмнөх кодуудаас хэд хэдэн илүү үр дүнг өгнө.
• Идэвхитэй ажлын байрны мэдээлэл нь Model logic-оор бүрэн дүрслэгдсэн
• Controller дахь кодууд нь уншигдахуйц, уншиж ойлгоход хялбар байна.
• getActiveJobs() method нь дахин ашиглагдахуйц (Өөр action-үүдэд)
• model code-ийг тестлэж болохуйц болсон
Ажлын байрны мэдээллийг expires_at баганаар эрэмбэлье:
public function getActiveJobs()
{
$q = $this->createQuery(‘j’)
->where(‘j.expires_at > ?’, date(‘Y-m-d H:i:s’, time()))
->orderBy(‘j.expires_at DESC’);
return $q->execute();
}
The orderBy methods нь ORDER BY–ийг SQL-д үүсгэдэг (addOrderBy()-ийг
мөн адил үүсгэнэ).

Categories on the Homepage
2 дахь өдөр үзсэн зүйлсээс:
“Ажлын байрны мэдээлэл нь Категори болон нийтлэгдсэн огноогоороо(шинэ нь
эхэндээ) эрэмбэлэгдэнэ”. Одоог хүртэл ажлын байрны категорийг тодорхойлж
өгөөгүй. Дээрхи шаардлагаар ажлын байр нь категориор эрэмбэлэгдэн харагдах
хэрэгтэй. Эхлээд бүх категорид ядаж нэг нэг идэвхитэй ажлын байрны мэдээлэл
оруулъя.
JobeetCategoryTable классыг нээж getWithJobs() method-ийг нэмье.
// lib/model/doctrine/JobeetCategoryTable.class.php
class JobeetCategoryTable extends Doctrine_Table
{
public function getWithJobs()
{
$q = $this->createQuery(‘c’)
->leftJoin(‘c.JobeetJobs j’)
->where(‘j.expires_at > ?’, date(‘Y-m-d H:i:s’, time()));
return $q->execute();
}
}
Index action-ийг дээрхи кодоос үүдэн өөрчилье.
// apps/frontend/modules/job/actions/actions.class.php
public function executeIndex(sfWebRequest $request)
{
$this->categories =
Doctrine_Core::getTable(‘JobeetCategory’)->getWithJobs();
}
Бүх идэвхитэй ажлыг дэлгэцэнд харуулахын тулд template-д өөрчлөлт оруулна:
// apps/frontend/modules/job/templates/indexSuccess.php
<?php use_stylesheet(‘jobs.css’) ?>
<div id=&#8221;jobs&#8221;>
<?php foreach ($categories as $category): ?>
<div>
<div>
<div>
<a href=&#8221;&#8221;>Feed</a>
</div>
<h1><?php echo $category ?></h1>
</div>
<table>
<?php foreach ($category->getActiveJobs() as $i => $job): ?>
<tr>
<td>
<?php echo $job->getLocation() ?>
</td>
<td>
<?php echo link_to($job->getPosition(), ‘job_show_user’,$job) ?>
</td>
<td>
<?php echo $job->getCompany() ?>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
<?php endforeach; ?>
</div>
Категорийн нэрийг template-д харуулахын тулд echo $category-ийг ашиглав. Энэ
сонин сонсогдож байна уу? $category объектоор echo яаж категорийн нэрийг харуулж
байна вэ? Хариулт нь 3 дахь өдөр тодорхойлсон бүх model класст зориулсан
__toString() method.
Үүний тулд getActiveJob() method-ийг jobeetCategory класст нэмнэ.
// lib/model/doctrine/JobeetCategory.class.php
public function getActiveJobs()
{
$q = Doctrine_Query::create()
->from(‘JobeetJob j’)
->where(‘j.category_id = ?’, $this->getId());
return Doctrine_Core::getTable(‘JobeetJob’)->getActiveJobs($q);
}
JobeetCategory::getActiveJobs() method нь Doctrine_Core::getTable(‘JobeetJob’)->
getActiveJobs() method-ийг идэвхитэй ажлын байранд категори нэмэхэд ашиглана.
Doctrine_Core::getTable(‘JobeetJob’)->getActiveJobs()-ийг дуудсанаар категориор
тодорхойлогдсон элдэв хязгаарлалтуудыг хийх боломжтой болно. Бид категори
объект дамжуулахын оронд Doctrine_Query объект ашигласан нь энэ нөхцлийг
бүрдүүлж өгсөн.
getActiveJob()-д энэ Doctrine_Query объектыг query-ийнх нь хамт нэгтгэнэ.
Doctrine_Query нь объект тул энэ нь амархан.
// lib/model/doctrine/JobeetJobTable.class.php
public function getActiveJobs(Doctrine_Query $q = null)
{
if (is_null($q))
{
$q = Doctrine_Query::create()
->from(‘JobeetJob j’);
}
$q->andWhere(‘j.expires_at > ?’, date(‘Y-m-d H:i:s’, time()))
->addOrderBy(‘j.expires_at DESC’);
return $q->execute();
}
Limit the Results
“Категори бүрийн эхний 10 ажлын байрны жагсаалтыг харуулах ба категорийн
бүх ажлын байрны жагсаалтын харуулах холбоостой байна.”
Үүнийг getActiveJobs() method-оор хялбархан шийдэж болно:
// lib/model/doctrine/JobeetCategory.class.php
public function getActiveJobs($max = 10)
{
$q = Doctrine_Query::create()
->from(‘JobeetJob j’)
->where(‘j.category_id = ?’, $this->getId())
->limit($max);
return Doctrine_Core::getTable(‘JobeetJob’)->getActiveJobs($q);
}
Тохирох LIMIT нөхцөл нь Model-д засах боломжгүй (hard-coded) байдаг боловч
түүний утгыг өөрчлөх боломжтой байдаг. Нэг хуудсанд харагдах ажлын байрны
жагсаалтыг app.yml файлд зааж өгч болно:
<!– apps/frontend/modules/job/templates/indexSuccess.php –>
<?php foreach
($category->getActiveJobs(sfConfig::get(‘app_max_jobs_on_homepage’)) as $i
=> $job): ?>
app.yml-д үүнээс гадна шинэ тохиргоо нэмж болно:
all:
active_days: 30
max_jobs_on_homepage: 10


Dynamic Fixtures
Та max_jobs_on_homepage тохиргоогүйгээр өөрчлөлтийг харж чадахгүй.
Иймээс бид ажлын байрны жагсаалтад fixture нэмэх хэрэгтэй. Ингэхийн тулд та
COPY and PASTE маягаар үүнийг шийдэж болох боловч үүнээс хялбар арга байна.
Fixture файлуудыг давхардуулан ашиглах нь муу. Symfony үүнийг шийдвэрлэсэн!
Symfony-ийн YAML нь файлуудаас өмнө ачаалдаг ба PHP кодуудыг дэмждэг.
jobs.yml fixture файлыг засварлаж дараахи кодуудыг төгсгөлд нь нэм:
# Starts at the beginning of the line (no whitespace before)
<?php for ($i = 100; $i <= 130; $i++): ?>
job_<?php echo $i ?>:
JobeetCategory: programming
company: Company <?php echo $i.&#8221;\n&#8221; ?>
position: Web Developer
location: Paris, France
description: Lorem ipsum dolor sit amet, consectetur adipisicing elit.
how_to_apply: Send your resume to lorem.ipsum [at] company_<?php echo $i
?>.sit
is_public: true
is_activated: true
token: job_<?php echo $i.&#8221;\n&#8221; ?>
Practical symphony Day6. More with the Model
Ariunsuld_sh@e-map.mn Хуудас 9
email: job@example.com
<?php endfor ?>
Анхааруулахад YAML parser нь тав гэх мэт догол мөрийг дэмждэггүй. Зөвхөн
хоосон зай (white space)-г дэмжнэ.
PHP кодыг YAML файлд бичихдээ:
• <?php ?> statements үргэлж мөрийн эхэнд байх болон өгөгдлийг өргөтгөх.
• Хэрэв <?php ?> statement мөрийн төгсгөлд байвал, (“\n”)-аар шинэ мөр гэж
зааж өгөх хэрэгтэй.
Та doctrine:data-load нь Programming категорийн 10 ажлын байрыг л үндсэн
хуудсан харуулж байгааг үзэж болно. Доорхи зурганд нэг хуудсанд харуулах
ажлын байрны жагсаалтыг 5-аар хязгаарласныг харж болно.


Secure the Job Page
Ажлын байрын идэвхитэй хугацаа дууссанаар хандах URL-ыг яг мэдэж байсан ч
хандах боломжгүй болдог. Идэвхигүй болсон (expired) ажлын байрны URL-ыг
мэдэхийг оролдъё (Үндсэн id нь өгөгдлийн сангаас –SELECT id, token FROM
jobeet_job WHERE expires_at<NOW()):
/frontend_dev.php/job/sensio-labs/paris-france/ID/web-developer-expired
Идэвхигүй ажлын жагсаалтыг харахаас өмнө бид хэрэглэгчид харагдах 404
хуудсыг (Page not found) харуулах ёстой. Гэвч үүнийг яаж автоматаар шийдвэрлэх
вэ?
# apps/frontend/config/routing.yml
job_show_user:
url: /job/:company_slug/:location_slug/:id/:position_slug
class: sfDoctrineRoute
options:
model: JobeetJob
type: object
method_for_query: retrieveActiveJob
param: { module: job, action: show }
requirements:
id: \d+
sf_method: [GET]
retrieveActiveJob() method нь Doctrine_Query объектыг хаяг(route)-аар үүсгэнэ.
// lib/model/doctrine/JobeetJobTable.class.php
class JobeetJobTable extends Doctrine_Table
{
public function retrieveActiveJob(Doctrine_Query $q)
{
$q->andWhere(‘a.expires_at > ?’, date(‘Y-m-d H:i:s’, time()));
return $q->fetchOne();
}
// …
}
Одоо хэрэв та идэвхигүй болсон ажлын жагсаалтыг харахаар оролдвол 404
хуудас (Page not found) гарах болно.


Link to the Category Page
Гэвч хэсэг хүлээ. Бидний бэлтгэл ажил хараахан бэлэн болоогүй байна. Иймээс
таньд илүү их чөлөөт цаг болон өөрийгөө хөгжүүлэх хангалттай мэдлэг хэрэгтэй!
Энэ талын дадлага ажил хийцгээе. Маргааш өөрсний ажлыг эргэн шалгах болно.
Final Thoughts
Өөрийн локал Jobeet төсөл дээр ажиллалаа. Symfony-ийн онлайн API
documentation2 болон үнэгүй бичиг баримтууд3 нь таньд тусална. Маргааш бид
үүнийг хэрхэн хэрэгжүүлэх боломжийг судална.

2 http://www.symfony-project.org/api/1_4/
3 http://www.symfony-project.org/doc/1_4/

орчуулсан: Ариунсүлд

Advertisements

10 thoughts on “Practical symfony 6 дахь өдөр More with the Model (орчуулсан: Ариунсүлд)

  1. goy blog bn l dee gehdee yag gadaag hiiheer aldaa garaad bhiin er n bol video hicheel hiiwel yasiin gesen sanaa dewshuuluul arai dawartsan hereg bolohuu gehdee zuger l sanlaa helsen yum shu

  2. Энд гацчилаа data- load хийхээр болж байгаан нөгөө 2 мэргэжил маань нүүр хуудсан дээр гарч ирэхээ байчхын юундаа байгаан бол

  3. Баазад чинь алдаагүй орцон бол дуудаж байгаа модел хэсэг дээр чинь л алдаа байгаа байх. Баазаасаа дуудаж байгаа утгуудаа шалга.

  4. Баазад алдаагүй орцон байналдаа би бүр jobeet ийн 6 дахь өдрийн respotary г харж байгаад нэг нэгээр хуулж үзлээ болдгүэ юундаа байгаан болдоо :-/

Хариулт үлдээх

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Өөрчлөх )

Twitter picture

You are commenting using your Twitter account. Log Out / Өөрчлөх )

Facebook photo

You are commenting using your Facebook account. Log Out / Өөрчлөх )

Google+ photo

You are commenting using your Google+ account. Log Out / Өөрчлөх )

Connecting to %s