بخش فروش دیجیکالا تصمیم گرفته است که تعدادی offer استثنایی ارائه دهد. آنها میخواهند تا عید نوروز سال آینده تخفیف ۸۰٪ روی برخی از اجناس اعمال کنند! حتی ممکن است چنین offer هایی در سالهای آینده نیز ارائه شوند؛ لذا آنها نیاز به برنامهای برای محاسبهی خودکار تعداد روزهای باقیمانده تا عید نوروز دارند.
از شما میخواهیم برنامهای بنویسید که یک تاریخ شمسی از ورودی دریافت کرده و تعداد روزهای باقیمانده تا عید نوروز سال بعد، با محاسبه روز فعلی، را محاسبه کند.
نکته: فرض کنید که سال کبیسه نداریم؛ یعنی همهی سالها ۳۶۵ روزه هستند و شش ماه اول سال ۳۱ روزه، ۵ ماه بعدی، ۳۰ روزه و ماه آخر ۲۹ روزه است.
در یک خط از ورودی استاندارد (stdin)، رشتهی تاریخ (به صورت شمسی) با فرمت yyyy/mm/dd
وارد میشود.
برای دریافت ورودی، میتوانید از تابع readline
استفاده کنید:
در یک خط از خروجی استاندارد، تعداد روزهای باقیمانده تا عید نوروز سال بعد ورودی را چاپ کنید.
برای حل این مسئله، میتوانید آرایهای شامل تعداد روزهای هر ماه در نظر بگیرید.
آرایهی شامل تعداد روزهای هر ماه بهصورت زیر خواهد بود:
با استفاده از تابع readline
میتوان ورودی را از stdin دریافت کرد. همچنین، با استفاده از تابع explode
میتوان سال، ماه و روز را جدا کرد. در نهایت، با استفاده از تابع list
میتوان آرایهی شامل سال، ماه و روز را در سه متغیر ذخیره کرد:
با استفاده از تابع array_slice
میتوان ماههای باقیمانده تا پایان سال را بر اساس آرایهی $months
جدا کرد:
با استفاده از تابع array_sum
میتوان مجموع اعداد آرایهی بالا را بهدست آورد. بنابراین، تعداد روزهای باقیمانده تا عید نوروز سال بعد برابر خواهد بود با:
میلاد بهتازگی در دیجیکالا بهعنوان توسعهدهندهی junior استخدام شده است. اولین task ای که به او واگذار شده، بازنویسی بخش pagination وبسایت دیجیاستایل است. از آنجا که میلاد تجربهی انجام این کار را ندارد، از شما میخواهیم تا این بخش را برای او پیادهسازی کنید.
پروژهی اوّلیه را از اینجا دانلود کنید. ساختار پروژه بهصورت زیر است:
pagination.tpl
: این فایل شامل قالب HTML بخش pagination بوده و محتوای آن بهصورت زیر است:pagination.php
: شامل دو تابع زیر است:renderPagination
: این تابع بهترتیب یک رشته حاوی قالب HTML ، تعداد مطالب موجود در وبسایت، حداکثر تعداد مطالب در هر صفحه، شمارهی صفحهی فعلی و لینک پایهی صفحات را دریافت میکند. در نهایت، بخش pagination را بهصورت یک رشته برمیگرداند.
getPaginationButtons
: این تابع بهترتیب تعداد مطالب موجود در وبسایت، حداکثر تعداد مطالب در هر صفحه و شمارهی صفحهی فعلی را دریافت کرده و آرایهای شامل دکمهها جهت نمایش در بخش pagination را برمیگرداند. هر دکمه یک آرایهی associative است که شامل دو کلید text
و number
است. مقدار کلید text
برای دکمهی رفتن به صفحهی قبلی prev
و برای دکمهی رفتن به صفحهی بعدی next
است. همچنین، مقدار کلید text
برای دکمهی ...
همان ...
است. مقدار کلید number
بیانگر شمارهی صفحهی موجود در لینک دکمه است؛ برای مثال اگر ۴ صفحه داشته باشیم و در حال حاضر در صفحهی ۳ باشیم، مقدار کلید number
برای دکمههای prev
و next
بهترتیب برابر با 2
و 4
خواهد بود. بدیهی است که مقدار کلید number
برای سایر دکمهها (بهجز دکمهی ...
) باید برابر با مقدار کلید text
باشد.
توجه: دکمهی ...
نباید کلید number
را داشته باشد.
محتویات فایل pagination.php
بهصورت زیر است:
قوانین صفحهبندی بهشرح زیر هستند:
...
نمایش داده میشوند....
دکمهی شمارهی صفحهی بین آنها قرار میگیرد؛ برای مثال، بین دکمههای ۵ و ۷ هیچگاه دکمهی ...
نمیآید.prev
باید در صورتی نمایش داده شود که شمارهی صفحهی فعلی ۱ نباشد.next
باید در صورتی نمایش داده شود که شمارهی صفحهی فعلی برابر با تعداد صفحات نباشد.توجه: ترتیب آرایههای خروجی تابع getPaginationButtons
باید بهصورت زیر باشد:
prev
(در صورت وجود)...
نیز باشد.)next
(در صورت وجود) خروجی مورد انتظار:
خروجی مورد انتظار:
خروجی مورد انتظار:
خروجی مورد انتظار:
خروجی مورد انتظار:
index.php
: این فایل توابع موجود در فایل pagination.php
را فراخوانی کرده و از طریق آن میتوان خروجی بخش pagination را مشاهده کرد. محتوای آن بهصورت زیر است:پس از پیادهسازی تابع getPaginationButtons
، فایل pagination.php
را آپلود کنید.
تعداد صفحات برابر خواهد بود با :
آرایهای برای ذخیرهسازی دکمهها در نظر میگیریم:
اگر تعداد صفحات بیشتر از ۱ باشد، دکمهی prev
شمارهی $current_page - 1
را اضافه میکنیم:
پس از اضافه کردن دکمههای شماره و ...
(در صورت نیاز)، اگر تعداد صفحات بیشتر از شمارهی صفحهی فعلی باشد، دکمهی next
با شمارهی $current_page + 1
را اضافه میکنیم:
میدانیم حداکثر دو دکمهی ...
در بین دکمهها موجود خواهند بود که یکی از این دکمهها در بین دکمههای سمت چپ دکمهی صفحهی فعلی و دیگری در بین دکمههای سمت راست دکمهی صفحهی فعلی خواهد بود. دو flag برای این دو دکمه در نظر میگیریم که هرگاه این دکمهها درج شوند، flag شان true
میشود.
پیمایش را از شمارهی ۱ تا تعداد صفحات انجام میدهیم. اگر مقدار شمارهی فعلی ۱ باشد، یا اختلاف آن با شمارهی صفحهی فعلی کمتر از ۳ باشد، یا مقدار شمارندهی فعلی برابر با تعداد صفحات باشد، دکمهای با مقدار شمارنده درج میکنیم.
در غیر اینصورت، اگر مقدار شمارنده کوچکتر از شمارهی صفحهی فعلی باشد و $leftDots
برابر با false
باشد، یک دکمهی ...
درج کرده و $leftDots
را true
میکنیم.
در غیر اینصورت، اگر مقدار شمارنده بزرگتر از شمارهی صفحهی فعلی باشد و $rightDots
برابر با false
باشد، یک دکمهی ...
درج کرده و $rightDots
را true
میکنیم.
کد این بخش بهصورت زیر خواهد بود:
اخیراً کارمندان دیجیکالا تصمیم گرفتهاند که پستهای وبلاگشان را با فرمت مارکداون بنویسند. مارکداون یک زبان نشانهگذاری برای قالببندی متن با امکان تبدیل به فرمتهای مختلف از جمله HTML است. با استفاده از مارکداون بهراحتی میتوان تیتر، متنهای bold ، italic ، نقلقول و... ایجاد کرد. از مارکداون در وبسایتهایی نظیر GitHub نیز استفاده میشود. برای کسب اطلاعات بیشتر دربارهی مارکداون به اینجا مراجعه کنید.
از شما میخواهیم کلاسی برای تبدیل مارکداون به HTML با بهرهگیری از عبارات باقاعده (Regex) پیادهسازی کنید.
پروژهی اولیه را میتوانید از اینجا دانلود کنید.
RuleInterface
🔗برای مدیریت روشهای تبدیل مارکداون به HTML ، اینترفیسی با نام RuleInterface
ایجاد کردهایم؛ زیرا ممکن است در آینده با روشی غیر از عبارات باقاعده فرایند تبدیل را انجام دهیم. این اینترفیس شامل یک متد با نام parse
است که باید رشتهای شامل محتوای مارکداون را دریافت کرده و خروجی موردنظر را برگرداند.
RegexRuleInterface
🔗این اینترفیس از اینترفیس RuleInterface
پیروی کرده و وظیفهی آن، مدیریت قواعد مختلف برای تبدیل مارکداون به HTML است. متدی با نام rule
در این اینترفیس وجود دارد که باید رشتهای شامل یک عبارت باقاعده برای تشخیص یکی از عناصر مارکداون را برگرداند.
RegexRule
🔗این کلاس، اینترفیس RegexRuleInterface
را پیادهسازی میکند. متدی انتزاعی با نام replacement
در این کلاس موجود است که باید رشتهای شامل عبارتی که قرار است جایگزین نتایج اجرای عبارت باقاعده روی محتوای مارکداون شود را برگرداند.
MarkdownParser
🔗این کلاس با استفاده از نمونههایی از کلاسهای مختلف که از کلاس RegexRule
ارثبری میکنند، محتوای مارکداون را به HTML تبدیل میکند. متدی با نام render
در این کلاس وجود دارد که یک رشتهی مارکداون دریافت کرده و خروجی HTML آن را برمیگرداند.
در حال حاضر از هفت عنصر مختلف در مارکداون استفاده میکنیم که باید قوانین استخراج و جایگزینی آنها را پیادهسازی کنید. همهی این قوانین باید تحت قالب کلاسهایی مجزا که از کلاس RegexRule
ارثبری میکنند باشند. هر کدام از این کلاسها، دو متد rule
و replacement
را خواهند داشت و هر کلاس باید در فایلی همنام با نام کلاس پیادهسازی شود.
Header
): این کلاس باید تیترهای موجود در متن را پردازش کند. تیترها در مارکداون از یک الی شش کاراکتر #
بههمراه فضای خالی در ادامهی آنها (بهصورت اختیاری) و نام تیتر تشکیل شدهاند:تیترها را توسط کلاس Header
به تگ h3
تبدیل کنید:
Bold
): این کلاس باید متنهای bold را پردازش کند. متنهای bold در مارکداون بین دو **
یا دو __
قرار میگیرند:متنهای bold را توسط کلاس Bold
به تگ b
تبدیل کنید:
Italic
): این کلاس باید متنهای italic را پردازش کند. متنهای italic در مارکداون بین دو *
یا دو _
قرار میگیرند:متنهای italic را توسط کلاس Italic
به تگ i
تبدیل کنید:
Link
): این کلاس باید لینکها را پردازش کند. لینکها در مارکداون بهصورت زیر هستند:لینکها را توسط کلاس Link
به تگ a
تبدیل کنید:
Image
): این کلاس باید تصاویر را پردازش کند. تصاویر در مارکداون بهصورت زیر هستند:تصاویر را توسط کلاس Image
به تگ img
تبدیل کنید:
Code
): این کلاس باید کدها را پردازش کند. کدها در مارکداون بین دو ` قرار میگیرند:کدها را توسط کلاس Code
به تگ code
تبدیل کنید:
HorizontalRule
): این کلاس باید خطوط افقی را پردازش کنند. خطوط افقی در مارکداون از ۳ یا تعداد بیشتری -
پشت سر هم تشکیل میشوند:خطوط افقی را توسط کلاس HorizontalRule
به تگ hr
تبدیل کنید:
نکته: لزوماً نباید همهی کلاسهای بالا را پیادهسازی کنید. به ازای هر کلاس، امتیاز آن را بهصورت جدا دریافت خواهید کرد.
پس از پیادهسازی کلاسهای بالا، فایلهای زیر را بهصورت Zip ارسال کنید:
عبارت باقاعده برای تشخیص تیتر (با فرض این که کاراکتر #
در متن تیتر موجود نیست) بهصورت زیر است:
برای تبدیل تیتر به HTML ، باید محتویات گروه ۱ را درون تگ h3
قرار داد و نتیجه را جایگزین گروه ۰ کرد. بنابراین کد کلاس Header
بهصورت زیر خواهد بود:
عبارت باقاعده برای تشخیص متنهای bold بهصورت زیر است:
برای تبدیل متن bold به HTML ، باید محتویات گروه ۲ را درون تگ b
قرار داد و نتیجه را جایگزین گروه ۰ کرد. بنابراین، کد کلاس Bold
بهصورت زیر خواهد بود:
عبارت باقاعده برای تشخیص لینک بهصورت زیر است:
برای تبدیل لینک به HTML ، باید محتویات گروه ۱ را درون تگ a
و محتویات گروه ۲ را درون مشخصهی href
تگ a
قرار داد و نتیجه را جایگزین گروه ۰ کرد. بنابراین، کد کلاس Link
بهصورت زیر خواهد بود:
مهدی طرفدار پروژههای خاص و سخت است. اخیراً یکی از دوستان صمیمی او، نیما، سفارش نوشتن یک سایت تبلیغاتی را به او داده است. از آنجا که مهدی نمایندگی فروش هاست و سرور ندارد، از نیما درخواست یک هاست برای میزبانی پروژه کرد. نیما هم این درخواست را با کمال میل قبول کرد و دسترسی یک هاست اشتراکی ساده با کمترین امکانات ممکن را برای مهدی فرستاد. مهدی پس از بررسیهای فراوان، متوجه شد که این هاست حتی قابلیت اتصال به MySQL را هم ندارد! لذا تصمیم گرفت که خودش اطلاعات را در قالب JSON درون فایلهای مختلف نگهداری کند و از آنها استفاده کند.
مهدی فرصت کمی برای انجام این پروژه دارد؛ بنابراین از شما میخواهیم که بخش ذخیرهسازی اطلاعات را برای مهدی بنویسید.
ساختار فایلهایی که اطلاعات در آنها ذخیره میشوند به صورت زیر است:
همهی جداول دیتابیس در یک دایرکتوری مشخص قرار میگیرند. نام هر فایل، نمایانگر نام جدول است. در مثال بالا، سه جدول با نامهای table1
، table2
و table3
وجود دارد.
هر جدول شامل خانهای به نام schema
است و مشخصات مربوط به ستونهای جدول در آن قرار دارند. در schema
هر جدول، مقدار پیشفرض ستونها و امکان null
بودن آنها تعریف میشود. مقدار پیشفرض هر ستون در خانهای به نام default
و امکان null
بودن مقدار ستون به صورت boolean
در خانهای به نام nullable
ذخیره میشود. لزوماً خانهی default
برای ستون تعریف نمیشود، امّا خانهی nullable
برای تمامی ستونها موجود است.
schema
یک جدول:🔗همچنین هر جدول خانهای به نام data
دارد که شامل آرایهای از سطرهای موجود در جدول است.
کل پروژه را در قالب کلاسی به نام JsonDB
با موارد خواستهشدهی زیر پیادهسازی کنید:
متد __construct
را به گونهای پیادهسازی کنید که مسیر اصلی ذخیرهسازی فایلهای جداول را دریافت کند. در صورتی که آدرسی به متد داده نشد، مسیر فعلی اسکریپت بهعنوان مکان ذخیرهسازی فایلهای جداول در نظر گرفته میشود.
متد insert
را به گونهای پیادهسازی کنید که نام جدول و آرایهای از ستونهای سطر موردنظر را دریافت کرده و آن را به انتهای جدول اضافه کند. در صورتی که مقداری برای ستون خاصی تعریف نشود و مقدار پیشفرضی برای آن ستون وجود نداشته باشد و امکان null
بودن ستون وجود نداشته باشد، باید یک Exception
با پیام No value provided for column column_name
(column_name
نام ستون است) throw شود. در صورتی که مقداری برای ستون خاصی تعریف نشود و مقدار پیشفرضی برای آن ستون وجود نداشته باشد و امکان null
بودن مقدار ستون وجود داشته باشد، مقدار null
به عنوان مقدار ستون ذخیره خواهد شد. در صورتی که ستونی به متد داده شود و آن ستون در schema
جدول موجود نباشد، باید یک Exception
با پیام Column column_name not found
(column_name
نام ستون موردنظر است) throw شود.
insert
:🔗select
را به گونهای پیادهسازی کنید که نام جدول و آرایهای از ستونها و مقادیر متناظرشان را دریافت کرده و سطرهایی که مقادیر ستونهایشان با مقادیر ستونهای ورودی یکسان است را در قالب آرایه برگرداند. لزوماً مقادیر همهی ستونها بهعنوان ورودی به متد داده نمیشوند. فرض بر این است که بین شرطها جهت یافتن سطرهای خروجی AND
وجود دارد. در صورتی که ستونی بهعنوان ورودی به متد داده نشود، باید همهی سطرها بهعنوان خروجی تابع return
شود. در صورتی که ستونی به متد داده شود و آن ستون در schema
جدول موجود نباشد، باید یک Exception
با پیام Column column_name not found
(column_name
نام ستون موردنظر است) throw شود.select
:🔗update
مقدار یک یا چند ستون را در سطرهایی که مشخص میکنیم تغییر میدهد. این متد شامل سه آرگومان بوده که آرگومان اول نام جدول موردنظر برای بهروزرسانی است، آرگومان دوم شامل مقادیر جدید ستونهایی است که قرار است تغییر کنند و آرگومان سوم مشخص میکند که ستونهای چه سطرهایی باید تغییر کنند؛ به طوری که هر سطری که مقادیر ستونهایش برابر با مقادیر ستونهای آرگومان سوم باشد باید بهروزرسانی شود. لزوماً مقادیر همهی ستونهای جدول در آرگومانهای دوم و سوّم موجود نیستند. اگر آرگومان سوّم به متد داده نشد، باید همهی سطرهای جدول بهروزرسانی شوند. فرض بر این است که بین شرطها جهت یافتن سطرها جهت بهروزرسانی AND
وجود دارد. در صورتی که ستونی در آرگومان دوم یا سوّم موجود باشد و آن ستون در schema
جدول موجود نباشد، باید یک Exception
با پیام Column column_name not found
(column_name
نام ستون موردنظر است) throw شود.update
:🔗delete
را به گونهای پیادهسازی کنید که نام جدول و آرایهای از ستونها و مقادیر متناظرشان را دریافت کرده و سطرهایی که مقادیر ستونهایشان با مقادیر ستونهای ورودی یکسان است را از جدول حذف کند. لزوماً مقادیر همهی ستونها بهعنوان ورودی به متد داده نمیشوند. فرض بر این است که بین شرطها جهت یافتن سطرها برای حذف AND
وجود دارد. در صورتی که ستونی بهعنوان ورودی به متد داده نشود، باید همهی سطرها از جدول حذف شوند. در صورتی که ستونی به متد داده شود و آن ستون در schema
جدول موجود نباشد، باید یک Exception
با پیام Column column_name not found
(column_name
نام ستون موردنظر است) throw شود.delete
:🔗نکته: در صورتی که جدول موردنظر در هر یک از متدهای insert
، select
، update
یا delete
یافت نشود، باید یک Exception
با پیام Table table_name not found
(table_name
نام جدول موردنظر است) throw شود.
یک فایل PHP که کلاس JsonDB
درون آن قرار دارد آپلود کنید.
بدیهی است که باید یک property برای ذخیرهسازی محل قرارگیری فایلهای جدولها در نظر بگیریم (آن را $db_path
مینامیم). بنابراین، متد __construct
بهصورت زیر خواهد بود:
اگر نام یک جدول برابر با $table_name
باشد، مسیر فایل جدول برابر خواهد بود با:
برای بررسی وجود فایل جدول، میتوان از تابع file_exists
یا is_file
استفاده کرد. در صورت عدم وجود فایل، باید یک Exception
throw کرد:
علت بازگشت مقدار false
، جلوگیری از ادامهی روند اجرای متد در صورت استفاده از try/catch
است.
برای دریافت محتویات فعلی جدول، میتوان از توابع file_get_contents
و json_decode
استفاده کرد:
برای بررسی مطابقت ستونهای جدول با ستونهای ورودی، میتوان از حلقهی foreach
استفاده کرد:
برای بررسی nullable بودن ستونها و مقدار پیشفرض ستونها نیز میتوان از حلقهی foreach
استفاده کرد. در حین پیمایش روی ستونها، اگر مطابقت بین جدول و ستونهای ورودی وجود داشته باشد، مقدار ستون ورودی را درون یک آرایهی موقت نگه میداریم و در غیر اینصورت، یک Exception
throw میکنیم:
در نهایت، آرایهی $row
را به انتهای data
جدول اضافه کرده و با استفاده از تابع file_put_contents
و json_encode
، نتیجه را در فایل ذخیره میکنیم:
برای پیادهسازی متد select
، پس از بررسی وجود جدول، آرگومان دوم را بررسی میکنیم. اگر این آرایه خالی باشد، تمامی سطرهای جدول را برمیگردانیم. در غیر اینصورت، schema
جدول را با آرگومان دوم متد مقایسه میکنیم. اگر ستون نامعتبری یافت شود، یک Exception
با پیغام Column column_name not found
throw میکنیم:
در ادامه، سطرهای موجود در جدول را با آرگومان دوم مقایسه میکنیم. اگر ستونی یافت شود که مقدار آن با آرگومان دوم مغایرت داشته باشد، از آن صرفنظر میکنیم. کد این قسمت بهصورت زیر خواهد بود:
در نهایت، آرایهی $rows
را برمیگردانیم.
برای پیادهسازی متد delete
نیز ابتدا صحت نام جدول و ستونها را بررسی میکنیم:
برای حذف سطرهای موردنظر از جدول، میتوان از تابع array_filter
استفاده کرد. اگر مقادیر ستونهای موجود در آرگومان دوم متد با ستونهای یک سطر مطابقت داشته باشد، آن سطر از ستون حذف میشود.
در پایان، برای ریست کردن key
های جدول، از تابع array_values
استفاده کرده و نتیجه را در فایل جدول ذخیره میکنیم:
مدیر کتابخانهی شهر کدنشینها دستور داده است تا از این پس مدیریت کتابهای موجود در کتابخانه توسط یک سیستم برخط صورت گیرد. قرار بود که یکی از شهروندان شهر کدنشینها این سیستم را طراحی کند، اما ظاهر این سیستم آنقدر پیچیده بهنظرشان آمد که همهی آنها در حین پیادهسازی این پروژه آن را ترک کردند! اکنون از شما میخواهیم تا بخشی از این سیستم را پیادهسازی کنید.
پروژهی اولیه را از اینجا دانلود کنید.
قرار است در این پروژه از پایگاه دادهی MySQL استفاده شود. سه جدول با مشخصات زیر از قبل طراحی شدهاند و شامل سطرهایی بهعنوان مقادیر اولیه هستند:
books
):نام ستون | نوع | توضیح | ملاحظات |
---|---|---|---|
id |
INT(11) |
شناسهی کتاب | UNSIGNED AUTO_INCREMENT PRIMARY KEY |
name |
VARCHAR(255) |
عنوان کتاب | NOT NULL |
author_id |
INT(11) |
شناسهی نویسندهی کتاب | UNSIGNED NOT NULL |
publisher_id |
INT(11) |
شناسهی ناشر کتاب | UNSIGNED NOT NULL |
quantity |
INT(11) |
موجودی کتاب | UNSIGNED NOT NULL |
authors
):نام ستون | نوع | توضیح | ملاحظات |
---|---|---|---|
id |
INT(11) |
شناسهی نویسنده | UNSIGNED AUTO_INCREMENT PRIMARY KEY |
name |
VARCHAR(255) |
نام نویسنده | NOT NULL |
publishers
):نام ستون | نوع | توضیح | ملاحظات |
---|---|---|---|
id |
INT(11) |
شناسهی ناشر | UNSIGNED AUTO_INCREMENT PRIMARY KEY |
name |
VARCHAR(255) |
نام ناشر | NOT NULL |
دسترسی به پایگاه داده از طریق نمونهای از کلاس PDO
صورت میگیرد. این نمونه از طریق کلید DB
توسط کلاس Base
قابل دسترسی است:
فایل موردنیاز برای ساخت جدولها را میتوانید از اینجا دانلود کنید.
در این پروژه، همهی درخواستها به فایل index.php
ارسال میشوند و متد مناسب از یک کنترلر بر اساس URL
صدا زده میشود. چندین route از قبل در پروژه تعریف شدهاند که بهشرح زیر هستند:
GET /
: صفحهی پیشخوانGET /books
: صفحهی لیست کتابهاGET /books/add
: فرم افزودن کتابGET /books/reserve/:id
: رزرو کردن کتابGET /books/unreserve/:id
: افزودن موجودی کتابGET /books/delete/:id
: حذف کتابGET /authors
: صفحهی لیست نویسندگانGET /publishers
: صفحهی لیست ناشرانتابعی با نام redirect
در پروژه تعریف شده است که با استفاده از آن کاربری را به آدرس موردنظر هدایت کرد. مثال:
Flash
🔗از این کلاس برای نمایش پیغام به کاربر پس از هدایت شدن به صفحات دیگر استفاده میشود. متدهای این کلاس را مطابق موارد زیر پیادهسازی کنید:
set($type, $message)
: پیامی با محتوای $message
از نوع $type
(که بهصورت رشته است) را در session کاربر ذخیره میکند.get()
: پیام ذخیرهشده در session کاربر را بهصورت یک آرایهی انجمنی برمیگرداند. هر پیام فقط یک بار پس از redirect شدن کاربر به سایر صفحات نمایش داده میشود. در صورتی که پیامی ذخیره نشده بود، این متد باید مقدار NULL
را برگرداند. نمونهای از خروجی این متد:سه مدل در قالب سه کلاس در دایرکتوری app/Models
موجود هستند که باید متدهای درون آنها را پیادهسازی کنید. همهی این مدلها از کلاس Model
ارثبری میکنند و میتوان فیلدهای آنها را از طریق یک آرایهی انجمنی در constructor آنها مقداردهی کرد. این مدلها و متدهای موردنیاز هر کدام بهشرح زیر هستند:
Book
:id
: شناسهی کتاب (از نوع عدد)name
: نام کتاب (از نوع رشته)author
: نویسندهی کتاب (از نوع آبجکتی از مدل Author
)publisher
: ناشر کتاب (از نوع آبجکتی از مدل Publisher
)quantity
: موجودی کتاب (از نوع عدد صحیح)all()
: همهی کتابهای موجود در جدول books
را در قالب آرایهای از آبجکتهای مدل Book
برمیگرداند.count()
: تعداد همهی کتابها (صرفنظر از موجودیشان) را برمیگرداند.find($id
: کتابی که شناسهی آن برابر با مقدار $id
است را برمیگرداند. در صورتی که چنین کتابی موجود نباشد، باید یک Exception با پیغام Book not found
پرتاب شود.save()
: تغییرات مشخصات کتاب را در جدول ذخیره میکند. تضمین میشود که شناسهی کتاب، شناسهی نویسنده و شناسهی ناشر از قبل موجود است.delete()
: کتابی که شناسهی آن با شناسهی کتاب فعلی برابر است را از جدول حذف میکند. در صورتی که چنین کتابی در جدول موجود نباشد، نباید تغییری صورت گیرد.Author
:id
: شناسهی نویسنده (از نوع عدد)name
: نام نویسنده (از نوع رشته)books_count
: تعداد کتابهای متمایز از این نویسنده (از نوع عدد صحیح)all()
: همهی نویسندگان موجود در جدول authors
که حداقل یک کتاب از آنها در لیست کتابها موجود است را در قالب آرایهای از آبجکتهای مدل Author
برمیگرداند.count()
: تعداد همهی نویسندگانی که حداقل یک کتاب از آنها در لیست کتابهای کتابخانه موجود است را برمیگرداند.Publisher
:id
: شناسهی ناشر (از نوع عدد)name
: نام ناشر (از نوع رشته)books_count
: تعداد کتابهای متمایز از این ناشر (از نوع عدد صحیح)all()
: همهی ناشران موجود در جدول publishers
که حداقل یک کتاب از آنها در لیست کتابها موجود است را در قالب آرایهای از آبجکتهای مدل Publisher
برمیگرداند.count()
: تعداد همهی ناشرانی که حداقل یک کتاب از آنها در لیست کتابهای کتابخانه موجود است را برمیگرداند.کنترلرها وظیفهی دریافت اطلاعات از مدلها، پردازش آنها و ارسال نتایج به viewها را دارند. چهار کنترلر در قالب چهار کلاس در این پروژه موجود هستند که خوشبختانه سه کنترلر از قبل بهطور کامل پیادهسازی شدهاند. متد add
از کنترلر BooksController
را مطابق موارد زیر پیادهسازی کنید:
این متد زمانی فراخوانی میشود که متد درخواست POST باشد. اطلاعات زیر از طریق $_POST
قابل دسترسی خواهند بود:
name
: نام کتابauthor
: نام نویسندهی کتابpublisher
: نام ناشر کتاباگر حداقل یکی از فیلدهای بالا خالی باشند، باید پیغامی از نوع danger
و با محتوای همهی اطلاعات باید وارد شوند.
در session کاربر ذخیره شده و کاربر به آدرس /books/add
هدایت شود.
در صورت مقداردهی شدن همهی فیلدها، کتابی با اطلاعات ورودی در جدول books
با موجودی اولیهی 1
درج کنید. اگر نام نویسندهی کتاب یا نام ناشر کتاب از قبل در جدول authors
یا publishers
موجود باشند، این مقادیر نباید مجدداً به این جداول اضافه شوند و باید از شناسهی قبلی آنها برای درج استفاده شود. پس از درج اطلاعات، باید پیغامی از نوع success
و با محتوای کتاب با موفقیت افزوده شد!
در session کاربر ذخیره شده و کاربر به آدرس /books
هدایت شود.
نمایی از صفحهی اصلی پروژه:
نمایی از صفحهی لیست کتابها:
فایلها و فولدرهای زیر را بدون تغییر در ساختار فولدربندی بهصورت یک فایل Zip ارسال کنید. از سایر فایلها صرفنظر خواهد شد:
برای پیادهسازی کلاس Flash
میتوان هر کلید دلخواهی را در $_SESSION
در نظر گرفت. متد set
این کلید را مقداردهی خواهد کرد و متد get
پس از دریافت مقدار کلید، مقدار پیام را برابر با NULL
قرار میدهد. البته قبل از دریافت مقدار کلید، باید با استفاده از تابع isset
بررسی کرد که آیا این کلید از قبل موجود است یا خیر. کد کلاس Flash
بهصورت زیر خواهد بود:
کوئری دریافت تعداد نویسندگانی که حداقل یک کتاب از آنها ثبت شده بهصورت زیر است:
بنابراین، کد متد count
از کلاس Author
بهصورت زیر خواهد بود:
از آنجا که پس از فراخوانی متد save
اطلاعات نویسنده و ناشر موجود در مدل نیز باید بهروزرسانی شوند، بنابراین کد متد save
در کلاس Book
بهصورت زیر خواهد بود: