مهدی طرفدار پروژههای خاص و سخت است. اخیراً یکی از دوستان صمیمی او، نیما، سفارش نوشتن یک سایت تبلیغاتی را به او داده است. از آنجا که مهدی نمایندگی فروش هاست و سرور ندارد، از نیما درخواست یک هاست برای میزبانی پروژه کرد. نیما هم این درخواست را با کمال میل قبول کرد و دسترسی یک هاست اشتراکی ساده با کمترین امکانات ممکن را برای مهدی فرستاد. مهدی پس از بررسیهای فراوان، متوجه شد که این هاست حتی قابلیت اتصال به _MySQL_ را هم ندارد! لذا تصمیم گرفت که خودش اطلاعات را در قالب _JSON_ درون فایلهای مختلف نگهداری کند و از آنها استفاده کند.
مهدی فرصت کمی برای انجام این پروژه دارد؛ بنابراین از شما میخواهیم که بخش ذخیرهسازی اطلاعات را برای مهدی بنویسید.
# جزئیات پروژه
ساختار فایلهایی که اطلاعات در آنها ذخیره میشوند به صورت زیر است:
```
db_files
├── table1.json
├── table2.json
└── table3.json
```
همهی جداول دیتابیس در یک دایرکتوری مشخص قرار میگیرند. نام هر فایل، نمایانگر نام جدول است. در مثال بالا، سه جدول با نامهای `table1`، `table2` و `table3` وجود دارد.
هر جدول شامل خانهای به نام `schema` است و مشخصات مربوط به ستونهای جدول در آن قرار دارند. در `schema` هر جدول، مقدار پیشفرض ستونها و امکان `null` بودن آنها تعریف میشود. مقدار پیشفرض هر ستون در خانهای به نام `default` و امکان `null` بودن مقدار ستون به صورت `boolean` در خانهای به نام `nullable` ذخیره میشود. لزوماً خانهی `default` برای ستون تعریف نمیشود، امّا خانهی `nullable` برای تمامی ستونها موجود است.
### مثالی از `schema` یک جدول:
```json
{
"first_name": {
"nullable": false
},
"last_name": {
"nullable": true
},
"country": {
"nullable": true,
"default": "Iran"
}
}
```
همچنین هر جدول خانهای به نام `data` دارد که شامل آرایهای از سطرهای موجود در جدول است.
### مثالی از یک جدول:
```json
{
"schema": {
"first_name": {
"nullable": false
},
"last_name": {
"nullable": true
},
"country": {
"nullable": true,
"default": "Iran"
}
},
"data": [{
"first_name": "John",
"last_name": "Smith",
"country": "U.S."
}, {
"first_name": "Ali",
"last_name": null,
"country": "Iran"
}]
}
```
کل پروژه را در قالب کلاسی به نام `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`:
```php
$db = new JsonDB(__DIR__ . '/db');
$db->insert('users', ['first_name' => 'Ali', 'last_name' => 'AliZadeh', 'country' => 'Iran']);
$db->insert('users', ['first_name' => 'Ali', 'last_name' => 'AliZadeh']);
$db->insert('users', ['last_name' => 'AliZadeh', 'country' => 'Iran']); // Exception: No value provided for column first_name
```
+ متد `select` را به گونهای پیادهسازی کنید که نام جدول و آرایهای از ستونها و مقادیر متناظرشان را دریافت کرده و سطرهایی که مقادیر ستونهایشان با مقادیر ستونهای ورودی یکسان است را در قالب آرایه برگرداند. لزوماً مقادیر همهی ستونها بهعنوان ورودی به متد داده نمیشوند. فرض بر این است که بین شرطها جهت یافتن سطرهای خروجی `AND` وجود دارد. در صورتی که ستونی بهعنوان ورودی به متد داده نشود، باید همهی سطرها بهعنوان خروجی تابع `return` شود. در صورتی که ستونی به متد داده شود و آن ستون در `schema` جدول موجود نباشد، باید یک `Exception` با پیام `Column column_name not found` (`column_name` نام ستون موردنظر است) _throw_ شود.
### مثالی از فراخوانی متد `select`:
```php
$db = new JsonDB(__DIR__ . '/db');
$db->select('users');
/*
[
[
'first_name' => 'Ali',
'last_name' => 'AliZadeh',
'country' => 'Iran'
],
[
'first_name' => 'John',
'last_name' => 'Smith',
'country' => null
]
]
*/
$db->select('users', ['first_name' => 'Ali']);
/*
[
[
'first_name' => 'Ali',
'last_name' => 'AliZadeh',
'country' => 'Iran'
]
]
*/
$db->select('users', ['first_name' => 'Ali', 'country' => null]);
/*
[]
*/
$db->insert('users', ['invalid_column' => 'Sample Value', 'country' => 'Iran']); // Exception: Column invalid_column not found
```
+ متد `update` مقدار یک یا چند ستون را در سطرهایی که مشخص میکنیم تغییر میدهد. این متد شامل سه آرگومان بوده که آرگومان اول نام جدول موردنظر برای بهروزرسانی است، آرگومان دوم شامل مقادیر جدید ستونهایی است که قرار است تغییر کنند و آرگومان سوم مشخص میکند که ستونهای چه سطرهایی باید تغییر کنند؛ به طوری که هر سطری که مقادیر ستونهایش برابر با مقادیر ستونهای آرگومان سوم باشد باید بهروزرسانی شود. لزوماً مقادیر همهی ستونهای جدول در آرگومانهای دوم و سوّم موجود نیستند. اگر آرگومان سوّم به متد داده نشد، باید همهی سطرهای جدول بهروزرسانی شوند. فرض بر این است که بین شرطها جهت یافتن سطرها جهت بهروزرسانی `AND` وجود دارد. در صورتی که ستونی در آرگومان دوم یا سوّم موجود باشد و آن ستون در `schema` جدول موجود نباشد، باید یک `Exception` با پیام `Column column_name not found` (`column_name` نام ستون موردنظر است) _throw_ شود.
### مثالی از فراخوانی متد `update`:
```php
$db = new JsonDB(__DIR__ . '/db');
$db->select('users');
/*
[
[
'first_name' => 'Ali',
'last_name' => 'AliZadeh',
'country' => 'Iran'
],
[
'first_name' => 'John',
'last_name' => 'Smith',
'country' => null
]
]
*/
$db->update('users', ['first_name' => 'Mohammad'], ['first_name' => 'Ali']);
$db->select('users');
/*
[
[
'first_name' => 'Mohammad',
'last_name' => 'AliZadeh',
'country' => 'Iran'
],
[
'first_name' => 'John',
'last_name' => 'Smith',
'country' => null
]
]
*/
$db->update('users', ['first_name' => 'Mohammad']);
$db->select('users');
/*
[
[
'first_name' => 'Mohammad',
'last_name' => 'AliZadeh',
'country' => 'Iran'
],
[
'first_name' => 'Mohammad',
'last_name' => 'Smith',
'country' => null
]
]
*/
$db->update('users', ['invalid_column' => 'Test']); // Exception: Column invalid_column not found
```
+ متد `delete` را به گونهای پیادهسازی کنید که نام جدول و آرایهای از ستونها و مقادیر متناظرشان را دریافت کرده و سطرهایی که مقادیر ستونهایشان با مقادیر ستونهای ورودی یکسان است را از جدول حذف کند. لزوماً مقادیر همهی ستونها بهعنوان ورودی به متد داده نمیشوند. فرض بر این است که بین شرطها جهت یافتن سطرها برای حذف `AND` وجود دارد. در صورتی که ستونی بهعنوان ورودی به متد داده نشود، باید همهی سطرها از جدول حذف شوند. در صورتی که ستونی به متد داده شود و آن ستون در `schema` جدول موجود نباشد، باید یک `Exception` با پیام `Column column_name not found` (`column_name` نام ستون موردنظر است) _throw_ شود.
### مثالی از فراخوانی متد `delete`:
```php
$db = new JsonDB(__DIR__ . '/db');
$db->select('users');
/*
[
[
'first_name' => 'Ali',
'last_name' => 'AliZadeh',
'country' => 'Iran'
],
[
'first_name' => 'John',
'last_name' => 'Smith',
'country' => null
]
]
*/
$db->delete('users', ['first_name' => 'Mohammad']);
$db->select('users');
/*
[
[
'first_name' => 'Ali',
'last_name' => 'AliZadeh',
'country' => 'Iran'
],
[
'first_name' => 'John',
'last_name' => 'Smith',
'country' => null
]
]
*/
$db->delete('users', ['first_name' => 'Ali']);
$db->select('users');
/*
[
[
'first_name' => 'John',
'last_name' => 'Smith',
'country' => null
]
]
*/
$db->delete('users');
$db->select('users');
/*
[]
*/
$db->delete('users', ['invalid_column' => 'Test']); // Exception: Column invalid_column not found
```
**نکته:** در صورتی که جدول موردنظر در هر یک از متدهای `insert`، `select`، `update` یا `delete` یافت نشود، باید یک `Exception` با پیام `Table table_name not found` (`table_name` نام جدول موردنظر است) _throw_ شود.
## آنچه باید آپلود کنید
یک فایل _PHP_ که کلاس `JsonDB` درون آن قرار دارد آپلود کنید.
پسر J
مهدی طرفدار پروژههای خاص و سخت است. اخیراً یکی از دوستان صمیمی او، نیما، سفارش نوشتن یک سایت تبلیغاتی را به او داده است. از آنجا که مهدی نمایندگی فروش هاست و سرور ندارد، از نیما درخواست یک هاست برای میزبانی پروژه کرد. نیما هم این درخواست را با کمال میل قبول کرد و دسترسی یک هاست اشتراکی ساده با کمترین امکانات ممکن را برای مهدی فرستاد. مهدی پس از بررسیهای فراوان، متوجه شد که این هاست حتی قابلیت اتصال به 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
درون آن قرار دارد آپلود کنید.