جستجوی Entity ها در دروپال 7 با کلاس EntityFieldQuery

جستجوی Entity ها در دروپال 7 با کلاس EntityFieldQuery

مفهوم Entity در دروپال

در مقاله «مفهوم Entity، Bundle و Field در دروپال» با مفهوم Entity در دروپال 7 آشنا شدیم. در آنجا بیان شد که «مفهوم Entity در دروپال یک مفهوم Abstract یا انتزاعی است که به پاره ای از اشیاء (object ها) در دروپال مانند کاربر (User)، محتوا (Content)، نظر (comment)، دسته ها (Taxonomy Term) و ... اطلاق می شود». در نمودار زیر مشاهده می کنید که چه موجودیت هایی در هسته دروپال Entity به شمار می روند.

مفهوم Entity در دروپال

جستجوی Entity ها در دیتابیس دروپال

برخی از این موجودیت ها ضمن اینکه خود دارای داده هایی هستند، در سیستم دروپال دارای فیلد های دیگری نیز هستند. مثلا یک محتوا از جنس Node است ولی شما در دروپال 7 فیلد های دیگری را نیز با استفاده از Field API به آن اضافه می کنید. این داده ها درون دیتابیس دروپال نگه داری می شوند و مایل هستیم در آنها جستجو کنیم. مثلا تمام entity هایی که از جنس Node هستند و bundle آنها article است و این به معنی پیدا کردن تمام محتوای از جنس Article در دروپال است.

تصور کنید یک نوع محتوا به نام blog داریم که یک فیلد متنی به نام منبع دارد. می خواهیم تمام محتوای سایت از نوع بلاگ که از منبع خاصی هستند جستجو کنیم. طبیعتا انجام این کار با استفاده از ماژول Views به آسانی صورت می گیرد. ولی بحث ما در اینجا برنامه نویسی ماژول است. یعنی در جایی در یک ماژول نیاز به چنین اطلاعاتی داریم و می خواهیم به سرعت به اطلاعات مورد نظر خود دست پیدا کنیم.

ابتدایی ترین راهی که به نظر ما می رسد این است که با استفاده از روش های مرسوم کار با دیتابیس در دروپال 7 (کلاس SelectQuery و db_select) روی جداول کوئری بزنیم یا از تابع قدیمی node_load استفاده کنیم. ولی دروپال 7 کلاس جدیدی به نام EntityFieldQuery ارائه کرده است که روش جدید و واحدی برای جستجوی Entity ها در دروپال را عرضه می کند.

کلاس EntityFieldQuery در دروپال 7

این کلاس امکان محدود کردن جستجو در Entity ها را به اطلاعات مختلف یک Entity type فراهم می کند. می توانید بر اساس مقادیر فیلد ها شرایط جستجو را تعیین کنید، یا خصوصیت های آن Entity و یا اطلاعات عمومی تر Entity ها.

در نمونه کد زیر از این کلاس استفاده کرده ایم:

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
	->entityCondition('bundle', 'book')
	->propertyCondition('status', 1)
	->fieldCondition('field_tags', 'tid', '110');
$result = $query->execute();

custom_dpm($result);

در خط اول، ابتدا یک object (شیء) از کلاس EntityFieldQuery ایجاد کرده ایم.

در خط دوم یک شرط اضافه کرده ایم که مربوط به اطلاعات عمومی  Entity ها است. این نوع شرط ها entityCondition هستند. بنابراین با تابعی به همین نام، شرط را تعریف می کنیم. با شرطی که در خط دوم کد تعیین کرده ایم از ابتدا دایره جستجو را به محتوای سایت یعنی Node ها محدود کرده ایم.

در خط سوم شرط عمومی دیگری مربوط به entity ها تعیین کرده ایم.  در این شرط bundle را محدود کرده ایم. در مقاله «مفهوم Entity، Bundle و Field در دروپال» با مفهوم Entity در دروپال 7 آشنا شدیم. با توجه به اینکه هر entity type در دروپال، می تواند انواع مختلفی داشته باشد.، این شرط را تعیین کرده ایم. محتوا (node)  می تواند انواع داشته باشد. یعنی نوع محتوا ها (content type) هایی که در سایت اضافه می کنیم هر یک bundle ای از نوع موجودیت Node هستند. در این خط سوم نیز همین کار را کرده ایم و برای اینکه جستجو به محتوای کتاب ها در دروپالیکا محدود شود، bundle را برابر book قرار داده ایم.

در خط چهارم یک شرط مخصوص entity را تعیین کرده ایم. در اینجا ما میخواستیم که فقط محتوایی که در حالت published قرار  دارند را پیدا کنیم. در پشت این قضیه status یک محتوا در دیتابیس باید برابر 1 باشد تا در حالت published یا انتشار قرار داشته باشد. این یک اطلاعاتی خاص node ها (محتوا) است مثلا taxonomy term ها این را ندارند. بنابراین این شرط را با استفاده از تابع properyCondition اضافه کرده ایم.

در خط پنجم، یک شرط فیلد تعیین کرده ایم. با فیلد نیز آشنا هستید و در مقاله «مفهوم Entity، Bundle و Field در دروپال» مطالبی در این باره بیان شده است. در سایت دروپالیکا، نوع محتوای bookیک فیلد تگ دارد که نام ماشین آن field_tags است. در این خط تعیین کرده ایم که جستجو را به محتوایی محدود کند که از طریق این فیلد به taxonomy term با شناسه 110 مرتبط هستند.

در خط ششم، تابع execute را روی object ای که ساخته بودیم و نام آن $query بود، اجرا می کنیم که جستجو در داده های دیتابیس انجام شود و نتیجه ای که بر میگرداند را نیز در یک متغیر به نام $result ذخیره می کنیم.

در خط هفتم، با استفاده ار روشی که در مقاله «مشاهده مقادیر متغیر ها و آرایه ها در برنامه نویسی ماژول دروپال» بیان کردیم، نشان داده ایم که نتیجه ای که از اجرای کوئری گرفته ایم چه ساختاری دارد که در تصویر زیر نتیجه را مشاهده می کنید:

نمایش نتیجه حاصل از اجرای کوئری EntityFieldQuery در دروپال

خروجی تابع execute با توجه به این شکل، یک آرایه است که یک خانه دارد و ایندکس این خانه با توجه به اینکه entity type ما node است، همان node است. این خانه نیز خودش حاوی یک آرایه است که درون آن entity های یافته شده (در اینجا محتوای پیدا شده) قرار دارند. فعلا در اینجا فقط یک محتوا پیدا کرده که nid آن 108 است. برای هر محتوا می بینیم که ایندکس آن خانه شناسه آن محتوا است و درون آن نیز یک شی (object)  از نوع stdClass داریم که حاوی nid و vid و type آن محتوا است.

جستجوی دسته ها (Taxonomy Term ها)  با استفاده از EntityFieldQuery از دیتابیس دروپال

همانطور که گفتیم این کلاس فقط برای استحراج داده های مربوط به محتوای سایت یا node ها نیست بلکه می توانیم برای Entity type ها دیگر نیز آن را به کار ببریم. در نمونه کدی که در ادامه مشاهده می کنید، می خواهیم دسته های سایت را که با استفاده از Taxonomy در دروپال ایجاد شده اند را پیدا کنیم.

$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'taxonomy_term')
	->entityCondition('bundle', 'tags');
$result = $query->execute();

custom_dpm($result);

مانند نمونه قبل، اولین کاری که انجام داده ایم این است که یک objectاز کلاس EntityFielQuery درست کنیم. در خط دوم نوع entity را مشخص کرده ایم. با توجه به اینکه می خواهیم در دسته ها یا taxonomy term ها جستجو را انجام بدهیم، یک شرط عمومی entity تعیین کرده ایم که entity_type برابر taxonomy_term باشد.

در خط سوم، مشخص کرده ایم که دسته ها درون کدام bundle را نیاز داریم. می دانیم که taxonomy term ها درون Taxonomy Vocabulary ها قرار می گیرند ما در اینجا می خواستیم که مشخص کنیم فقط دسته های موجود در vocabulary که نام ماشین آن tags است را پیدا کنیم. بنابراین شرط عمومی entity دیگری اضافه کرده ایم که bundle را به tags محدود کند.

در نهایت تابع execute را برای اجرای جستجو در دیتابیس فراخوانی کرده ایم و نتیجه را گرفته و با استفاده از روشی که در مثال قبل گفته شد، نمایش داده ایم.

نتیجه اجرای کد را هم مشاهده می کنید:

جستجوی دسته ها با استفاده از EntityFieldQuery در دروپال

این نتیجه مشخص می کند که نتیجه با چه ساختاری به ما داده شده است. بنابر چیزی که در بالا می بینیم، نتیجه اجرا یک آرایه است که یک خانه دارد که حاوی نام entity_type است که در اینجا taxonomy_term می باشد. این یک خانه خودش حاوی یک آرایه است که این آرایه محتوی اطلاعات term هایی است که یافت شده اند. مانند قبل ایندکس های آرایه اخیر، شناسه Taxonomy Term هایی که پیدا شده اند، است و درون آنها نیز یک object از نوع stdClass داریم که باز هم محتوی شناسه آن دسته هستند.

بیشتر درباره تابع entityCondition

همانطور که گفته شد شرط هایی که بین اکثر Entity type ها عمومی هستند، با استفاده از این تابع به کوئری EntityFieldQuery اضافه می شوند. در اینجا ما از دو نوع شرط عمومی استفاده کردیم:

  • شرط entity_type: مقادیر آن می توانند همه entity type هایی باشد که توسط هسته دروپال یا ماژول های دیگری تعریف شده اند. مثل node، taxonomy_term، comment، user و file که توسط هسته دروپال تعریف شده اند.
  • شرط bundle: نمونه استفاده آن در node و taxonomy_term را دیدیم. البته همه entity type ها این را ندارند.

شرط revision_id و entity_id از دیگر شروطی هستند که از این طریق این تابع اضافه می شوند.

تابع entityCondition سه ورودی می گیرد. ورودی اول نام شرط که در بالا ذکر شد، ورودی دوم مقداری که با آن شرط باید مقایسه شود. ورودی سوم یک عملگر است. به صورت پیش فرض چون دقیقا می خواهیم برابری نام و مقدار را بررسی کنیم، چیزی به این ورودی سوم نمی دهیم. برای بعضی شرط ها اساساً نمی توان عملگر دیگری تصور کرد مثل entity_type که حتما باید با یک مقدار که به آن می دهیم برابر باشد. ولی برای شرط bundle می توانیم از عملگر IN استفاده کنیم که در این صورت می توانیم به جای یک bundle، آرایه ای از bundle ها را بدهیم.  برای دو شرط revision_id و entity_id که عددی هستند می توانیم از عملگرهای مقایسه ای نظیر < و > و != استفاده کنیم. همین طور استفاده از IN و NOT IN به صورتی که آرایه ای از مقادیر را به ورودی دوم بدهیم، برای آنها متصور است.

بیشتر درباره تابع propertyCondition

شروطی به این تابع می دهیم، مخصوص entity type ای هست که انتخاب کرده ایم. معمولا ستون هایی از دیتابیس هستند که در جدول خاص آن entity ها وجود دارند. مثلا برای محتوا یا node ها status را دیدیدم. همین طور می توانیم برای node ها شروطی نظیر type و uid را نیز استفاده کنیم.

ورودی های این تابع شبیه ورودی های تابع entityCondition هستند.

بیشتر درباره تابع fieldCondition

بیان شد که وقتی می خواهیم روی فیلد ها جستجویی را انجام بدهیم، از این تابع استفاده می کنیم. ورودی اول این تابع نام ماشین فیلد است. ورودی دوم، نام ستونی از آن فیلد است که در جدول آن فیلد در دیتابیس وجود دارد. مثلا برای یک فیلد عددی ستون value حاوی مقدار آن فیلد است. برای یک فیلد Term Reference، ستون tid حاوی شناسه term است. در یک فیلد متنی مثل body ستون های body_value، body_summary و body_format را داریم. البته هر کدام از این جداول ستون های دیگری نیز دارند.

توابع مفید دیگری از EntityFieldQuery

برای اینکه نتیجه جستجو را بر اساس خاصی مرتب کنیم، از تابع propertyOrderBy استفاده می کنیم. برای اینکه تعداد مشخصی نتیجه از اجرای کوئری بگیریم، از تابع range استفاده می کنیم.

نظرات

عالی هستید.
مرسی از آموزش خوبتون

تصویر admin
رضا جان، ممنون از اینکه نظر خود را می دهید و مسرور از اینکه مقاله را مفید ارزیابی کرده اید.

سلام
خسته نباشد و ممنون از توضیح خوبتون
من دو تا کانتنت تایپ 1 و 2 دارم که در هر کدام اطلاعاتی ذخیره میشه حالا میخام که اگر در شماره 1 مقادیری مثل رادیوباتوون بلی خیر بود در شماره 2 بعضی فیلدها نمایش داده نشود یا نشود

ارسال نظر