Jednoduchý e-shop Laravel 5.3 část 4 – dokončení objednávky
V dnešní části dokončíme objednávku zboží, které jsme si vložili do košíku. Zobrazíme si obsah košíku a nyní je potřeba přidat kód pro tlačítko objednat. …
V dnešní části dokončíme objednávku zboží, které jsme si vložili do košíku. Zobrazíme si obsah košíku a nyní je potřeba přidat kód pro tlačítko objednat. …
Pokračujeme tedy dál no homepage máme zobrazení košíku a teď bychom chtěli zboží přidat do košíku a po té zobrazit zboží v košíku. Obsah košíku uložíme do session .
Takže do routes/web.php si přidáme dvě routy a to pro přidání zboží do košíku a také pro zobrazení košíku.
1 2 |
Route::post('/addcart', 'CartController@postAdd'); Route::get('/cart','CartController@index'); |
a vytvoříme si CartController
1 |
php artisan make:controller CartController |
a upravíme takto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Product; class CartController extends Controller { public function index(Request $request) { $cartData = $request->session()->get('cart'); $cart = []; $sum = 0; if ($request->session()->has('cart')) { foreach ($cartData as $key => $value) { $product = Product::where('id', '=', $key)->get()->toArray(); $cart_item['item'] = $product['0']; $cart_item['total_price'] = $value['qty'] * $product['0']['price']; $cart_item['qty'] = $value['qty']; $sum = $sum + $cart_item['total_price']; array_push($cart, $cart_item); } } return view('cart')->with('cart',$cart)->with('sum',$sum); } public function postAdd(Request $request) { $id = $request->input('product_id'); $session = $request->session(); $cartData = ($session->get('cart')) ? $session->get('cart') : array(); if (array_key_exists($id, $cartData)) { $cartData[$id]['qty']++; } else { $cartData[$id] = array( 'qty' => 1 ); } $request->session()->put('cart', $cartData); return redirect()->back()->with('message', 'Prodcut Added Successfully!'); } } |
funkce postAdd nám slouží pro přidání zboží z homepage do košíku a a index nám zobrazí aktuální obsah košíku. Ještě musíme připravit view pro zobrazení košíku. V resources/views založíme cart.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
@extends('layouts.master') @section('title','HomePage'); @section('content') <table id="cart" class="table table-hover table-condensed"> <thead> <tr> <th style="width:50%">Product</th> <th style="width:10%">Cena</th> <th style="width:8%">Množství</th> <th style="width:22%" class="text-center">Součet</th> <th style="width:10%"></th> </tr> </thead> <tbody> @foreach ($cart as $cart_item) <tr> <td data-th="Product"> <div class="row"> <div class="col-sm-2 hidden-xs"><img src="http://placehold.it/100x100" alt="..." class="img-responsive"/></div> <div class="col-sm-10"> <h4 class="nomargin">{{ $cart_item['item']['name'] }}</h4> <p>{{ $cart_item['item']['description'] }}</p> </div> </div> </td> <td data-th="Price">{{ number_format($cart_item['item']['price'], 2, ',', ' ').' Kč' }}</td> <td data-th="Quantity" class="text-center"> {{--<input type="number" class="form-control text-center" value="{{ $cart_item['qty'] }}">--}} {{ $cart_item['qty'] }} </td> <td data-th="Subtotal" class="text-center">{{ number_format($cart_item['total_price'], 2, ',', ' ').' Kč' }}</td> <td class="actions" data-th=""> {{--<button class="btn btn-info btn-sm"><i class="fa fa-refresh"></i></button>--}} <a href="{{ URL::to('/cartdelete/'.$cart_item['item']['id'] ) }} " class="btn btn-danger btn-sm"><i class="fa fa-trash-o"></i></a> </td> </tr> @endforeach </tbody> <tfoot> <tr class="visible-xs"> <td class="text-center"><strong>{{ $sum }}</strong></td> </tr> <tr> <td><a href="{{ URL::to('/') }}" class="btn btn-warning"><i class="fa fa-angle-left"></i> Pokračovat v nákupu</a></td> <td colspan="2" class="hidden-xs"></td> <td class="hidden-xs text-center"><strong>{{ number_format($sum, 2, ',', ' ').' Kč' }}</strong></td> <td><a href="{{ URL::to('checkout') }}" class="btn btn-success btn-block">Objednat <i class="fa fa-angle-right"></i></a></td> </tr> </tfoot> </table> @stop |
Ještě drobná úprava css stylu pro správné zobrazení v public/css/styles.css
1 2 3 |
body { padding-top:70px; } |
No ještě by to chtělo vedle ikonky košíku na homepage zobrazit aktuální množství položek v košíku.
Takže upravíme resources/view/layouts/master.blade.php
1 |
<li><a href="{{ URL::to('cart') }}"><i class="glyphicon glyphicon-shopping-cart"></i> Košík <span class="badge">{{ $cart_qty }}</span></a></li> |
nyní nám ovšem e-shop přestane fungovat jelikož proměnnou $cart_qty je potřeba naplnit a k tomu využijeme tzv. view composer a to konkrétně v app/providers/AppServiceProvider.php upravíme funcki
1 2 3 4 5 6 7 |
public function boot() { View::composer('layouts.master', function($view) { $cart_qty = Session::get('cart') ? array_sum(array_column(Session::get('cart'), 'qty')) : 0; $view->with('cart_qty',$cart_qty); }); } |
No a nyní by nám již všechno mělo fungovat
Dazabázi máme vytvořenou. Abychom mohli vyvíjet aplikaci naplním si produkty daty. K tomu využiji další pěknou feature, kterou Laravel má a to database seeder.
Takže si v database/seeds upravíme DatabaseSeeder.php a to takto
1 2 3 4 |
public function run() { $this->call(ProductsTableSeeder::class); } |
Dále si ve stejném adresáři vytvoříme ProductsTableSeeder.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<?php use Illuminate\Database\Seeder; use Illuminate\Database\Eloquent\Model; use App\Product; class ProductsTableSeeder extends Seeder { public function run() { DB::table('products')->delete(); Product::create(array( 'name'=>'Náhrdelník swarowski', 'description'=>'Nový luxusní náhrdelník swarovski', 'slug'=>'nahrdelnik-swarowski', 'price'=>'1001.40', )); Product::create(array( 'name'=>'Prstýnek chirurgická ocel', 'description'=>'Potěší každou slečnu nebo paní.', 'slug'=>'prstynek-chirurgicka-ocel', 'price'=>'100.50', )); Product::create(array( 'name'=>'Náramek pro meditaci', 'description'=>'Meditační náramek přímo z Indie', 'slug'=>'meditacni-naramek', 'price'=>'250', )); } } |
a nyní bychom už mohli pustit seeder
1 |
php artisan db:seed |
Ovšem ten nám skončí chybou ClassProductcTableSeeder does not exists. Ovšem my ale víme, že existuje. Problém je pouze v autoloadu takže provedeme
1 |
composer dump-autoload |
A zkusíme seeder znovu spustit. Ops opět chybka Class App\Produxt not found. Jistě v ProductsTableSeeder.php používáme Product model, ten ovšem nenáme vytvořen takže
1 |
php artisan make:model Product |
A konečně spustíme seeder. A databázi produktů máme naplněnou.
Teď by to chtělo náš minieshop ještě trochu oživit. Vytvoříme se teda jednoduchou homeage vytvoříme si HomeController pomocí
1 |
php artisan make:controller HomeController |
a HomeController upravíme takto:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Product; class HomeController extends Controller { public function index() { $products = Product::all(); return view('home', ['products' => $products]); } } |
samozřejmě ještě potřebujeme vytvořit routu a to editaci routes/web.php na
1 |
Route::get('/', 'HomeController@index'); |
Teď nám ještě chybí příslušné view, takže v resources/view vytvoříme home.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
@extends('layouts.master') @section('title','HomePage'); @section('content') @if(session('message')) <div id="success-alert" class="alert alert-success"> <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a> {{ session('message') }} </div> @endif <div class="row"> @foreach ($products->chunk(3) as $products) <div class="row"> @foreach ($products as $product) <div class="col-md-4"> <div class="image"> <img src="{{ url('/products/'.$product->image) }}" alt="{{ $product->name }}"> </div> <div class="description"> <h3>{{ $product->name }}</h3> <p>{{ $product->description }}</p> </div> <div class="price">{{ $product->price }} Kč</div> <div class="buy"> <form method="POST" action="{{ URL::to('addcart') }}" class="form-inline" role="form"> {{ csrf_field() }} <input type="hidden" name="product_id" value="{{ $product->id }}"> <button type="submit" class="btn btn-primary">Koupit</button> </form> </div> </div> @endforeach </div> @endforeach </div> @stop |
a jistě jste si všimli že potřebujeme vytvořit v resources/views ještě adresář layouts a v něm master.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Jednoduchý eshop Laravel 5.3"> <meta name="author" content="Mamusha"> <link rel="icon" href="../../favicon.ico"> <title>@yield('title', 'Jednoduchý shop Laravel 5.3')</title> <!-- Bootstrap core CSS --> <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="//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"> <!-- Custom styles for this template --> <link href="{{ URL::asset('css/style.css') }}" rel="stylesheet"> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head> <body> <!-- Fixed navbar --> <nav class="navbar navbar-default navbar-fixed-top"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="{{ URL::to('/') }}">MaMusha shop</a> </div> <div id="navbar" class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li class="active"><a href="{{ URL::to('/') }}">Úvodní strana</a></li> <li><a href="#about">Vše o nákupu</a></li> <li><a href="#contact">Kontakt</a></li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="{{ URL::to('cart') }}"><i class="glyphicon glyphicon-shopping-cart"></i> Košík <span class="badge"></span></a></li> </ul> </div><!--/.nav-collapse --> </div> </nav> <div class="container"> @yield('content') </div> <!-- jQuery (necessary for Bootstrap's JavaScript plugins) --> <script src="https://code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script> <!-- Include all compiled plugins (below), or include individual files as needed --> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> </body> </html> |
a už nám konečně něco funguje
Po krátké přestávce ( v mezidobí jsem pronikala do tajů záludného prgramovacího jazyka C) jsem se vrátila k mému původnímu e-shopu ( viz. seriál a drobný update). Jak už to tak bývá, zjistila jsem, že ne zrovna všechno v něm bylo ideální. Protože se blíží vánoce a kromě zaměstnání, úklidu domácnosti, pečení cukroví a nákupu dárků, nemám v podstatě nic na práci, rozhodla jsem se svůj nehezký kód přepracovat a to s využitím nejnovější verze Laravel framewroku a to konkrétně aktuální verze 5.3. Idea je stejná jako v minulém seriálu vytvořit jednoduchý, ale zároveň provozuschpný e-shop. Začínáme… …
UPDATE: Začala jsem novy seriál Jednoduchý e-shop Laravel 5.3
Po čase jsem se vrátila ke svému jednoduchému e-shopu na frameworku Laravel. Pro jednu známou jsem potřebovala jednoduchý e-shop na prodej jejich výrobků a tak jsem oprášila svůj zdrojový kód ze seriálu a updatovala jsem na Laravel 5.3.
Oproti původnímu seriálu jsem vypustila kategorie (v požadovaném e-shopu je nepotřebuji, prodává jen pár svých kousků). Zato jsem přidala administraci s využitím vestavěné autentizace ve frameworku. Vytvořila jsem si vlastní middleware pro přihlášení do administrace a pro odesílání mailu jsem využila novinku v Laravel 5.3 tzv. mailables. Do modelů jsem přidala i tzv. relationship. A už tu mám první jednoduchou verzi a dokonce jsem byla tak hodná, že jsem zdrojáky zveřejnila na githubu takže, kdo chce může se mrknout a samozřejmě budu ráda za jakoukoli zpětnou vazbu.
Tak si pohrávám s myšlenkou jak vylepšit jednoduchý e-shop a v rámci zkoušení jsem si vyzkoušela způsob jakým použít interface nebo jak tomu říkají Contract v Laravelu. …
Pokračuji si s hraním spoužitím Gulpu , začala jsem v minulém příspěvku. Dnes si naistaluji browserSync automatické obnovení okna prohlížeče při změně souborů, gulp-notify informační zprávy v OS a gulp- autoprefixer. Nejprve si balíčky naistalujeme. …
UPDATE: Začala jsem novy seriál Jednoduchý e-shop Laravel 5.3
Tak zatím se nikdo neozval, že by se mu šikla ta administrace, tak si zatím opravím drobnou chybu a to že pokud se do obchodu podívám a nemám ještě nic v košíku zobrazí se chyba …
UPDATE: Začala jsem novy seriál Jednoduchý e-shop Laravel 5.3
Po delší pauze dnes dokončím náš minieshop. Zbývá nám jenom uložení objednávky.
Vytvoříme si nejprve controller pro obsluhu objednávek …