本文最初出现在 Cosmic JS Blog中 。
在本教程中,我们将使用Laravel和Vue.js作为前端创建一个简单的库存管理应用程序。 本教程假定您具有面向对象的php和javascript的基础知识,尽管我们将学习Laravel和Vue.js的基础知识,但建议您对它们的概念有基本的了解。 现在,我们已经清除了该问题,启动您的php服务器,让我们来构建一些东西。
TL; DR
入门:
由于这是一个laravel应用程序,因此您将需要创建一个新的laravel项目,确保您的服务器满足laravel服务器要求中所述的laravel要求,并确保服务器上已安装Composer。 一旦安装了作曲家,打开命令行,并进入服务器根目录,然后简单地运行
composer create-project --prefer-dist laravel/ laravel inventory
成功运行后,这将在目录清单中设置一个新的laravel项目。
设置新项目后,您将运行npm install或npm install-如果要在Windows上开发,请使用no-bin-links。 这将下载并设置我们所有的javascript依赖项。 为了能够查看我们的空laravel项目,只需从项目目录运行php artisan serve,这将从我们项目的根目录启动php服务器,然后您可以在浏览器网址中输入http://127.0.0.1:8000应该使用默认的laravel屏幕。
设置Cosmic JS php库
我们将使用Cosmic JS php库中的某些功能,将存储库下载到一个单独的文件夹中,我们将需要对其进行一些编辑才能与laravel一起正常使用。 在inventory/app/
文件夹中,创建一个/Vendor/cosmicjs
文件夹,然后将cosmicjs-php库的所有内容复制到其中,例如, cosmicjs.php
的路径将cosmicjs.php
app/Vendor/cosmicjs/cosmicjs.php
。 然后将app/Vendor/cosmicjs/curl
类重命名为app/Vendor/cosmicjs/cosmiccurl
并更改代码的此顶部:
class Curl {
...
}
至
namespace App \ Vendor \ cosmicjs ;
class CosmicCurl {
....
}
我们所做的是在cosmiccurl文件中添加了一个命名空间,以便我们可以导入laravel并更改类名以匹配文件名。 完成此操作后,替换此部分的cosmicjs.php
include( "curl.php" );
$curl = new Curl;
class CosmicJS {
function __construct ( ) {
global $curl;
global $config;
$ this ->curl = $curl;
$ this ->config = $config;
$ this ->config->bucket_slug = $config->bucket_slug;
$ this ->config->object_slug = $config->object_slug;
$ this ->config->read_key = $config->read_key;
$ this ->config->write_key = $config->write_key;
$ this ->config->url = "https://api.cosmicjs.com/v1/" . $ this ->config->bucket_slug;
$ this ->config->objects_url = $ this ->config->url . "/objects?read_key=" . $ this ->config->read_key;
$ this ->config->object_url = $ this ->config->url . "/object/" . $ this ->config->object_slug . "?read_key=" . $ this ->config->read_key;
$ this ->config->media_url = $ this ->config->url . "/media?read_key=" . $ this ->config->read_key;
$ this ->config->add_object_url = $ this ->config->url . "/add-object?write_key=" . $ this ->config->write_key;
$ this ->config->edit_object_url = $ this ->config->url . "/edit-object?write_key=" . $ this ->config->write_key;
$ this ->config->delete_object_url = $ this ->config->url . "/delete-object?write_key=" . $ this ->config->write_key;
}
与
namespace App \ Vendor \ cosmicjs ;
use App \ Vendor \ cosmicjs \ CosmicCurl ;
class CosmicJS {
private $config;
private $curl;
function __construct ($bucket_slug, $type_slug,$object_slug = "" , $read_key = "" , $write_key = "" ) {
$this ->curl = new CosmicCurl();
$this ->config = new \stdClass();
//$this->config = $config;
$this ->config->bucket_slug = $bucket_slug;
$this ->config->object_slug = $object_slug;
$this ->config->type_slug = $type_slug;
$this ->config->read_key = $read_key;
$this ->config->write_key = $write_key;
$this ->config->url = "https://api.cosmicjs.com/v1/" . $this ->config->bucket_slug;
$this ->config->objects_url = $this ->config->url . "/objects?read_key=" . $this ->config->read_key;
$this ->config->object_type_url = $this ->config->url . "/object-type/" . $this ->config->type_slug . "?read_key=" . $this ->config->read_key;
$this ->config->object_url = $this ->config->url . "/object/" . $this ->config->object_slug . "?read_key=" . $this ->config->read_key;
$this ->config->media_url = $this ->config->url . "/media?read_key=" . $this ->config->read_key;
$this ->config->add_object_url = $this ->config->url . "/add-object?write_key=" . $this ->config->write_key;
$this ->config->edit_object_url = $this ->config->url . "/edit-object?write_key=" . $this ->config->write_key;
$this ->config->delete_object_url = $this ->config->url . "/delete-object?write_key=" . $this ->config->write_key;
}
所做的更改是它使用其名称空间导入了cosmiccurl,它使我们能够在laravel中快速创建cosmicjs对象的多个实例,只需通过构造函数参数进行初始化即可,而不必设置一些会变得混乱的配置变量当用于大型应用程序时。 最后,将以下函数添加到cosmicjs.php文件中。
public function getByObjectSlug ($key,$slug)
{
$this ->config->object_by_meta_object = $this ->config->url . "/object-type/" . $this ->config->type_slug . "/search?metafield_key=" . $key . "&metafield_object_slug=" .$slug;
$data = json_decode( $this ->curl->get( $this ->config->object_by_meta_object));
return $data;
}
构建我们的应用
现在我们已经在app / Vendor文件夹中设置了cosmicjs库,是时候实际构建一些东西了。 由于所有请求都将由app/Http/Controller/IndexController.php
文件处理,因此将其打开并复制并粘贴此代码。
<?php
namespace App \ Http \ Controllers ;
use Illuminate \ Http \ Request ;
use App \ Vendor \ cosmicjs \ CosmicJS ;
use GuzzleHttp \ Client ;
class IndexController extends Controller {
private $locations_cosmic;
private $items_cosmic;
private $bucket_slug = '' ;
private $read_key = '' ;
private $write_key = '' ;
public function __construct () {
//initialize cosmicjs php instance for fetching all locations
$this ->bucket_slug = config( 'cosmic.slug' );
$this ->read_key = config( 'cosmic.read' );
$this ->write_key = config( 'cosmic.write' );
$this ->locations_cosmic = new CosmicJS( $this ->bucket_slug, 'locations' );
$this ->items_cosmic = new CosmicJS( $this ->bucket_slug, 'items' , $this ->read_key, $this ->write_key);
}
public function index ($location = null) {
//get objects with cosmic-js php
$locations = $this ->locations_cosmic->getObjectsType();
//set locations and bucket_slug variable to be passed to view
if (property_exists($locations, 'objects' )) {
$data[ 'locations' ] = $locations->objects;
}
else
{
$data[ 'locations' ] = [];
}
$data[ 'bucket_slug' ] = $this ->bucket_slug;
//if location slug was passed in url, pass it to view as well
if ($location) {
$data[ 'location_slug' ] = $location;
} else {
$data[ 'location_slug' ] = '' ;
}
//load view
return view( 'index' , $data);
}
//fetch items for location based on slug
public function itemsByLocation ($slug) {
//fetch items using the cosmicjs library's custom function
$items = $this ->items_cosmic->getByObjectSlug( 'location' , $slug);
//if the returned value has "object" property, pass it
if (property_exists($items, 'objects' )) {
//returning arrays in laravel automatically converts it to json string
return $items->objects;
} else {
return 0 ;
}
}
public function newLocation (Request $request) {
//get passed input
$title = $request->input( 'title' );
$address = $request->input( 'address' );
$picture = $request->input( 'image' );
//set data array
$data[ 'title' ] = $title;
$data[ 'type_slug' ] = "locations" ;
$data[ 'bucket_slug' ] = $this ->bucket_slug;
$metafields = array ();
$address_data[ 'key' ] = "address" ;
$address_data[ 'type' ] = 'textarea' ;
$address_data[ 'value' ] = $address;
if ($picture != '' ) {
$picture_data[ 'key' ] = "picture" ;
$picture_data[ 'type' ] = 'file' ;
$picture_data[ 'value' ] = $picture;
array_push($metafields, $picture_data);
}
array_push($metafields, $address_data);
$data[ 'metafields' ] = $metafields;
//create a new guzzle client
$client = new Client();
//create guzzle request with data array passed as json value
$result = $client->post( 'https://api.cosmicjs.com/v1/' . $this ->bucket_slug . '/add-object' , [
'json' => $data,
'headers' => [
'Content-type' => 'application/json' ,
]
]);
//flash message
$request->session()->flash( 'status' , 'The location"' . $title . '" was successfully locations' );
//return result body
return $result->getBody();
}
//create a new item
public function newItem (Request $request) {
//get data
$name = $request->input( 'name' );
$count = $request->input( 'count' );
$location_id = $request->input( 'location' );
$picture = $request->input( 'image' );
//create data array to be passed
$data[ 'title' ] = $name;
$data[ 'type_slug' ] = "items" ;
$data[ 'bucket_slug' ] = $this ->bucket_slug;
$count_metafield[ 'key' ] = "count" ;
$count_metafield[ 'value' ] = $count;
$count_metafield[ 'type' ] = "text" ;
$location_meta[ 'key' ] = "location" ;
$location_meta[ 'object_type' ] = "locations" ;
$location_meta[ 'type' ] = "object" ;
$location_meta[ 'value' ] = $location_id;
$metafields = array ();
//set picture if passed into request
if ($picture != '' ) {
$picture_data[ 'key' ] = "picture" ;
$picture_data[ 'type' ] = 'file' ;
$picture_data[ 'value' ] = $picture;
array_push($metafields, $picture_data);
}
array_push($metafields, $count_metafield);
array_push($metafields, $location_meta);
$data[ 'metafields' ] = $metafields;
$client = new Client();
$result = $client->post( 'https://api.cosmicjs.com/v1/' . $this ->bucket_slug . '/add-object' , [
'json' => $data,
'headers' => [
'Content-type' => 'application/json' ,
]
]);
//flash message
$request->session()->flash( 'status' , 'The Item "' . $name . '" was successfully created' );
//return result body
return $result->getBody();
}
public function editItem (Request $request) {
$name = $request->input( 'name' );
$count = $request->input( 'count' );
$slug = $request->input( 'slug' );
$location_id = $request->input( 'location_id' );
$data[ 'title' ] = $name;
$data[ 'slug' ] = $slug;
$count_meta[ 'key' ] = "count" ;
$count_meta[ 'value' ] = $count;
$count_meta[ 'type' ] = "text" ;
$location_meta[ 'key' ] = "location" ;
$location_meta[ 'object_type' ] = "locations" ;
$location_meta[ 'type' ] = "object" ;
$location_meta[ 'value' ] = $location_id;
$metafields = array ();
//set picture if passed into request
if ($request->input( 'image' )) {
$picture_data[ 'key' ] = "picture" ;
$picture_data[ 'type' ] = 'file' ;
$picture_data[ 'value' ] = $request->input( 'image' );
array_push($metafields, $picture_data);
}
array_push($metafields, $count_meta);
array_push($metafields, $location_meta);
$data[ 'metafields' ] = $metafields;
$client = new Client();
$result = $client->put( 'https://api.cosmicjs.com/v1/' . $this ->bucket_slug . '/edit-object' , [
'json' => $data,
'headers' => [
'Content-type' => 'application/json' ,
]
]);
//flash message
$request->session()->flash( 'status' , 'The Item was successfully edited!' );
//return result body
return $result->getBody();
}
public function deleteItem (Request $request, $slug) {
//create new client and delete item
$client = new Client();
$result = $client->delete( 'https://api.cosmicjs.com/v1/' . $this ->bucket_slug . '/' . $slug, [
'headers' => [
'Content-type' => 'application/json' ,
]
]);
//flash message
$request->session()->flash( 'status' , 'The Item was successfully deleted!' );
return $result;
}
}
上面的代码很自言自语,带有注释
注意事项:
- 我们创建一个新的Cosmic JS实例来检索位置
- 我们正在设置vuejs前端将与之交互的所有功能
- $ client = new CLient()创建一个新的食人鱼实例,我们用它来调用宇宙api
接下来,我们将在routes/web.php
文件中创建路由。 打开文件,然后复制此代码并将其粘贴到其中。
<?php
Route::get( '/{location?}' , 'IndexController@index' );
Route::get( 'items/{slug}' , 'IndexController@itemsByLocation' );
Route::post( 'locations/new' , 'IndexController@newLocation' );
Route::post( 'items/new' , 'IndexController@newItem' );
Route::post( 'items/edit' , 'IndexController@editItem' );
我们在做什么
我们正在将所有IndexCOntroller的功能注册到路由,以便前端可以访问它们。
建立前端
还记得我们的IndexController返回视图('index',$ data);中的这段代码吗? 很好的时间来创建将要加载的视图。 打开/resources/views
文件夹并打开master.blade.php
然后将其复制并粘贴到其中。
< html lang = "{{ config('app.locale') }}" >
< head >
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
<!-- Set Csrf token on all pages -->
< meta name = "csrf-token" content = "{{ csrf_token() }}" >
<!-- Load Bootstrap-->
< link rel = "stylesheet" href = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity = "sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin = "anonymous" >
< link href = "https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.6.2/sweetalert2.css" rel = "stylesheet" type = "text/css" >
< title > Inventory Manger </ title >
<!-- Fonts -->
< link rel = "stylesheet" href = "{{ asset('css/font-awesome/css/font-awesome.min.css')}}" />
< link href = "https://fonts.googleapis.com/css?family=Raleway:100,600" rel = "stylesheet" type = "text/css" >
< script src = "https://use.fontawesome.com/682442a8be.js" > </ script >
<!-- Set Csrf token to be used by javascript and axios-->
< script >
window .Laravel = <?php
echo json_encode([
'csrfToken' => csrf_token(),
]);
?>
</ script >
<!-- Styles -->
< style >
.location-tab {
height : 104px ;
padding-left : 150px ;
}
.location-tab > img {
position : absolute;
left : 0 ;
top : 0 ;
height : 100% ;
width : auto;
max-width : 130px ;
}
.text-primary {
color : #29ABE2 !important ;
}
.panel-heading {
background-color : #29ABE2 !important ;
color : white !important ;
}
.panel {
border-color : #29ABE2 !important ;
}
.btn-primary {
background-color : #29ABE2 !important ;
color : white !important ;
border-color : #29ABE2 !important ;
border-radius : 3px ;
margin : 10px 0 ;
}
</ style >
</ head >
< body >
< div class = "container" >
< div id = "wrapper" >
@yield('content')
</ div >
</ div >
<!-- Load Jquery and bootstrap js-->
< script src = "https://code.jquery.com/jquery-3.2.1.min.js" integrity = "sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin = "anonymous" > </ script >
< script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity = "sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin = "anonymous" > </ script >
< script src = "https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/6.6.2/sweetalert2.min.js" > </ script >
< script src = "{{ asset('/js/app.js')}}" > </ script >
@yield('scripts')
</ body >
</ html >
master.blade.php将用作可扩展布局,然后我们可以将其用作所有其他视图的父级布局。 现在,在同一文件夹中创建一个index.blade.php文件,并将其粘贴到其中。
@extends( 'master' )
@section( 'content' )
<div class =" row ">
< div class =" col - md -12">
< div style =" float : left ">
< h1 > Inventory Management </ h1 >
</ div >
< div style =" float : right ; padding - top : 20 px ">
< a class =" btn btn - default ">< i class =" fa fa - github "></ i > View on Github </ a >
</ div >
</ div >
</ div >
< div class =" row ">
< div class =" col - md -12">
< div style =" float : right ; margin - bottom : 15 px ;">< a href =" https :// cosmicjs . com " target =" _blank " style =" text - decoration : none ;">< img class =" pull - left " src =" https :// cosmicjs . com / images / logo . svg " width ="28" height ="28" style =" margin - right : 10 px ;">< span style =" color : rgb (102, 102, 102); position : relative ; top : 3 px ;"> Proudly powered by Cosmic JS </ span ></ a ></ div >
</ div >
</ div >
< div class =" row " style =" font - size : 16 px ">
<!-- Display vue component and set props from given data -->
< inventory message =" {{Session::get( 'status' )}} " :initial-locations=" {{ json_encode($locations) }} " slug=" {{ $bucket_slug }} " location-slug=" {{ $location_slug }} "></inventory>
</div>
@endsection
@section('scripts')
<script>
</script>
@endsection
注意事项
- 我们创建了一个主布局,其中包含可用内容,脚本和样式的可用部分,我们的其他视图可以扩展这些部分。
- 我们添加了vue组件(将在下一部分中创建),其中props作为控制器提供给视图的数据
创建我们的控制器
本节假定您具有Vuejs的基本知识,否则,我建议您重新学习Vuejs,因为解释某些vue函数的工作原理超出了本教程的范围。 现在开始,打开命令提示符并cd到应用程序的文件夹,然后运行npm run watch来启动laravel mix,这将在我们对任何文件进行更改时编译我们的资产,或者您可以在任何时候键入npm run dev您需要自己编译资产。 打开/resources/assets/js/app.js
文件并更改它
Vue.component( 'example' , require ( './components/Example.vue' ));
至
Vue.component( 'inventory' , require ( './components/Inventory.vue' ));
在这里,我们将默认示例组件替换为将要创建的名为清单的组件。在/resources/assets/js/components
文件夹中,创建和Inventory.vue文件来容纳我们的组件。 在新创建的文件中复制此代码并将其粘贴到其中
< template >
< div >
<!---- ADD LOCATION FORM -->
< div v-if = "add_location" >
< button class = "btn btn-primary" v-on:click = "add_location=false" > < span class = "glyphicon glyphicon-chevron-left" aria-hidden = "true" > </ span > Go back </ button >
< div class = "panel panel-default" >
< div class = "panel-heading" > Add New Location </ div >
< div class = "panel-body" >
< form id = "location_form" name = "location" >
< div class = "form-group" >
< label for = "name" > Name </ label >
< input type = "text" class = "form-control" name = "title" required = "" >
< label for = "address" > Address </ label >
< input type = "text" class = "form-control" name = "address" required = "" >
< label for = "image" > Image </ label >
< input type = "file" class = "form-control media" name = "media" />
</ div >
< button type = "submit" class = "btn btn-primary" :class = "{disabled: isDisabled}" v-on:click.prevent = "addLocation" > Submit </ button >
</ form >
</ div >
</ div >
</ div >
< div v-else >
<!---- LOCATIONS LIST -->
< div v-if = "unselected" >
< button class = "btn btn-primary pull-right" v-on:click = "add_location = true" > < span class = "glyphicon glyphicon-plus" aria-hidden = "true" > </ span > Add New </ button >
< ul class = "list-group" >
< button type = "button" class = "list-group-item location-tab text-primary" :class = "{disabled: list_disable}" v-for = "location in locations" v-on:click = "fetchItems(location)" > < img v-if = "location.metadata.hasOwnProperty('picture')" :src = "location.metadata.picture.url" > {{ location.title }} - {{ location.metadata.address}} </ button >
</ ul >
</ div >
< div v-else >
<!---- ADD ITEM FORM -->
< div v-if = "add_item" >
< button class = "btn btn-primary" v-on:click = "add_item=false" > < span class = "glyphicon glyphicon-chevron-left" aria-hidden = "true" > </ span > Go back </ button >
< div class = "panel panel-default" >
< div class = "panel-heading" > Add New Item </ div >
< div class = "panel-body" >
< form id = "item_form" >
< div class = "form-group" >
< label for = "name" > Name </ label >
< input type = "text" class = "form-control" name = "name" >
</ div >
< div class = "form-group" >
< label for = "count" > Count </ label >
< input type = "number" class = "form-control" name = "count" >
</ div >
< div >
< label for = "image" > Image </ label >
< input type = "file" class = "form-control media" name = "media" />
</ div >
< button type = "submit" class = "btn btn-primary" :class = "{disabled: isDisabled}" v-on:click.prevent = "addItem" > Submit </ button >
</ form >
</ div >
</ div >
</ div >
<!---- EDIT ITEM FORM -->
< div v-else-if = "edit_item" >
< button class = "btn btn-primary" v-on:click = "edit_item=false" > < span class = "glyphicon glyphicon-chevron-left" aria-hidden = "true" > </ span > Go back </ button >
< div class = "panel panel-default" >
< div class = "panel-heading" > Edit {{ selected_item.title }} </ div >
< div class = "panel-body" >
< form id = "edit_item" >
< div class = "form-group" >
< label for = "name" > Name </ label >
< input type = "text" class = "form-control" name = "name" :value = "selected_item.title" >
</ div >
< div class = "form-group" >
< label for = "count" > Count </ label >
< input type = "number" class = "form-control" name = "count" :value = "selected_item.metadata.count" >
</ div >
< button type = "submit" class = "btn btn-primary" :class = "{disabled: isDisabled}" v-on:click.prevent = "editItem" > Submit </ button >
</ form >
</ div >
</ div >
</ div >
< div v-else >
<!---- ITEMS LIST -->
< button class = "btn btn-primary" v-on:click = "unselected=true" > < span class = "glyphicon glyphicon-chevron-left" aria-hidden = "true" > </ span > Go back </ button >
< button class = "btn btn-primary pull-right" v-on:click = "add_item = true" > < span class = "glyphicon glyphicon-plus" aria-hidden = "true" > </ span > Add New Item </ button >
< div class = "panel panel-default" >
< div class = "panel-heading" > {{ selected_location.title }} </ div >
< div class = "panel-body" >
< ul class = "list-group" >
< button type = "button" class = "list-group-item text-primary location-tab" :class = "{disabled: isDisabled}" v-for = "item in items" > < img v-if = "item.metadata.hasOwnProperty('picture')" :src = "item.metadata.picture.url" > {{ item.title }} - {{ item.metadata.count }} < div class = "pull-right" > < span class = "glyphicon glyphicon-pencil" aria-hidden = "true" v-on:click.prevent = "openEdit(item)" > </ span > < span class = "glyphicon glyphicon-trash" aria-hidden = "true" v-on:click.prevent = "deleteItem(item)" style = "padding: 0 5px;" > </ span > </ div > </ button >
</ ul >
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
</ template >
< script >
export default {
mounted() {
var self = this ;
//If location slug was passed show items for that location
if ( this .message)
{
swal( this .message);
}
if ( this .locationSlug)
{
this .unselected = false ;
//find location with slug
var item = this .locations.filter( function ( obj )
{
return obj.slug === self.locationSlug;
});
this .selected_location = item[ 0 ];
this .fetchItems( this .selected_location);
}
},
props : [ 'initial-locations' , 'slug' , 'location-slug' , 'message' ],
data : function ( ) {
return {
edit_item : false ,
locations : this .initialLocations,
isDisabled : false ,
list_disable : false ,
unselected : true ,
items : [],
add_location : false ,
selected_location : [],
selected_item : [],
add_item : false
};
},
methods : {
fetchItems(location)
{
//disable the list and fetch items from laravel
var self = this ;
this .list_disable = true ;
axios.get( 'items/' + location.slug).then( response => {
if (response.data.constructor === Array )
{
self.items = (response.data);
self.selected_location = location;
self.unselected = false ;
} else {
self.selected_location = location;
self.items = [];
self.unselected = false ;
}
self.list_disable = false ;
});
},
addLocation()
{
//disable button
this .isDisabled = true ;
var image = '' ;
var form = $( "#location_form" )[ 0 ];
var data = new FormData(form);
//Check if image is selected then upload image first
if ($( "#location_form .media" ).val() !== '' )
{
//delete X-csrf-token default header as it is not accepted by cosmic api
delete axios.defaults.headers.common[ "X-CSRF-TOKEN" ];
axios.post( 'https://api.cosmicjs.com/v1/' + this .slug + '/media' , data).then( function ( response )
{
//set x-csrf-token again
window .axios.defaults.headers.common[ 'X-CSRF-TOKEN' ] = window .Laravel.csrfToken;
//get image name, append to formdata and send form data to laravel to add location
image = response.data.media.name;
data.set( 'image' , image);
axios.post( 'locations/new' , data).then( response => {
location.reload( true );
});
});
} else {
window .axios.defaults.headers.common[ 'X-CSRF-TOKEN' ] = window .Laravel.csrfToken;
//send form data to laravel without image
axios.post( 'locations/new' , data).then( response => {
location.reload( true );
});
}
},
//set selected item and open edit item section
openEdit(item)
{
this .selected_item = item;
this .edit_item = true ;
},
addItem() {
var self = this ;
this .isDisabled = true ;
var form = $( '#item_form' )[ 0 ];
var data = new FormData(form);
data.append( 'location' , this .selected_location._id);
//Check if image is selected the upload image first
if ($( "#item_form .media" ).val() !== '' )
{
//delete X-csrf-token default header as it is not allowed by cosmic api and post
delete axios.defaults.headers.common[ "X-CSRF-TOKEN" ];
axios.post( 'https://api.cosmicjs.com/v1/' + this .slug + '/media' , data).then( function ( response )
{
//set x-csrf-token again
window .axios.defaults.headers.common[ 'X-CSRF-TOKEN' ] = window .Laravel.csrfToken;
//get image name, append to formdata and send form data to laravel to add location
var image = response.data.media.name;
data.set( 'image' , image);
axios.post( 'items/new' , data).then( response => {
//refresh page BUT pass location_slug, which then makes the app load into the passed location
window .location.href = "./" + self.selected_location.slug;
});
});
} else {
//add header back after post
window .axios.defaults.headers.common[ 'X-CSRF-TOKEN' ] = window .Laravel.csrfToken;
//send form data to laravel without image
axios.post( 'items/new' , data).then( response => {
window .location.href = "./" + self.selected_location.slug;
});
}
},
editItem()
{
//edit item, by sending data to IndexController's editItem() function
var self = this ;
var form = $( "#edit_item" )[ 0 ];
var data = new FormData(form);
this .isDisabled = true ;
data.append( 'slug' , this .selected_item.slug);
if ( this .selected_item.metadata.hasOwnProperty( 'picture' )){
data.append( 'image' , this .selected_item.metafields[ 0 ].value);
}
data.append( 'location_id' , this .selected_location._id);
axios.post( 'items/edit' , data).then( response => {
//refresh page BUT pass location_slug, which then makes the app load into the passed location
window .location.href = "./" + self.selected_location.slug;
});
},
deleteItem(item)
{
var self = this ;
swal({
title : 'Are you sure?' ,
text : 'You will not be able to recover this item!' ,
type : 'warning' ,
showCancelButton : true ,
confirmButtonText : 'Yes, delete it!' ,
cancelButtonText : 'Nope, still need it'
}).then( function ( ) {
axios.get( 'item/' + item.slug + '/delete' ).then( response => {
window .location.href = "./" + self.selected_location.slug;
});
})
}
}
}
</ script >
最大的问题是,这里发生了什么(很多)?
在我们的Vue组件中发生了很多事情,因为大多数前端都在这里,为了使教程简单起见,将阐明各节和变量的主要目标,并且代码中的注释还说明了该节的内容是为了完成
- 我们首先设置一些布尔值(edit_item,add_item,add_location,unselected),这些帮助在变量已更改的情况下切换应用的视图,例如,当edit_item为true时,视图将切换为编辑项形式
- isDisable和list_disable用于通过将某些ui元素的值绑定到“禁用”的引导按钮类来禁用某些ui元素,例如s按钮
- 挂载函数中的代码,只需检查是否传递了位置信息,如果是,则将视图切换到该位置的项目
- 创建的方法会在执行操作后执行调用,其主要逻辑在注释中说明
- 我们使用axios对laravel后端进行了所有调用
- 对于图片上传,我们首先检查是否选择了文件,然后首先上传所选文件,然后再创建一个新图片并将其图片元数据设置为返回的图片名称。
注意
- 确保更改完成后资产已成功编译,如果要手动编译资产,只需运行npm run production即可将其编译为productin模式。
- 我们创建一个自变量,并将其设置为大多数函数的开头,因为如果在某些嵌套函数调用中使用它,则会开始松散this变量的上下文。 可以在此堆栈溢出后找到更多信息
设置铲斗弹头
现在我们要设置铲斗弹头。 我们希望能够通过运行artisan php artisan make:command SetSlug
进行设置,因此运行php artisan make:command SetSlug
。 现在导航到app/console/Commands/SetSlug
并将其复制并粘贴到其中:
<?php
namespace App \ Console \ Commands ;
use Illuminate \ Console \ Command ;
class SetSlug extends Command {
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'bucket {slug} {read?} {write?}' ;
/**
* The console command description.
*
* @var string
*/
protected $description = 'Set the bucket slug' ;
/**
* Create a new command instance.
*
* @return void
*/
protected $files;
protected $read;
protected $write;
public function __construct (\Illuminate\Filesystem\Filesystem $files) {
parent ::__construct();
$this ->files = $files;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle () {
$this ->read = $this ->argument( 'slug' );
$this ->write = $this ->argument( 'slug' );
$config_path = base_path() . "/config/cosmic.php" ;
$content = "<?php\n\treturn [\n\t\t'slug' => '" . $this ->argument( 'slug' ) . "',\n\t\t"
. "'read' => '" . $this ->argument( 'read' ). "',\n\t\t"
. "'write' => '" . $this ->argument( 'write' ). "',\n\t];" ;
$this ->files->put($config_path, $content);
echo "Bucket variables set" ;
}
}
我们正在做的是在config / cosmic.php中打开/创建一个配置文件,并从命令中保存我们的变量,现在可以使用php artisan bucket bucket_slug read_key write_key来设置bucket Slug。 现在,在命令部分的app / console / kernel.php中将其注册为
protected $commands = [
Commands\SetSlug::class
];
结论
我们能够使用vue,宇宙的Js php库,大量的消耗和大量的axios创建和更新项目。 您可以随意修改代码并进行自己的修改,这是删除项目,移动到新位置的一种方式,您可以自己命名,记住我们只是将Cosmic JS与Laravel惊人地结合使用而已。 因此,继续创造惊人的东西。
From: https://hackernoon.com/building-an-inventory-management-app-using-vue-js-and-laravel-1abc492d95d7