Pai*_*Han 1 php laravel laravel-5
我正在尝试制作一个 api,它会在数据库中创建该单词后返回该单词的类型(名词、代词、动词等)。但是由于某种原因,当我的词汇模型中明确定义了类型方法时,我收到了“调用未定义的方法 Illuminate\Database\Eloquent\Relations\BelongsTo::type()”错误。我没有使用多对多的关系,而是使用一对多的关系(这就是我使用 hasMany() 和belongsTo 的原因)。Type 有很多 Vocabulary 但是 Vocabulary 只有一个 Type 和很多 VocabularyContents 并且 VocabularyContent 只有一个相关的词汇。所以显然没有多对多的关系。很明显,我的问题不是Call to undefined method (laravel 5.2) 的重复。以下是该应用程序的部分代码。
第一个模型是类型模型,它允许我获取类型的“内容”(此处未列出模型)和属于特定类型的词汇表。
模型代码清单 1:VocType.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class VocType extends Model
{
public function contents()
{
return $this->hasMany('App\VocTypeContent');
}
public function vocabularies()
{
return $this->hasMany('App\VocVocabulary');
}
}
Run Code Online (Sandbox Code Playgroud)
这第二个模型允许我在词汇表中创建一个词,访问它的“内容”、类型和类别。这就是问题所在。
模型代码清单 2:VocVocabulary.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class VocVocabulary extends Model
{
protected $fillable = ['voc_category_id','type_id', 'name', 'context', 'picture'];
public $timestamps = false;
public function contents()
{
return $this->hasMany('App\VocVocabularyContent');
}
public function type()
{
return $this->belongsTo('App\VocType');
}
public function category()
{
return $this->belongsTo('App\VocCategory');
}
}
Run Code Online (Sandbox Code Playgroud)
第三个模型允许我创建词汇表的内容并访问它的父词汇表。
模型代码清单 3:VocVocabularyContent.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class VocVocabularyContent extends Model
{
protected $fillable = ['voc_vocabulary_id','lang_id', 'content', 'context', 'romanization', 'pronunciation', 'audio'];
public $timestamps = false;
public function vocabulary()
{
return $this->belongsTo('App\VocVocabulary');
}
}
Run Code Online (Sandbox Code Playgroud)
下面是用于上面列出的模型的三个迁移。
迁移代码清单 1:create_voc_types_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVocTypesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('voc_types', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('abbreviation');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('voc_types');
}
}
Run Code Online (Sandbox Code Playgroud)
迁移代码清单 2:create_voc_vocabularies_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVocVocabulariesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('voc_vocabularies', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('cat_id');
$table->unsignedInteger('type_id');
$table->foreign('cat_id')->references('id')->on('voc_categories')->onDelete('cascade');
$table->foreign('type_id')->references('id')->on('voc_types')->onDelete('cascade');
$table->string('name');
$table->string('context');
$table->string('picture');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('voc_vocabularies');
}
}
Run Code Online (Sandbox Code Playgroud)
迁移代码清单 3:create_voc_vocabulary_contents_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVocVocabularyContentsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('voc_vocabulary_contents', function (Blueprint $table) {
$table->primary(['voc_id', 'lang_id']);
$table->unsignedInteger('voc_id');
$table->unsignedInteger('lang_id');
$table->foreign('voc_id')->references('id')->on('voc_vocabularies')->onDelete('cascade');
$table->foreign('lang_id')->references('id')->on('languages')->onDelete('cascade');
$table->string('content');
$table->string('context');
$table->string('romanization');
$table->string('pronunciation');
$table->string('audio');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('voc_vocabulary_contents');
}
}
Run Code Online (Sandbox Code Playgroud)
这是我调用词汇表的 type() 方法的控制器。基本上我有一个 html 表单,它向这个控制器的方法 (postVocabularyAPI) 发送一个 post 请求,如果请求中没有提供 id,将创建一个词汇表(如果语言是英语)。然后,无论请求是否提供了 id,该方法都会为给定的 id 创建一个词汇“内容”(如果没有提供 id,则给定的 id 将是先前创建的词汇的 id)。然后 postVocabularyAPI 方法将返回一个 json 响应,其中包含词汇表类型的 id。
控制器代码清单 1:Vocabulearn.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Language;
use App\VocTheme;
use App\VocCategory;
use App\VocCategoryContent;
use App\VocVocabulary;
use App\VocVocabularyContent;
use App\VocType;
class Vocabulearn extends Controller
{
//other methods above
public function postVocabularyAPI(Request $request, $language, $theme, $category){
$vocabulary_id = $request->vocabulary_id;
if($vocabulary_id === NULL){
if($language == "english"){
$vocabulary = VocVocabulary::create([
'voc_category_id' => VocCategory::where("slug", $category)->get()->first()->id,
'type_id' => VocType::where("abbreviation", $request->type)->get()->first()->id,
'name' => ucfirst(addslashes($request->translation)),
'context' => $request->context,
'picture' => ''
]);
$vocabulary_id = $vocabulary->id;
} else {
echo '{"success":false, "message":"Create first the English Vocabulary"}';
}
}
$vocabularyContent = VocVocabularyContent::where('lang_id', '=', Language::where("slug", $language)->get()->first()->id)
->where('voc_vocabulary_id', '=', $vocabulary_id)
->first();
if($vocabularyContent !== NULL){
$vocabularies = DB::table('voc_vocabulary_contents')
->where('lang_id', '=', Language::where("slug", $language)->get()->first()->id)
->where('voc_vocabulary_id', '=', $vocabulary_id)
->delete();
}
$vocabularyContent = VocVocabularyContent::create([
'voc_vocabulary_id' => $vocabulary_id,
'lang_id' => Language::where("slug", $language)->get()->first()->id,
'content' => ucfirst(addslashes($translation)),
'context' => addslashes($context),
'romanization' => strtolower(addslashes($romanization)),
'pronunciation' => $pronunciation,
'audio' => $request->audio
]);
echo '{"success":true, "type":"'.stripslashes(html_entity_decode($vocabularyContent->vocabulary()->type()->id)).'"}';
}
}
Run Code Online (Sandbox Code Playgroud)
这样做给了我一个
“调用未定义的方法 Illuminate\Database\Eloquent\Relations\BelongsTo::type()”
即使我改变
echo '{"success":true, "type":"'.stripslashes(html_entity_decode($vocabularyContent->vocabulary()->type()->id)).'"}';
Run Code Online (Sandbox Code Playgroud)
经过
echo '{"success":true, "type":"'.stripslashes(html_entity_decode($vocabularyContent->vocabulary()->get()->first()->type()->id)).'"}';
Run Code Online (Sandbox Code Playgroud)
我收到一个错误说明
“在 null 上调用成员函数 type()”
这是不对的,因为数据库已正确填充,所以我不应该得到空词汇。
有一个快速的解决方案。
首先在VocVocabulary模型type函数中添加外键
public function type()
{
return $this->belongsTo('App\VocType', 'type_id');
}
Run Code Online (Sandbox Code Playgroud)
然后去掉括号
echo $vocabularyContent->type->id;
Run Code Online (Sandbox Code Playgroud)
但这不是做到这一点的标准方法。您需要以标准方式设置您的关系,以帮助 Laravel 理解您的关系。
首先,您需要将函数名称更改为模型名称的驼峰式。例如,因为您的类型模型名称是VocType这样您的type功能应该更改为
public function type()
Run Code Online (Sandbox Code Playgroud)
到
public function vocType()
{
return $this->belongsTo('App\VocType'); //you don't need a foreign key here
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您告诉 laravel 该函数vocType是针对VocType模型的。此外,您需要更改的表的外键VocVocabulary的type_id到voc_type_id。通过这种方式,Laravel 清楚地了解您的关系,否则您需要付出额外的努力来教 Laravel 了解您的关系。
| 归档时间: |
|
| 查看次数: |
10685 次 |
| 最近记录: |