איך מעצבים הגבלות לתוכניות מנוי

בדרך כלל אני שומר את תוכנית המנוי של המשתמש בטבלת users, למשל בעמודה plan_id שמפנה לתוכניות המנוי.

בואו נכין לזה במה…

תוכניות המנוי שלנו.php

return [

	cheap_plan ⇒ [

		‘maximum_list’ ⇒ 20,

	],

	expensive_plan ⇒ [

		‘maximum_list’ ⇒ 50,

	],

];

ואז אפשר להשתמש בזה ב-controller כך (בהנחה שרק משתמשים מחוברים יכולים לגשת ל-endpoint הזה)

public function create()
{
	$postCount = Auth::user()->loadCount('posts')->posts_count;

	if ($postCount > Auth::user()->plan->maximum_list) {
		abort(403, "You've reached your maximum list. Please upgrade your plan.");
	}

	// proceed to create the list
	// $list = List::create(...)

	// return redirect()->route('lists.show', ['list' => $list]);
}

זו דרך תקינה, ולדעתי ברוב היישומים היא עושה את העבודה כשצריך לאמת את מגבלת היצירה.

אבל, כפי שציינתם, יש גם גישה "ריכוזית" יותר.

שימוש ב-Gate וב-Policy.

בואו נעשה refactor לקוד הקודם ל-Gate

// AuthServiceProvider.php

class AuthServiceProvider extends ServiceProvider
{
	//

	public function boot()
	{
		$this->registerPolicies();

		Gate::define('create-list', function($user) {
			$postCount = Auth::user()->loadCount('posts')->posts_count;

			if ($postCount > Auth::user()->plan->maximum_list) {
				return Response::deny("You've reached your maximum list. Please upgrade your plan.");
			}

			return Response::allow();
		});
	}
}

וב-controller אפשר לעשות refactor כך

public function create()
{
	$this->authorize('create-list');
	// or Gate::allows('create-list');
	// or Gate::inspect('create-list'); // if you want more customized response.

	// proceed to create the list
	// $list = List::create(...)

	// return redirect()->route('lists.show', ['list' => $list]);
}

זה כבר אמור לענות על הצרכים שלכם. אבל אולי יש דרך מחמירה יותר?

אתם צודקים. שימוש ב-Policy.

אומרים ש-Policy מתאים יותר כשמתעסקים ב"משאב" או במודלים בדומיין, כמו מודל List במקרה שלנו.

ו-Gate מתאים יותר כשמתעסקים ב"פעולה".

אבל לדעתי האישית כדאי להשתמש ב-Policy בכל פעם שאפשר, כי… חוץ מזה שזה נותן תירוץ ליצור קבצים נפרדים, זה גם לא מלכלך את AuthServiceProvider… (אגב, אני לא ממש אוהב לשנות את ה-service provider, אלא אם באמת צריך).

בואו נעשה refactor לקוד הקודם ל-Policy

class ListPolicy
{
	use HandlesAuthorization;

	public function create(User $user)
	{
		$postCount = Auth::user()->loadCount('posts')->posts_count;

		if ($postCount > Auth::user()->plan->maximum_list) {
			return Response::deny("You've reached your maximum list. Please upgrade your plan.");
		}

		return Response::allow();
	}

}

שמתם לב שהמתודה מחקה את ה-resource controller? לדעתי זה מכוון מצד צוות Laravel. כל הכבוד להם.

ואפשר פשוט להשתמש בזה ב-controller כך

public function create()
{
	$this->authorize('create', List::class);
	// or Gate::allows('create-list', List::class);
	// or Gate::inspect('create-list', List::class); // if you want more customized response.

	// proceed to create the list
	// $list = List::create(...)

	// return redirect()->route('lists.show', ['list' => $list]);
}

ה-List::class נמצא שם רק כדי לעזור ל-Laravel להסיק באיזו מחלקת Policy להשתמש.

בסך הכול, בדרך הזו אפשר להימנע מהבעיות שבהן… אפשר ממש ליצור את הרשימה מ-10 controllers שונים. פשוט שמים שם את $this->authorize() ומסיימים.

להמשך קריאה: How To Build Your Own Content Management System (Like WordPress), או הכירו את Sawir Renew, תוסף המנויים החינמי ל-WooCommerce, בתוספי WordPress שלנו.

למדתם משהו מהפוסט הזה?

אשמח לקבל את כתובת האימייל שלכם, כדי לשלוח לכם פוסטים נוספים כמו זה בכל פעם שמתפרסם פוסט חדש.

    לא אשלח לכם ספאם. אפשר לבטל את המנוי בכל עת.