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

[font="Tahoma"][rtl]

شاید خیلی مرسوم نباشه ولی واقعاً بعضی جاها نیاز پیدا میکنید که اکشن یا کلاً متد خاصی از یک کنترلر رو توی یک کنترلر دیگه صدا بزنید. این مسئله بخصوص وقتهایی ضروری میشه که یک کنترلر اصلی داشته باشین که نقش Router رو ایفا میکنه و همه درخواستها به اون میرسه (با کمک urlManager یا htaccess) و حالا توی اون کنترلر اصلی نیاز دارین که برحسب درخواست کاربر، اکشن خاصی رو از کنترلر دیگه، صدا بزنید. مثلاً فرض کنید urlManager رو اینطوری تنظیم کردین:

[/rtl][/font]




'urlManager' => array(

    'urlFormat' => 'path',

    'showScriptName' => false,

    'rules' => array(

        '<action:.+>' => 'site/index',

    ),

),



[font="Tahoma"][rtl]

حالا با چنین کدی توی actionIndex از کنترلر SiteController میتونید کارهای لازم رو برای فراخوانی اکشن مناسب از کنترلر دلخواه انجام بدین:

[/rtl][/font]




class SiteController extends Controller {

    ...

    public function actionIndex() {

        if(isset($_GET['action'])) {

            switch(strtolower($_GET['action'])) {

            case 'users/login':

                list($users) = Yii::app()->createController('users');

                $users->actionLogin();

                break;

            case 'users/register':

                list($users) = Yii::app()->createController('users');

                $users->actionRegister();

                break;

            default:

                $this->render('error');

                break;

            }

        }

    }

    ...

}



[font="Tahoma"][rtl]البته یک روش دیگه هم هست:[/rtl][/font]




class SiteController extends Controller {

    ...

    public function actionIndex() {

        if(isset($_GET['action'])) {

            Yii::import('application.controllers.*');

            switch(strtolower($_GET['action'])) {

            case 'users/login':

                $users = new UsersController;

                $users->actionLogin();

                break;

            case 'users/register':

                $users = new UsersController;

                $users->actionRegister();

                break;

            default:

                $this->render('error');

                break;

            }

        }

    }

    ...

}



[font="Tahoma"][rtl]یا روش بهینه تر:[/rtl][/font]




class SiteController extends Controller {

    ...

    public function actionIndex() {

        if(isset($_GET['action'])) {


            switch(strtolower($_GET['action'])) {

            case 'users/login':

                Yii::import('application.controllers.UserController');

                $users = new UsersController;

                $users->actionLogin();

                break;

            case 'users/register':

                Yii::import('application.controllers.UserController');

                $users = new UsersController;

                $users->actionRegister();

                break;

            default:

                $this->render('error');

                break;

            }

        }

    }

    ...

}



[font="Tahoma"][rtl]این روش از این جهت بهینه تره که برای هر کنترلر، فقط همون رو Import میکنه و به بقیه کنترلرها کاری نداره.

[/rtl][/font]

[right][rtl][font="Tahoma"]

ممنون از اینکه وقت گذاشتید و پست آموزشی نوشتید : ) ولی به نظرم به جز موردی که مثال زدید ـ اون هم در شرایط خاص ـ کلا امر پسندیده ای نیست فراخوانی یک کنترلر در یک کنترلر دیگه. در MVC رفت و آمد بین کنترلر ها مرسوم و توصیه شده نیست. بهتره طراحی طوری صورت بگیره که از این کار اجتناب بشه

[/font][/rtl][/right]

مطلب مفیدی بود، فکر میکنم برای زمانی که بخواهیم متدی را از کنترل دیگری صدا بزنیم روش مناسبی باشد

اما پیشنهاد می کنم در مواردی که قرار است یک اکشن فراخونی شود به آدرس اکشن ریدایرکت کنیم

$this->redirect(array(’/profile/index’));

یا این

header( ‘Location: ‘.Yii::app()->baseUrl.’/profile/index’);

exit;

سپاس

[font="Tahoma"][rtl]

من هم گفتم زیاد مرسوم نیست و همونطور که اشاره کردین، اصولی هم نیست ولی بهرحال بعضی جاها (مثل پیاده سازی RMVC) شاید نیاز بشه چنین کاری انجام بدیم. ضمناً Redirect کردن در اینجا جواب نمیده چون اگه به صفحه موردنظر بریم، با توجه به Ruleهای تعریف شده در urlManager دوباره درخواستها تحویل همین controller/action داده میشه.

[/rtl][/font]

[rtl][font="Tahoma"]قبلاً خیلی دنبال همچین چیزی بودم ولی به جواب قطعی نرسیده بودم.

ممنون بابت مقاله خوبتون

[/font][/rtl]

[font="Tahoma"][rtl]

سلام ممنون از مطلب مفیدتون

البته اشاره به این کردین که از این زمانی استفاده می کنید که یک اکشن نقش روتر رو ایفا کنه ولی احتمال وقوع همچنین تحلیلی برا یک نرم افزار نمی دونم فکر می کنم خیلی کم باشه

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

معمولا برای کدهایی که ممکن است شما در چند کنترلر بطور تکراری استفاده کنید یه library جدا ساخته میشه البته من تو yii تاحالا این کار رو نکردم ولی تو فریم ورک zend کنار library خود zend یه پوشه به اسم core دارم که کلاس های مشترک رو اونجا می نویسم و از توابعشون استفاده می کنم[/rtl][/font]