3 回答

TA貢獻1827條經(jīng)驗 獲得超9個贊
首先,讓我們穩(wěn)定一下:
來自 PHP 的類型雜耍: ...變量的類型由使用該變量的上下文決定。
洞察力的簡單示例:
$thisIsAnObject = new Object;
echo $thisIsAnObject;
// as echo expects a string, PHP will attempt to cast it to string and it
// will fail with a message similar to: "Object could not be converted to string"
然而,Laravel,特別是在 中Illuminate\Support\Collection,接管了這種自動轉(zhuǎn)換并以其需要的類型提供上下文。
洞察力的簡單示例:
$simpleCollection = collect([['key' => 'value'],['key' => 'value']]);
echo $simpleCollection;
// instead of letting it error, laravel feeds the echo statement with the json
// representation of the collection (which is a string): [{"key":"value"},{"key":"value"}]
// check Illuminate\Support\Collection::__toString() function
Laravel 對以下內(nèi)容完全相同foreach:
$collection = Question::latest()->paginate(15);
foreach ($collection as $model) {}
// collection feeds the foreach an array of models for better manusing.
// check Illuminate\Support\Collection::toArray() function
總而言之,請注意QuestionResource的映射發(fā)生在toArray()函數(shù)內(nèi)部。
所以這:
$questionResource = QuestionResource::collection(Question::latest()->paginate(15));
如果您使用$questionResource上述內(nèi)容提供 foreach ,則框架的意圖是為 foreach 提供其集合模型的數(shù)組,而忽略您將所有內(nèi)容轉(zhuǎn)換為帶有QuestionResource's 的原始數(shù)組的意圖->toArray()。
但是,例如,如果您要傳遞$questionResource給json_encode()需要字符串且不涉及任何循環(huán)的函數(shù),則框架可以首先解析QuestionResource's->toArray()然后將其轉(zhuǎn)換為集合的 json 表示形式。
這就是你上面的代碼發(fā)生的事情。
我將寫兩種解決這個問題的方法,從最快到最好:
1) 調(diào)用 ->toArray() 預先強制轉(zhuǎn)換
$questions = $this->apiController->index()->toArray(request());
@forelse ($questions as $question)
<a href="#" class="list-group-item">
<h4>{{$question['title']}}</h4>
<p>{{Str::limit($question['body'], 100)}}</p>
<span>Asked {{$question['created']}} by {{$question['user_name']}}</span>
</a>
@empty
<h2>No questions!</h2>
@endforelse
2)為您的問題模型中的created和user_name字段創(chuàng)建一個訪問器
class Question extends Model
{
// $this->created
public function getCreatedAttribute()
{
return $this->created_at->diffForHumans();
}
// $this->user_name
public function getUserNameAttribute()
{
return $this->user->name;
}
}
像這樣,您通過在任何有問題模型實例的地方都可以使用這些字段來持久化這些字段。當然,這包括QuestionResource.
class QuestionResource extends JsonResource
{
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'path' => $this->path,
'body' => $this->body,
'created' => $this->created,
// 'modified' => $this->modified_at,
'user_name' => $this->user_name,
'user_id' => $this->user_id
];
}
}
@forelse ($questions as $question)
<a href="#" class="list-group-item">
<h4>{{$question->title}}</h4>
<p>{{Str::limit($question->body, 100)}}</p>
<span>Asked {{$question->created}} by {{$question->user_name}}</span>
{{json_encode($question)}}
</a>
@empty
<h2>No questions!</h2>
@endforelse
希望能幫助到你。

TA貢獻1868條經(jīng)驗 獲得超4個贊
我認為您對 API 和 Web 響應有點困惑。
首先定義QuestionResourceAPI 資源,這很好,并且created正確放置了屬性。
如果然后查看視圖文件,您正在迭代一個集合,其中每個對象都是一個QuestionResource對象類型。
要獲得您想要的屬性,您應該打印出來,{{ $question->created_at->diffForHumans() }}因為您仍在與模型進行神奇的交互Question。
快速深入的解釋
使用 API 資源時,您應該記住,PHP Object -> JSON string轉(zhuǎn)換發(fā)生在控制器處理請求之后和路由器組件向用戶發(fā)送響應之前的后期階段,如果您從另一個方法調(diào)用您的方法,您仍然沒有經(jīng)歷了 json 轉(zhuǎn)換過程,因為它最終是核心代碼后期階段的一部分。
這意味著$question您從$this->apiController->index()調(diào)用中獲得的返回值會為您提供 的集合QuestionResource,而不是響應的 json 字符串。
要了解Question即使您有一個QuestionResource對象數(shù)組,您如何仍然可以訪問模型,您必須查看JsonResourcelaravel 核心中的類。
laravel 中的每個 API 資源類都繼承自它。此類使用DelegateToResource定義此方法的特征(在 Laravel 的核心中也定義了該特征):
/**
* Dynamically get properties from the underlying resource.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
return $this->resource->{$key};
}
這意味著當你有一個$question類型的對象時,QuestionResource你仍然可以通過簡單地“假裝”你的資源對象是一個問題來訪問底層資源,因為它會像這樣運行并且會自動將所有方法調(diào)用和讀取的屬性轉(zhuǎn)發(fā)到問題模型。
如果您質(zhì)疑您告訴 將模型本身QuestionResource包裝在何處Question,您可以在 index 方法的 return 指令中做到這一點:
return QuestionResource::collection(Question::latest()->paginate(15));
您可以將此返回指令視為Question您作為參數(shù)傳遞給更大對象(QuestionResource類)中的每個模型的“簡單”包裝,該對象添加了一個方法以將問題表示為數(shù)組,因此將用于將模型轉(zhuǎn)換為 json在稍后階段(正如我之前提到的)。
因此,要在@foreach循環(huán)中正確檢索字段,您必須引用模型屬性的名稱,而不是您定義為toArray()方法返回的名稱,因為這將在稍后階段執(zhí)行。
那么,為什么要{{json_encode($question)}}輸出資源中定義的字段呢?
因為JsonResourceclass 實現(xiàn)了 PHP 的JsonSerializable接口,這意味著它實現(xiàn)了jsonSerialize方法(由接口定義)來強制 json 轉(zhuǎn)換。
當您調(diào)用json_encode方法時,php 將識別$question實現(xiàn)該接口并因此是可序列化的,因此它調(diào)用該jsonSerialize方法并獲取所需的字符串。
結(jié)果,您獲得了 api 資源輸出并轉(zhuǎn)換為 json,并且該輸出具有您在QuestionResource類中定義的字段

TA貢獻1776條經(jīng)驗 獲得超12個贊
這些解決方案對我有用:
只需撥打
json_encode
和json_decode
在我的網(wǎng)站上QuestionController
。很簡單,不會產(chǎn)生太多的開銷。但這是一種解決方法。在
Question
Model
類中指定屬性獲取訪問器。微妙的。而Model
類是定義存取正確的地方?,F(xiàn)在我確實使用了該解決方案。
#1 的代碼:
public function index()
{
$str = json_encode($this->apiController->index());
$questions = json_decode($str);
return View::make('question.index')->with('questions', $questions);
}
#2 的代碼:
// in Question model class...
// $this->created
public function getCreatedAttribute()
{
return $this->created_at->diffForHumans();
}
// $this->user_name
public function getUserNameAttribute()
{
return $this->user->name;
}
- 3 回答
- 0 關(guān)注
- 166 瀏覽
添加回答
舉報