مقدمه ای بر کلاس EntityFieldQuery دروپال برای پرس و جو از entity ها و فیلد ها

دروپال 7 یک API جدید به نام EntityFieldQuery ایجاد کرده است. API فوق یک کلاس است که به کمک آن می توان به سهولت و سرعت زیاد، از کلیه ی entity ها (از جمله node ها) و فیلد های موجود درسایت گزارش گیری کرد.

لایه ی انتزاع پایگاه داده (Database abstraction layer) دروپال 7 خیلی غنی تر از نسخه های پیشین دروپال است. با این حال، بازهم برای کار با پایگاه داده در دروپال 7 به گونه ای نیاز به ایجاد query های SQL می باشد.

اما کلاس EntityFieldQuery کمک می کند که بدون داشتن دانش SQL از فیلدها و entity ها query های گوناگون بگیریم.

خود هسته ی دروپال هم از EntityFieldQuery به عنوان یک ابزار استفاده می کند. که در بسیاری از موارد فقط برای این استفاده شده که بررسی کند که آیا یک فیلد با یک مقدار مشخصی موجود هست یا خیر.

در زیر این کلاس مفید را بررسی می کنیم و با هم برخی از ویژگی های آن را یاد میگیریم:

شروع Query

برای شروع کافی است که یک آبجکت جدید از کلاس EntityFieldQuery ایجاد کنیم:

$query = new EntityFieldQuery();

خیلی ساده است. اینطور نیست؟ این همه ی چیزی است که برای شروع نیاز داریم.
اکنون اجازه دهید مقداری شرط به query مان اضافه کنیم:

$query
 ->entityCondition('entity_type', 'node')
 ->entityCondition('bundle', 'article')
 ->propertyCondition('status', 1)
 ->propertyOrderBy('created', 'DESC');

پیش از هر چیز، ممکن است عدم وجود سمیکالن در انتهای خطوط (بین فراخوانی متدها) توجه شما را جلب کند.
این به این خاطر است که هر متدی در آبجکت EntityFieldQuery به عنوان مقدار بازگشتی، دوباره همان آبجکت EntityFieldQuery مورد عمل را باز می گرداند و این ویژگی امکان فراخوانی زنجیره ای متدها را فراهم می کند. و باعث خوانایی بیشتر و سرعت بیشتر در کدنویسی می شود.

ویژگی فوق برای کسانی که قبلا با jQuery کار کرده اند نیز آشنا است. کد فوق را می توانستیم به صورت زیر هم بنویسیم:

$query->entityCondition('entity_type', 'node')->entityCondition('bundle', 'article')->propertyCondition('status', 1)->propertyOrderBy('created', 'DESC');

اما در این صورت، خوانایی کد کم می شود. توصیه می شود که همیشه فراخوانی هر متد را در یک خط جدید قرار دهید.

اکنون اجازه دهید که به تک تک خطوط کد فوق بپردازیم و کاری که انجام می دهند را شرح دهیم:

->entityCondition('entity_type', 'node')

اولین فراخوانی، از متد entityCondition استفاده می کند و مشخص می کند که می خواهیم از entity های نوع node گزارش گیری کنیم. توجه کنید که در دروپال entity های گوناگونی داریم به عنوان مثال node ها و user ها و taxonomy term ها و comment ها همگی انواع مختلف entity به حساب می آیند.

->entityCondition('bundle', 'article')

متد entityCondition شرایط خاصی را بر روی entity های موجود در گزارش اعمال می کند. در خط فوق، ما bundle را به عنوان آرگومان اول استفاده کردیم. به این ترتیب می توانیم گزارش مان را به node type های خاصی محدود کنیم. اگر بخواهیم همه ی node ها را صرف نظر از نوع شان شامل کنیم، می توانیم خط فوق را حذف کنیم.

نکته: توجه کنید که هر entity ممکن است دارای تعدادی bundle باشد. مثلا node دارای content type است. هر content type در واقع یک bundle از node است.

به عنوان مثال دیگر، Taxonomy می تواند شامل تعدادی vocabulary باشد. هر vocabulary یک bundle به حساب می آید...

همانطور که حدس می زنید، در دستور فوق مشخص کردیم که می خواهیم فقط از node های نوع article در query مان استفاده کنیم. توجه کنید که آرگومان دوم entityCondition می تواند یک رشته و یا یک آرایه باشد. به عنوان مثال اگر بخواهیم هم article و هم page ها را شامل کنیم، می توانیم خط فوق را به صورت زیر تغییر دهیم:

->entityCondition('bundle', array('article', 'page'))

همانطور که می بینید، خیلی ساده می توانید query تان را گسترش بدهید.

->propertyCondition('status', 1)

متد بعدی propertyCondition است. در اینجا، property به معنی یک فیلد در جدول اصلی entity مورد عمل می باشد. در مورد node ها ، از property می توانیم برای بررسی وضعیت منتشرشده بودن node ، کاربری که node را ایجاد کرده است، تاریخ ایجاد node و ... استفاده کنیم.

در دستور فوق، EntityFieldQuery را محدود کرده ایم که فقط node های منتشر شده را جمع آوری کند (که فیلد status آن ها 1 است).

->propertyOrderBy('created', 'DESC')

متد propertyOrderBy در مثال فوق، برای تنظیم شیوه ی مرتب سازی نتایج استفاده می شود. آرگومان اول، نام فیلدی است که مرتب سازی بر اساس آن انجام می گیرد و آرگومان دوم ASC و یا DESC است.

پرس و جوی فیلدها و محدود سازی

اکنون اجازه دهید که یک پرس و جو بر روی مقدار یک فیلد ایجاد کنیم.

برای این منظور از متد fieldCondition() استفاده می کنیم. فرض کنید که همه ی انواع node های که مورد پرس و جو قرار می دهیم، دارای یک فیلد به نام field_us_state می باشند.

قصد داریم که همه ی node هایی که متعلق به منطقه ی New York Tri-state area (که همچنین شامل Connecticut و New Jersey می شود) هستند را پیدا کنیم. این پرس و جو به صورت زیر خواهد شد:

$query->fieldCondition('field_us_state', 'value', array('CT', 'NJ', 'NY'));

در صورتی که بخواهیم می توانیم نتایج را بر روی مقداری فیلدها هم مرتب کنیم. توجه کنید که اگر چند نوع مرتب سازی داشته باشیم، قوانین مرتب سازی به همان ترتیبی که به پرس و جو اضافه شده اند، پردازش می شوند.

فرض کنید که می خواهیم نتایج را فقط به 10 گزینه ای که جدیدا ایجاد شده اند محدود کنیم. بگذارید یک محدودیت ایجاد کنیم:

$query->range(0,10);

دستور فوق نتایج را به موارد صفر تا 10 محدود می کند.

و بفرمایید!

در نهایت پرس و جو را اجرا می کنیم تا نتایج را به دست آوریم:

$result = $query->execute();

متد execute() پرس و جو را اجرا می کند و نتایج را به صورت یک آرایه از شناسه های entity ها (entity id) برمی گرداند. (در این جا node id ها یا nid ها) که با شرایط قید شده در پرس و جو منطبق می باشند.

اگر ما node ها را مورد پرس و جو قرار داده باشیم، نتایج در داخل $result['node'] قرار می گیرند. آن چه که معمولا شما می خواهید، nid هایی است که برگردانده شده اند. برای به دست آوردن آن ها به سادگی می توانید از دستور زیر استفاده کنید:

$nids = array_keys($result['node']);

کل کدی که نوشتیم به صورت زیر خواهد بود:

$query = new EntityFieldQuery();
$query
  ->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'article')
  ->propertyCondition('status', 1)
  ->propertyOrderBy('created', 'DESC')
  ->fieldCondition('field_us_state', 'value', array('CT', 'NJ', 'NY'))
  ->range(0,10);
$result = $query->execute();
$nids = array_keys($result['node']);

نسبت به نتیجه ی عالی ای که گرفیتم، اصلا کد زیادی ننوشتیم!
از این مهم تر این است که نیازی به دانش SQL و مهم تر از آن زیر ساخت ذخیره ی اطلاعات در پایگاه داده نداشتیم و همه چیز به طور خودکار انجام شد.
ما فقط پرس و جو را به شیوه ی ساده ی EntityFieldQuery می نویسیم و API قدرتمند دروپال آن را به یک query قابل درک توسط لایه ی انتزاعی پایگاه داده ی دروپال تبدیل می کند و اجرا کرده و نتایج را به فرمت مناسبی برای ما آماده می کند.

اکنون ما با یک لیست از node id ها چه کاری می توانیم انجام دهیم؟ مسلما هر کاری که بخواهیم! به عنوان مثال ممکن است بخواهیم همه ی node های بدست آمده را load کنیم:

$nodes = node_load_multiple($nids);

همچنین ممکن است بخواهیم node های بدست آمده را به صورت گروهی و در مود teaser نمایش دهیم که آن هم به سادگی قابل اجرا خواهد بود. اجازه دهید که یک آرایه ی قابل render ایجاد کنیم:

$output = node_view_multiple($nodes);

این فقط یک شروع بود. EntityFieldQuery یک کلاس بسیار قدرتمند است و می توانید مستندات آن را در سایت Drupal.org مطالعه کنید.

موفق باشید.

این مقاله از صفحه ی زیر برداشت شده است:
http://treehouseagency.com/blog/tim-cosgrove/2012/02/16/entityfieldquery...
با تشکر فراوان از Tim Cosgrove

افزودن دیدگاه جدید