Laravel如何通过从其他类的控制器中分离出方法以整理代码以供其他控制器重用

时间:2018-08-29 02:10:54

标签: php laravel methods controller

在这种情况下,我在Laravel有CRUD。我正在做的是针对特定受访者的调查。计划是向他们发送包含随机生成的字符串的链接,即:https://larasurvey.app/survey/gewuygde7w6gded8ed7hw,其中gewuygde7w6gded8ed7hw来自tokens表。

因此,我的 Token.php 模型如下所示:

<?php

namespace App\Models\path;

use Illuminate\Database\Eloquent\Model;

class Token extends Model
{
    protected $table = 'tokens';
    protected $connection = 'external';

    /* RELATIONSHIPS */
    public function respondent(){
        return $this->belongsTo(Respondent::class,'respondent_id','id');
    }

    /* METHODS*/
    //Route Model Binding to get the token, instead of the default id, in the survey's URL
    public function getRouteKeyName()
    {
        return 'token';
    }

    /* ... */
}

请注意,我正在使用路由模型绑定来获取令牌,而不是ID。

该调查包括五个部分。每个部分都有一个表格。在这种形式下,我使用的是Select2,这是一个更加动态的选择框。我正在使用几个选择框,这些信息来自目录表。

例如,一个目录是大学列表。当然,我们还没有世界上所有的大学,这就是为什么我使用select2并能够添加新大学的原因(如果大学(表)目录中不存在该大学)。

这是我用于大学选择框的html( blade )代码:

                {{-- University catalog --}}
                <div class="col-lg form-group" id="universities_row">
                    <label for="universities">University</label>
                    <select name="university" id="universities" class="form-control {{ $errors->has('university') ? 'is-invalid' : '' }}" aria-describedby="universityHelpBlock">
                        <option></option>
                        @foreach($universities as $key=>$university)
                            <option value="{{ $university->id }}" {{ old('university') == $university->id ? 'selected' : '' }}>{{ $university->name }}</option>
                        @endforeach
                    </select>
                    @if($errors->has('university'))
                        <div class="invalid-feedback">
                            {{ $errors->first('university') }}
                        </div>
                    @else
                        <small id="universityHelpBlock" class="form-text text-muted">Choose a university</small>
                    @endif
                </div>

这是对应的javascript

$('#universities').select2({
                placeholder: "Type to search. If it doesn't exist, type the new one.",
                tags: true, /*Allows new value*/
                allowClear: true,
                width: '100%',/*Make it responsive*/
            });

您知道,现在在控制器中,当受访者选择一所大学时,请求值$request->university是一个ID。但是,如果用户键入新值,则Select2将返回文本。

我设法告诉了$request->university值是数字还是字符串文本。当不是文本时,我在控制器内创建了另一个方法university_new($university),以便在universities(表)目录中创建新记录,并返回新生成的ID值以进行存储在'university_id'列中。

但是现在的问题是,如何使该方法可用于其他控制器,因为我想将该方法用于调查的其他部分。

这里是(比如) CoursesController.php

<?php

namespace App\Http\Controllers\path\to\survey;

class CoursesController extends Controller
{
   public function store(Token $token, Request $request){
      //validation ...

      //call method to check if the university typed value is a new one or not:
      $university_id = university_new($request->university, $token);

      $course = new Course();
      $course->university_id = $university_id;
      // ... more columns
      $course->save();
   }
   // ...

   /*METHODS*/

        public function university_new($university,$token){
        //Checking whether ID has only numbers or not
        if(!ctype_digit($university)){
            //Check whether there is already one with that name
            $university_exists = University::where('name',$university)->first();
            if($university_exists){
                $university_id = $university_exists->id;
            }else{
                //create new University record:
                $universityNew = new University();
                $universityNew->name=$university;
                $universityNew->notes='Created by respondent: '.$token->respondent->id;
                $universityNew->created_ip=request()->ip();
                $universityNew->save();
                $university_id = $universityNew->id;
            }
        }else{
            //...
            $university_id = $university;
        }
        return $university_id;
    }
}

到目前为止,一切都很好。但是university_new()函数是我想在其他控制器中使用的函数。

我遵循this tutorial的步骤,它首先通过创建一个名为 CourseSaveRequest.php

的验证请求来说明如何实现此目标。
<?php
//Validation when a new course data is saved

namespace App\Http\Requests\path\to\survey;

use App\Models\path\Token;
use Illuminate\Foundation\Http\FormRequest;

class CourseSaveRequest extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        //Check the token
        $token = $this->route('token');
        /*if(Token::where('token',$token)->exists()){
            echo '<p>Found!</p>';
        }else{
            echo '<p>Not found</p>';
        }*/
        //dd($token);
        return Token::where('token',$token)->exists();
        //return false;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'myvalidationsRules'             =>  'required|alpha',
            //...
        ];
    }
}

,然后在名为app/Service的{​​{1}}目录中创建了一个新类,如下所示:

universityCreateService.php

因此,现在在控制器<?php namespace App\Services\path\to\survey; use App\Http\Requests\path\to\CourseSaveRequest; use App\Models\path\to\University; use App\Models\path\Token; class universityCreateService { public function university_new(CourseSaveRequest $request,Token $token){ //Checking whether ID has only numbers or not if(!ctype_digit($request->university)){ //Check whether there is already one with that name $university_exists = University::where('name',$request->university)->first(); if($university_exists){ $university_id = $university_exists->id; }else{ //create new University record: $universityNew = new University(); $universityNew->name=$request->university; $universityNew->notes='Created by respondent: '.$token->respondent->id; $universityNew->created_ip=request()->ip(); $universityNew->save(); $university_id = $universityNew->id; } }else{ //... $university_id = $request->university; } return $university_id; } } 中,我通过向其注入构造函数来调用该类。

修改后的 CoursesController.php

CoursesController.php

现在的问题是,每当我进入本节课程(与class CoursesController extends Controller { private $universityCreateService; public function __construct(universityCreateService $createUniversity){ $this->universityCreateService=$createUniversity; } public function store(Token $token, Request $request){ //validation ... //call method to check if the university typed value is a new one or not: $university_id = $this->universityCreateService->university_new(); //calling the desired method, that is now in another class and injected in this controller. $course = new Course(); $course->university_id = $university_id; // ... more columns $course->save(); } // ... } 相关的所有内容)时,laravel应用程序会将我重定向到首页!

为什么会这样?

该如何解决?

或者是否存在另一种在多个控制器中重用方法的方法?

如何使一种最初位于控制器中的方法可用于其他控制器?

请注意,我使用的是令牌模型,而不是登录名。

否则,我可以扩展控制器,as explained here或在此video tutorial中显示。

0 个答案:

没有答案