介绍 ( Introduction )

When creating API's, we sometimes specify the data we want back in the various controller actions:

创建API时,有时我们会在各种控制器操作中指定要返回的数据:

public function show(Book $book)
{return response()->json(['data' => ['title' => $book->title,'description' => $book->description,'author' => $book->author->name]]);
}

Notice we omitted the attributes created_at and updated_at when formatting the response?

注意在格式化响应时我们省略了created_atupdated_at属性吗?

Take another scenario where we want to update a book and expect a response back.

在另一种情况下,我们想要更新一本书并期望得到回复。

public function update(Request $request, Book $book)
{$book = $book->update($reques->all());return response()->json(['data' => ['title' => $book->title,'description' => $book->description,]]);
}

We still have to format the response for the store() method and probably return the created book as part of the response.

我们仍然必须格式化store()方法的响应,并可能将创建的书作为响应的一部分返回。

If we want the same $book attributes returned in all responses that involve a book resource, there is a high likelihood of forgetting some attribute, especially when working with many attributes. Again having to keep track of these attributes in every controller action that involves a book resource is a hassle. Assuming we have a book component on the frontend that is reused in all the occasions that involve a book resource. We are going to run into a problem when one of the attributes is missing.

如果我们希望在涉及书籍资源的所有响应中返回相同的$book属性,则很可能会忘记某些属性,尤其是在处理许多属性时。 同样,在涉及书籍资源的每个控制器操作中都必须跟踪这些属性,这很麻烦。 假设我们在前端有一个书本组件,该组件在涉及书本资源的所有场合都可以重用。 当缺少其中一个属性时,我们将遇到一个问题。

To handle inconsistencies in API resource responses, we may update the model with what should be returned when we call a model instance.

为了处理API资源响应中的不一致,我们可以使用调用模型实例时应返回的内容来更新模型。

Still working with the book example:

仍在处理书籍示例:

// Book Model
protected $hidden = ['created_at', 'updated_at'];

This means the created_at and updated_at attributes won't be part of the response everytime we call on book resource.

这意味着,每次我们调用书本资源时, created_atupdated_at属性都不会成为响应的一部分。

But then again, how do we go about adding custom attributes that are not part of the original model:

但是再说一次,我们该如何添加不属于原始模型的自定义属性:

@media (max-width: 1280px) { .go-go-gadget-react img:first-child { display: none; } }@media (max-width: 780px) {.go-go-gadget-react { flex-direction: column; }.go-go-gadget-react img { margin-left: 0 !important; margin-bottom: 12px !important; }.header-thingy { margin-top: 20px; }.button-thingy { margin-left: 0 !important; margin-top: 12px !important; }} @media (max-width: 1280px) { .go-go-gadget-react img:first-child { display: none; } }@media (max-width: 780px) {.go-go-gadget-react { flex-direction: column; }.go-go-gadget-react img { margin-left: 0 !important; margin-bottom: 12px !important; }.header-thingy { margin-top: 20px; }.button-thingy { margin-left: 0 !important; margin-top: 12px !important; }}

protected $appends = ['date_stored'];public function getDateStored()
{return (string) $this->created_at->diffForHumans();
}

And that's just one custom attribute. Had we wanted to include many attributes to be part of the model's response, trust me we are going to end up with one bloated model. It's a lot easier to create a dedicated resource to respond with exactly the data one needs.

那只是一个自定义属性。 如果我们想包括许多属性作为模型响应的一部分,请相信我,我们将最终得到一个one肿的模型。 创建专用资源以准确响应一个所需的数据要容易得多。

分形 ( Fractal )

Before Laravel 5.5, Fractal, a third party package was the tool most developers used to format API responses. Fractal provides a presentation and transformation layer for complex data output, the likes found in RESTful APIs, and works really well with JSON. Think of this as a view layer for your JSON/YAML/etc. Fractal encourages good API design, and responses will be consistent across the API.

在Laravel 5.5 Fractal之前,第三方软件包是大多数开发人员用来格式化API响应的工具。 Fractal为复杂数据输出(如在RESTful API中找到的类似对象)提供了表示和转换层,并且与JSON配合得很好。 可以将其视为JSON / YAML / etc的视图层。 Fractal鼓励良好的API设计,并且响应将在整个API中保持一致。

引入Laravel API资源 ( Introducing Laravel API resources )

As of Laravel 5.5, Laravel has the capabilities Fractal offered with very little configuration. Setting up Fractal was a bit of a process - require the package, register service providers, create transform classes and so forth.

从Laravel 5.5开始,Laravel只需很少的配置就可以提供Fractal的功能。 设置Fractal只是一个过程-需要包,注册服务提供者,创建转换类等。

With API resources, developers can easily specify the data they want to be returned per model basis without having to update models or even specifying the attributes they want to be part of the response in the various controller methods.

借助API资源,开发人员可以轻松地按模型指定要返回的数据,而不必更新模型,甚至不必指定希望作为各种控制器方法中响应一部分的属性。

API resources provide a uniform interface that can be used anywhere in the app. Eloquent relationships are also taken care of.

API资源提供了一个统一的界面,可以在应用程序中的任何位置使用。 雄辩的关系也得到照顾。

Laravel provides two artisan commands for generating resources and collections - don't worry about the difference between the two yet, we'll get there in a bit. But for both resources and collections, we have our response wrapped in a data attribute; a JSON response standard.

Laravel提供了两个用于生成resourcescollections手Craft.io命令-不用担心两者之间的区别,我们将在稍后介绍。 但是对于资源和集合,我们的响应都包装在data属性中。 JSON响应标准。

We'll look at how to work with API resources in the next section by playing around with a small project.

在下一节中,我们将通过一个小项目来研究如何使用API​​资源。

先决条件: ( Prerequisites: )

To follow along in this artilce, you need to have the following prerequisites

要遵循本条款,您需要具备以下先决条件

  • Basic Laravel knowledge

    Laravel基础知识

  • A working Laravel development environment. Note, the project is built on Laravel 5.6 which requires PHP >= 7.1.3.

    一个有效的Laravel开发环境。 注意,该项目基于Laravel 5.6构建,需要PHP >= 7.1.3

歌曲API演示 ( Songs API Demo )

Clone this repo and follow the instructions in the README.md to get things up and running.

克隆这个回购协议 ,并按照指示README.md得到的东西和运行。

With the project setup, we can now start getting our hands dirty. Also, since this is a very small project, we won't be creating any controllers and will instead test out responses inside route closures.

通过项目设置,我们现在就可以开始动手了。 另外,由于这是一个很小的项目,我们将不会创建任何控制器,而是测试路由闭包内部的响应。

Let's start by generating a SongResource class:

让我们从生成一个SongResource类开始:

php artisan make:resource SongResource

If we peek inside the newly created resource file i.e. SongResource (Resouce files usually go inside the App\Http\Resources folder), the contents look like this:

如果我们窥视新创建的资源文件(即SongResource)(Resouce 文件通常位于App \ Http \ Resources文件夹中 ),则内容如下所示:

[...]
class SongResource extends JsonResource
{/_*_ Transform the resource into an array.__ @param  \Illuminate\Http\Request  $request_ @return array_/public function toArray($request){return parent::toArray($request);}
}

By default, we have parent::toArray($request) inside the toArray() method. If we leave things at this, all visible model attributes will be part of our response. To tailor the response, we specify the attributes we want to be converted to JSON inside this toArray() method.

默认情况下,我们在toArray()方法中有parent::toArray($request) 。 如果我们搁浅,所有可见的模型属性将成为我们响应的一部分。 为了定制响应,我们在此toArray()方法中指定要转换为JSON的属性。

Let's update the toArray() method to match the snippet below:

让我们更新toArray()方法以匹配下面的代码段:

public function toArray($request)
{return ['id' => $this->id,'title' => $this->title,'rating' => $this->rating,];
}

As you can see, we can access the model properties directly from the $this variable because a resource class automatically allows method access down to the underlying model.

如您所见,我们可以直接从$this变量访问模型属性,因为资源类自动允许方法访问底层模型。

Let's now update the routes/api.php with the snippet below:

现在,使用下面的代码片段更新routes/api.php

# routes/api.php[...]
use App\Http\Resources\SongResource;
use App\Song;
[...]Route::get('/songs/{song}', function(Song $song) {return new SongResource($song);
});Route::get('/songs', function() {return new SongResource(Song::all());
});

If we visit the URL /api/songs/1, we'll see a JSON response containing the key-value pairs we specified in the SongResource class for the song with an id of 1:

如果访问URL /api/songs/1 ,我们将看到一个JSON响应,其中包含我们在SongResource类中为ID为1的歌曲指定的SongResource对:

{data: {id: 1,title: "Mouse.",rating: 3}
}

However, if we try visiting the URL /api/songs, an Exception is thrown Property [id] does not exist on this collection instance.

但是,如果我们尝试访问URL /api/songs ,则会引发异常Property [id] does not exist on this collection instance.

This is because instantiating the SongResource class requires a resource instance be passed to the constructor and not a collection. That's why the exception is thrown.

这是因为实例化SongResource类需要将资源实例传递给构造函数而不是集合。 这就是引发异常的原因。

If we wanted a collection returned instead of a single resource, there is a static collection() method that can be called on a Resource class passing in a collection as the argument. Let's update our songs route closure to this:

如果我们想要返回一个集合而不是单个资源,则可以在传递集合作为参数的Resource类上调用静态的collection()方法。 让我们将歌曲的路由闭合更新为此:

Route::get('/songs', function() {return SongResource::collection(Song::all());
});

Visiting the /api/songs URL again will give us a JSON response containing all the songs.

再次访问/api/songs URL将为我们提供一个包含所有歌曲的JSON响应。

{data: [{id: 1,title: "Mouse.",rating: 3},{id: 2,title: "I'll.",rating: 0}]
}

Resources work just fine when returning a single resource or even a collection but have limitations if we want to include metadata in the response. That's where Collections come to our rescue.

当返回单个资源甚至一个集合时,资源工作得很好,但是如果我们想在响应中包括元数据,则资源会受到限制。 这就是Collections拯救我们的地方。

To generate a collection class, we run:

要生成一个收集类,我们运行:

php artisan make:resource SongsCollection

The main difference between a JSON resource and a JSON collection is that a resource extends the JsonResource class and expects a single resource to be passed when being instantiated while a collection extends the ResourceCollection class and expects a collection as the argument when being instantiated.

JSON资源和JSON集合之间的主要区别在于,资源扩展了JsonResource类,并期望在实例化时传递单个资源,而集合扩展了ResourceCollection类,并期望在实例化时将集合用作参数。

Back to the metadata bit. Assuming we wanted some metadata such as the total song count to be part of the response, here's how to go about it when working with the ResourceCollection class:

回到元数据位。 假设我们希望一些元数据(例如总歌曲数)成为响应的一部分,以下是在使用ResourceCollection类时如何进行处理:

class SongsCollection extends ResourceCollection
{public function toArray($request){return ['data' => $this->collection,'meta' => ['song_count' => $this->collection->count()],];}
}

If we update our /api/songs route closure to this:

如果我们将/api/songs路由闭包更新为此:

[...]
use App\Http\Resources\SongsCollection;
[...]
Route::get('/songs', function() {return new \SongsCollection(Song::all());
});

And visit the URL /api/songs, we now see all the songs inside the data attribute as well as the total count inside the meta bit:

并访问URL /api/songs ,现在我们可以看到data属性中的所有歌曲以及meta位中的总数:

{data: [{id: 1,title: "Mouse.",artist: "Carlos Streich",rating: 3,created_at: "2018-09-13 15:43:42",updated_at: "2018-09-13 15:43:42"},{id: 2,title: "I'll.",artist: "Kelton Nikolaus",rating: 0,created_at: "2018-09-13 15:43:42",updated_at: "2018-09-13 15:43:42"},{id: 3,title: "Gryphon.",artist: "Tristin Veum",rating: 3,created_at: "2018-09-13 15:43:42",updated_at: "2018-09-13 15:43:42"}],meta: {song_count: 3}
}

But we have a problem, each song inside the data attribute is not formatted to the specification we defined earlier inside the SongResource and instead has all attributes.

但是我们有一个问题,data属性中的每首歌曲都没有格式化为我们先前在SongResource中定义的规范,而是具有所有属性。

To fix this, inside the toArray() method, set the value of data to SongResource::collection($this->collection) instead of having $this->collection.

要解决此问题,请在toArray()方法内部,将data值设置为SongResource::collection($this->collection)而不要使用$this->collection

Our toArray() method should now look like this:

我们的toArray()方法现在应如下所示:

public function toArray($request)
{return ['data' => SongResource::collection($this->collection),'meta' => ['song_count' => $this->collection->count()]];
}

You can verify we get the correct data in the response by visiting the /api/songs URL again.

您可以通过再次访问/api/songs URL来验证我们在响应中获得了正确的数据。

What if one wants to add metadata to a single resource and not a collection? Luckily, the JsonResource class comes with an additional() method which lets you specify any additional data you'd like to be part of the response when working with a resource:

如果您想将元数据添加到单个资源而不是集合中怎么办? 幸运的是, JsonResource类带有一个JsonResource additional()方法,该方法使您可以指定在使用资源时希望作为响应一部分的任何其他数据:

Route::get('/songs/{song}', function(Song $song) {return (new SongResource(Song::find(1)))->additional(['meta' => ['anything' => 'Some Value']]);
})

In this case, the response would look somewhat like this:

在这种情况下,响应看起来像这样:

{data: {id: 1,title: "Mouse.",rating: 3},meta: {anything: "Some Value"}
}

###

###

包括关系 ( Including Relationships )

In this project, we only have two models, Album and Song. The current relationship is a one-to-many relationship, meaning an album has many songs and a song belongs to an album.

在这个项目中,我们只有两个模型AlbumSong 。 当前关系是one-to-many关系,这意味着专辑中有很多歌曲,而歌曲属于专辑。

Making an album be part of a song's response is pretty straightforward. Let's update the toArray() method inside the SongResource to take note of the album:

使专辑成为歌曲响应的一部分非常简单。 让我们更新SongResource内部的toArray()方法以记录专辑:

class SongResource extends JsonResource
{public function toArray($request){return [// other attributes'album' => $this->album];}
}

If we want to be more specific in terms of what album attributes should be present in the response, we can create an AlbumResource similar to what we did with songs.

如果我们想更具体地说明响应中应包含哪些专辑属性,则可以创建一个与歌曲相似的AlbumResource。

To create the AlbumResource we run:

要创建AlbumResource我们运行:

php artisan make:resource AlbumResource

Once the resource class has been created, we then specify the attributes we want to be included the response.

创建资源类后,我们然后指定要包含在响应中的属性。

class AlbumResource extends JsonResource
{public function toArray($request){return ['title' => $this->title];}
}

And now inside the SongResource class, instead of doing 'album' => $this->album, we can make use of the AlbumResource class we just created.

现在,在SongResource类中,我们无需使用'album' => $this->album ,而可以使用刚刚创建的AlbumResource类。

class SongResource extends JsonResource
{public function toArray($request){return [// other attributes'album' => new AlbumResource($this->album)];}
}

If we visit the /api/songs URL again, you’ll notice an album will be part of the response. The only problem with this approach is that it brings up the N + 1 query problem.

如果我们再次访问/api/songs URL,您会注意到专辑将成为响应的一部分。 这种方法的唯一问题是它提出了N + 1查询问题。

For demonstration purposes, add the snippet below inside the api/routes file:

出于演示目的,请在api/routes文件内添加以下代码段:

# routes/api.php[...]
\DB::listen(function($query) {var_dump($query->sql);
});

Visit the /api/songs URL again. Notice that for each song, we make an extra query to retrieve the album's details? This can be avoided by eager loading relationships. In our case, update the code inside the /api/songs route closure to:

再次访问/api/songs URL。 请注意,对于每首歌曲,我们都会进行一次额外的查询来检索专辑的详细信息? 可以通过渴望加载关系来避免这种情况。 在我们的例子中,将/api/songs路由闭包内的代码更新为:

return new SongsCollection(Song::with('album')->get());

Reload the page again and you'll notice the number of queries has reduced. Comment out the \DB::listen snippet since we don't need that anymore.

再次重新加载页面,您会发现查询数量有所减少。 注释掉\DB::listen代码段,因为我们不再需要它了。

使用资源时的条件 ( Conditionals When Working With Resources )

Every now and then, we might have a conditional determining the type of response that should be returned.

我们可能时不时地有条件地确定应返回的响应类型。

One approach we could take is introducing if statements inside our toArray() method. The good news is we don't have to do that as there is a ConditionallyLoadsAttributes trait required inside the JsonResource class that has a handful of methods for handling conditionals. Just to mention a few, we have the when(), whenLoaded() and mergeWhen() methods.

我们可以采用的一种方法是在toArray()方法中引入if语句。 好消息是我们不必这样做,因为JsonResource class内部需要一个ConditionallyLoadsAttributes trait ,它具有一些处理条件的方法。 仅举几例,我们有when()whenLoaded()mergeWhen()方法。

We'll only brush through a few of these methods, but the documentation is quite comprehensive.

我们将只介绍其中一些方法,但是文档非常全面。

####

####

whenLoaded()方法 (The whenLoaded() method)

This method prevents data that has not been eager loaded from being loaded when retrieving related models thereby preventing the (N+1) query problem.

此方法可以防止在检索相关模型时加载尚未渴望加载的数据,从而避免了(N+1)查询问题。

Still working with the Album resource as a point of reference (an album has many songs):

仍然使用专辑资源作为参考( 专辑中有很多歌曲 ):

public function toArray($request)
{return [// other attributes'songs' => SongResource::collection($this->whenLoaded($this->songs))];
}

In the case where we are not eager loading songs when retrieving an album, we'll end up with an empty songs collection.

如果我们不希望在检索专辑时加载歌曲,则最终会得到一个空的歌曲集合。

mergeWhen()方法 (The mergeWhen() Method)

Instead of having an if statement that dictates whether some attribute and its value should be part of the response, we can use the mergeWhen() method which takes in the condition to evaluate as the first argument and an array containing key-value pair that is meant to be part of the response if the condition evaluates to true:

我们可以使用mergeWhen()方法代替该if语句来确定某个属性及其值是否应作为响应的一部分,该方法将条件值作为第一个参数,并使用一个包含键值对的数组如果条件评估为true,则表示是响应的一部分:

public function toArray($request)
{return [// other attributes'songs' => SongResource::collection($this->whenLoaded($this->songs)),this->mergeWhen($this->songs->count > 10, ['new_attribute' => 'attribute value'])];
}

This looks cleaner and more elegant instead of having if statements wrapping the entire return block.

这看起来更干净,更优雅,而不是用if语句包装整个返回块。

单元测试API资源 ( Unit Testing API Resources )

Now that we've learnt how to transform our responses, how do we actually verify that the response we get back is what we specified in our resource classes?

现在,我们已经学会了如何转换响应,如何实际验证返回的响应是否是我们在资源类中指定的响应?

Here, we'll write tests verifying the response contains the correct data as well making sure eloquent relationships are still maintained.

在这里,我们将编写测试以验证响应是否包含正确的数据,并确保仍然保持雄辩的关系。

Let's create the test:

让我们创建测试:

php artisan make:test SongResourceTest --unit

Notice I passed the --unit flag when generating the test to tell Laravel this should be a unit test.

注意,在生成测试时我通过了--unit标志,以告知Laravel这应该是单元测试。

Let's start by writing the test to make sure our response from the SongResource class contains the correct data:

让我们从编写测试开始,以确保来自SongResource类的响应包含正确的数据:

[...]
use App\Http\Resources\SongResource;
use App\Http\Resources\AlbumResource;
[...]
class SongResourceTest extends TestCase
{use RefreshDatabase;public function testCorrectDataIsReturnedInResponse(){$resource = (new SongResource($song = factory('App\Song')->create()))->jsonSerialize();}
}

Here, we first create a song resource then call jsonSerialize() on the SongResource to transform the resource into JSON format, as that's what should be sent to our front-end ideally.

在这里,我们首先创建一个歌曲资源,然后在SongResource上调用jsonSerialize()将资源转换为JSON格式,因为这应该理想地发送到我们的前端。

And since we already know the song attributes that should be part of the response, we can now make our assertion:

由于我们已经知道应该作为响应一部分的歌曲属性,因此我们现在可以断言:

$this->assertArraySubset(['title' => $song->title,'rating' => $song->rating
], $resource);

I only matched against two attributes and their corresponding values to keep things simple but you can list as many attributes as you would like.

我只针对两个属性及其对应的值进行了匹配,以使事情保持简单,但是您可以根据需要列出尽可能多的属性。

What about making sure our model relationships are preserved even after converting our models to resources?

在将模型转换为资源后,如何确保保留模型关系又如何呢?

public function testSongHasAlbumRelationship()
{$resource = (new SongResource($song = factory('App\Song')->create(["album_id" => factory('App\Album')->create(['id' => 1])])))->jsonSerialize();
}

Here, we create a song with an album_id of 1 then pass the song on to the SongResource class before finally transforming the resource into JSON format.

在这里,我们创建一首带album_id1的歌曲,然后将其传递给SongResource类,最后将资源转换为JSON格式。

To verify that the song-album relationship is still maintained, we make an assertion on the album attribute of the $resource we just created. Like so:

为了验证歌曲专辑关系是否仍然保持,我们对刚创建的$resource的专辑属性进行断言。 像这样:

$this->assertInstanceOf(AlbumResource::class, $resource["album"]);

Note, however, if we did $this->assertInstanceOf(Album::class, $resource["album"]) our test would fail since we are transforming the album instance into a resource inside the SongResource class.

但是请注意,如果我们执行$this->assertInstanceOf(Album::class, $resource["album"])由于将专辑实例转换为SongResource类内部的资源,我们的测试将失败。

As a recap, we first create a model instance, pass the instance to the resource class, convert the resource into JSON format before finally making the assertions. I hope this helps.

作为回顾,我们首先创建一个模型实例,将该实例传递给资源类,然后将资源转换为JSON格式,最后进行断言。 我希望这有帮助。

回顾 ( Recap )

Congratulations if you have managed to get to this point. We've looked at what Laravel API resources are, how to create them as well as how to test out various JSON responses. If you are the curious type, you can peep inside the JsonResource class and see all the methods that are available to us.

恭喜您成功达到目标。 我们已经研究了Laravel API资源是什么,如何创建它们以及如何测试各种JSON响应。 如果您是一个好奇的类型,则可以在JsonResource类内部进行窥视,并查看所有可用的方法。

Do check the official docs to learn more about API resources. The complete code for this tutorial is available on GitHub.

请检查官方文档以了解有关API资源的更多信息。 本教程的完整代码可在GitHub上找到 。

翻译自: https://scotch.io/tutorials/laravel-eloquent-api-resources

Laravel Eloquent:API资源相关推荐

  1. 使用 TDD 测试驱动开发来构建 Laravel REST API

    TDD 以及敏捷开发的先驱者之一的 James Grenning有句名言: 如果你没有进行测试驱动开发,那么你应该正在做开发后堵漏的事 - James Grenning 今天我们将进行一场基于 Lar ...

  2. 使用 TDD 测试驱动开发来构建 Laravel REST API 1

    TDD 以及敏捷开发的先驱者之一的 James Grenning有句名言: 如果你没有进行测试驱动开发,那么你应该正在做开发后堵漏的事 - James Grenning 今天我们将进行一场基于 Lar ...

  3. 深入理解 Laravel Eloquent(三)——模型间关系(关联)

    Eloquent是什么 Eloquent 是一个 ORM,全称为 Object Relational Mapping,翻译为 "对象关系映射"(如果只把它当成 Database A ...

  4. dingo php,用laravel dingo/api创建简单的api

    这篇文章主要介绍了关于用laravel dingo/api创建简单的api,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 1,修改.env配置文件添加API_STANDARDS_TRE ...

  5. dingo php,详细介绍Laravel+Dingo/Api 自定义响应

    Laravel+Dingo/Api 自定义响应的实现 在最近的开发开发项目中,我使用了Dingo/Api这个第三方Api库. Dingo是个很强大的Api库, 但在开发的过程中,需要自定义响应字段. ...

  6. 【One by One系列】IdentityServer4(二)使用Client Credentials保护API资源

    书接上回,我们将会正式开始介绍IdentityServer4. IdentityServer4是实现了OAuth2.0+OpenId Connect两种协议的优秀第三方库,属于.net生态中的优秀成员 ...

  7. Identity Server 4 - Hybrid Flow - 使用ABAC保护MVC客户端和API资源

    这个系列文章介绍的是Identity Server 4 实施 OpenID Connect 的 Hybrid Flow. 保护MVC客户端: Identity Server 4 - Hybrid Fl ...

  8. rest laravel_如何通过测试驱动开发来构建Laravel REST API

    rest laravel by Kofo Okesola 由Kofo Okesola 如何通过测试驱动开发来构建Laravel REST API (How to build a Laravel RES ...

  9. 七、PHP框架Laravel学习笔记——资源控制器

    一.资源控制器 声明:资源控制器是某个特定场景下的产物,完全理解需要 PHP 项目基础: 比如开发过博客系统,留言帖子系统之类,具有类似思维,否则你懂的-: 只是学习了 PHP 基础,就立刻学习框架的 ...

  10. 用laravel dingo api插件库创建api的一些心得笔记

    用laravel创建api是很多大型项目正在使用的方法,一般他们都是用dingo api插件库来开发自己的api.以下是ytkah用dingo api的一些心得,有需要的朋友可以关注一下 1.安装 因 ...

最新文章

  1. 数学知识--Levenberg-Marquardt算法浅谈
  2. ImageNet训练再创纪录!谷歌提出1个小时训练EfficientNet,准确率高达83%!
  3. 每日一皮:Bug 变 Feature !惊不惊喜,意不意外,刺不刺激!
  4. HDU4658 Integer Partition(整数拆分+判断相同数)
  5. C#实现二叉树--二叉链表结构
  6. C# FolderBrowserDialog 的用法
  7. ADO.NET 快速入门(十五):ADO 应用转换为 ADO.NET
  8. 记一则js替换字符串的问题
  9. php psl标准,psl是什么单位
  10. 深入理解Mysql - 内部架构与模块
  11. 笔记随笔1(webpack,vue-router,vuex)
  12. HTML编程之利用jquery制作长图动画的方法
  13. plaintextedit指定一行一行的高亮显示_RDKit | 基于RDKit的指定原子或键高亮
  14. 2018 年大疆机器学习算法工程师春季提前批笔试题
  15. singleTop对onActivityForResult的影响
  16. 新手学Java,是该用记事本还是IDE?
  17. 海康ehome协议分析(1):前言
  18. iSCSI服务部署网络存储
  19. 杜克大学陈怡然教授转载一篇谈ChatGPT为何无法出现在中国的文章,一针见血
  20. HUAWEI nova 青春版发布会现场探秘 堪称圈内大惊喜

热门文章

  1. 淘宝直通车ROI,投产比怎么算,ROI计算公式
  2. 去除XP桌面图标的阴影
  3. 无线网卡驱动正常却搜索不到无线信号
  4. ft232h引脚_AM3356BZCZD60--越秀--回收各种内存IC
  5. 类工厂模式(TDB)
  6. poi批量导入导出Excel(一、需要建数据库表)
  7. Begging_Rust(译):做算术(第二章)
  8. 用Xenu检查死链发现域名后有//
  9. 软件设计师---数据库系统基础
  10. 蓝牙(四)LMP协议之一