Laravel Tutorial

Einen Katalog mit Laravel erstellen und das Framework verstehen lernen

Mein Setup für dieses Tutorial

  • Windows 7
  • Xampp mit Php7 & Mysql 5.7
  • Composer mit gesetzter Pathvariable

1.) Laravel Installer mit Composer downloaden

$ composer global require "laravel/installer=~1.1"

2.) In das Server Webverzeichnis navigieren und Projekt anlegen

$ cd C:\xampp\htdocs
$ composer create-project laravel/laravel framework_laravel 5.3.*

3.) Wir stellen das Projekt auf debug-modus ein

[code filename="config/app.php"]
return [
     'debug' => env('APP_DEBUG', true),
[/code]

4.) Wir konfigurieren unsere Datenbank(Mysql)-Einstellungen

[code filename=".env"]
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=framework_test
DB_USERNAME=rootXXXX
[/code]

4.) Http-Controller CatalogController erstellen und routen

[code filename="app/Http/Controllers/CatalogController.php"]
<?php 
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class CatalogController extends Controller  {
    public function catalog($param = null, Request $request = null)
    {
        echo __CLASS__.'::'.__FUNCTION__;
    }
}
[/code]

5.)  am Ende der Datei einfügen

[code filename="routes/web.php"]
Route::get('katalog', 'CatalogController@catalog');
Route::get('katalog/', 'CatalogController@catalog');
Route::get('katalog/{param}', 'CatalogController@catalog');
[/code]

6.) Es wird Zeit die datenbankstruktur aufzuseten

Vom rootverszeichnis verwenden wir nun Artisan(Laravel’s Kommandozeilenschnittstelle) um Migrations zu erzeugen

$ php artisan make:migration create_shop_articles_table
$ php artisan make:migration create_shop_article_countries_table
$ php artisan make:migration create_shop_article_languages_table
$ php artisan make:migration create_shop_categories_table
$ php artisan make:migration create_shop_article_categories_table

Die Migrations-Dateien werden von artisan als folgende Dateien abgelegt
Die Datums-Nomenklatur variiert natürlich in eurem Projekt

database/migrations/2016_11_24_120908_create_shop_articles_table.php
database/migrations/2016_11_24_121033_create_shop_article_countries_table.php
database/migrations/2016_11_24_121100_create_shop_article_languages_table.php
database/migrations/2016_11_24_121127_create_shop_categories_table.php
database/migrations/2016_11_24_121154_create_shop_article_categories_table.php

7. Die erzeugten Dateien werden geöffnet. Funktionern werden ergänzt:

[code filename="database/migrations/2016_11_24_120908_create_shop_articles_table.php"]
    public function up()
    {
        Schema::dropIfExists('shop_articles');
        Schema::create('shop_articles', function($table)
        {
            $table->increments('id');
            $table->integer('active')->default(1);
            $table->string('artnum');
            $table->string('picture_1')->nullable();
            $table->string('picture_2')->nullable();
            $table->string('picture_3')->nullable();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop('shop_articles');
    }
[/code]
[code filename="database/migrations/2016_11_24_121033_create_shop_article_countries_table.php"]
    public function up()
    {
        Schema::dropIfExists('shop_article_countries');
        Schema::create('shop_article_countries', function($table)
        {
            $table->increments('id');
            $table->integer('shop_articles_id')->unsigned();
            $table->foreign('shop_articles_id')->references('id')->on('shop_articles')->onDelete('cascade');
            $table->integer('country_id');
            $table->double('brutto', 8, 4);
            $table->double('vat', 2, 2);
            $table->string('currency', 16);
            $table->integer('available')->default(1);
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop('shop_article_countries');
    }
[/code]
[code filename="database/migrations/2016_11_24_121100_create_shop_article_languages_table.php"]
    public function up()
    {
        Schema::dropIfExists('shop_article_languages');
        Schema::create('shop_article_languages', function($table)
        {
            $table->increments('id');
            $table->integer('shop_articles_id')->unsigned();
            $table->foreign('shop_articles_id')->references('id')->on('shop_articles')->onDelete('cascade');
            $table->integer('language_id');
            $table->string('name', 255);
            $table->string('title', 255);
            $table->text('short_desc');
            $table->text('description');
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop('shop_article_languages');
    }
[/code]
[code filename="database/migrations/2016_11_24_121127_create_shop_categories_table.php"]
    public function up()
    {
        Schema::dropIfExists('shop_categories');
        Schema::create('shop_categories', function($table)
        {
            $table->increments('id');
            $table->integer('parent_id')->nullable();
            $table->string('name', 255);
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::drop('shop_categories');
    }
[/code]
[code filename="database/migrations/2016_11_24_121154_create_shop_article_categories_table.php"]
   public function up()
   {
      Schema::dropIfExists('shop_article_categories');
      Schema::create('shop_article_categories', function($table)
      {
            $table->increments('id');
            $table->integer('shop_articles_id')->unsigned();
            $table->foreign('shop_articles_id')->references('id')->on('shop_articles');
            $table->integer('shop_categories_id')->unsigned();
            $table->foreign('shop_categories_id')->references('id')->on('shop_categories');
            $table->timestamps();
      });
   }

   public function down()
   {
      Schema::drop('shop_article_categories');
   }
[/code]

8.) Mit Artisan erzeugen wir aus den Migrationsfiles die Datenbanktabellen

$ php artisan migrate
$ Y

Jetzt erzeugen wir noch die Eloquent-Modelle.
Jede Tabelle s.o. korrespondiert mit einem Model
Wir erstellen das Verzeichnis app/Models/Catalog
und legen dort folgende Dateien an

[code filename="app/Models/Catalog/ShopArticles.php"]
<?php
namespace App\Models\Catalog;

use Illuminate\Database\Eloquent\Model;

class ShopArticles extends Model{

    public function country()
    {
        return $this->hasOne('App\Models\Catalog\ShopArticleCountries');
    }

    public function language()
    {
        return $this->hasOne('App\Models\Catalog\ShopArticleLanguages');
    }

    protected $table = 'shop_articles';
}
[/code]
[code filename="app/Models/Catalog/ShopArticleLanguages.php"]
<?php

namespace App\Models\Catalog;

use Illuminate\Database\Eloquent\Model;

class ShopArticleLanguages extends Model{

   protected $table = 'shop_article_languages';
}
[/code]
[code filename="app/Models/Catalog/ShopArticleCountries.php"]
<?php

namespace App\Models\Catalog;

use Illuminate\Database\Eloquent\Model;

class ShopArticleCountries extends Model{
   protected $table = 'shop_article_countries';
}
[/code]
[code filename="app/Models/Catalog/ShopCategories.php"]
<?php

namespace App\Models\Catalog;

use Illuminate\Database\Eloquent\Model;

class ShopCategories extends Model{

   protected $table = 'shop_categories';
}
[/code]
[code filename="app/Models/Catalog/ShopArticleCategories.php"]
<?php

namespace App\Models\Catalog;

use Illuminate\Database\Eloquent\Model;

class ShopArticleCategories extends Model{

   protected $table = 'shop_article_categories';
}
[/code]

9.) Testdaten sind hier zu haben:

https://www.databau.de/download/tutorial-framework/framework_test-data.sql
Bitte downloaden und einspielen

10.) Wir kommen wieder zum CatalogController zurück

In der function catalog testen wir des erste mal eines unserer Elquent Modelle .

[code filename="app/Http/Controllers/CatalogController.php"]
<?php
namespace App\Http\Controllers;

use App\Models\Catalog\ShopArticles;
use Illuminate\Http\Request;

class CatalogController extends Controller  {

    public function catalog($param = null, Request $request = null)
    {
        $articles = ShopArticles::get();
        print_r($articles);
    }
}
[/code]

11.)  Sprach und Länder-spezifische Felder in das Artikel-Model joinen

Das Modell funktioniert also. Dann testen wir eine  erweitere Abfrage und ergänzen die function catalog

[code filename="app/Http/Controllers/CatalogController.php"]
    public function catalog($param = null, Request $request = null)
    {
        $request['language_id'] = 1;
        $request['country_id'] = 3;
        $request['offset'] = 0;
        $request['limit'] = 12;

        $articles = ShopArticles::with([
            'language' => function($query) use ($request){
                if( !empty($request['language_id']) )
                {
                    $query->whereRaw(' language_id = ? ', array($request['language_id']));
                }
            },
            'country' => function($query) use ($request){
                if( !empty($request['country_id']) )
                {
                    $query->whereRaw(' country_id = ? ', array($request['country_id']));
                }
            }])
            ->offset($request['offset'])
            ->limit($request['limit'])
            ->get();


        print_r($articles);

    }
[/code]

12.) Zum übergeben an das Frontend wollen wir unsere Resourcen mit Fractal transfomieren.

Bisher bekommen wir nur das ganze ORM-Eloquent-objekt, wollen aber eine weniger komplexe Struktur an das View liefern

Wir wollen ein eindimensionales Array mit angepassten keys, values pairs erzeugen.
Dafür integrieren wir Fractal-Transformers in unser Projekt.
In der Konsole installieren wir mit composer

$ composer require league/fractal

Und bauen einen Fractal-Transformer

[code filename="app/Transformers/Catalog/ShopArticlesTransformer.php"]
<?php namespace App\Transformers\Catalog;

use App\Models\Catalog\ShopArticles;
use League\Fractal\TransformerAbstract;

class ShopArticlesTransformer extends TransformerAbstract  {

    public function transform(ShopArticles $ShopArticles)
    {
        $article = $ShopArticles->getAttributes();

        $ShopLanguage = $ShopArticles->getRelation('language');
        $language = empty($ShopLanguage) ? array('name' => null, 'title' => null, 'short_desc' => null, 'description' => null) : $ShopLanguage->getAttributes();

        $ShopCountries = $ShopArticles->getRelation('country');
        $country = empty($ShopCountries) ? array('brutto' => null, 'currency' => null) : $ShopCountries->getAttributes();

        return [
            'id' => (int) $ShopArticles->id,
            'name' =>  $language['name'],
            'title' => $language['title'],
            'desc1' => $language['short_desc'],
            'desc2' => $language['description'],
            'price' => number_format($country['brutto'], 2, ',', '.') . ' ' . $country['currency'],
            'thumpnail' => empty($article['picture_1']) ? '' : 'thumpnail__' . $article['picture_1'],
            'img1' => $article['picture_1'],
            'img2' => $article['picture_2'],
            'img3' => $article['picture_3'],
        ];
    }
}
[/code]

Wir gehen wieder zum Http-Controller
Neue imports:

[code filename="app/Http/Controllers/CatalogController.php"]
use App\Transformers\Catalog\ShopArticlesTransformer;
use League\Fractal\Manager;
use League\Fractal\Resource\Collection;
[/code]

Dann Suchen:

[code filename="app/Http/Controllers/CatalogController.php"]
   
        print_r($articles);

[/code]

Und Ersetzen:

[code filename="app/Http/Controllers/CatalogController.php"]
        $manager = new Manager();
        $resource = new Collection($articles, new ShopArticlesTransformer());
        $ArticleList = $manager->createData($resource)->toArray();

    
        print_r($ArticleList);
     
[/code]

Die Transfomation und Ausgabe der $ArticleList eignet sich jetzt zu Übergabe an das View.
Jetzt aber erstmal print_r und nachsehen was wir haben. Die wirklich Übergabe erfolgt später

13.) Views erstellen

Blade heißt die Template-Engine für Laravel.
Wir erstellen zwei Blade-Dateien.

[code filename="resources/views/layout.blade.php"]
<!doctype html>
<html ng-app="framance.shop">
<head>
    <meta charset="UTF-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <meta name="device" content=""/>
    <title>Laravel Test</title>
    <link href="https://fonts.googleapis.com/css?family=Bad+Script" rel="stylesheet" type="text/css">
    <link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>
    <link href="https://www.databau.de/download/turorial-framework/assets/css/main.css" rel="stylesheet"/>
</head>
<body>

<nav class="navbar navbar-default navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">Laravel Tutorial</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="">Home</a></li>
                <li class="active"><a href="katalog">Katalog</a></li>
            </ul>
        </div>
    </div>
</nav>
<div class="content container">

    @yield('content')

</div>
</body>
</html>

[/code]
[code filename="resources/views/catalog.blade.php"]
@extends('layout')
@section('content')
<div class="wrapped-content">
    <div>
        <br/><br/><br/><br/><br/>
        <div class="page-container">

            @foreach ($ArticleList as $key=>$ArticleItem)

                <div class="col-sm-12 item-container list">
                    <div class="col-sm-3 item">
                        <a href="katalog/Schuhe#article/">
                            <img srcset="https://www.databau.de/download/tutorial-framework/images/{{$ArticleItem['img1']}} 750w, https://www.databau.de/download/tutorial-framework/images/{{$ArticleItem['thumpnail']}} 974w, https://www.databau.de/download/tutorial-framework/images/{{$ArticleItem['img1']}} 3000w" style="width:100%;height:auto;"/>
                        </a>
                        <span style="color:blue;">{{$ArticleItem['title']}}</span>
                        <span style="color:red;">{{$ArticleItem['price']}}</span>
                    </div>
                </div>

            @endforeach
        </div>
    </div>
</div>
@stop
[/code]

14.) Zuletzt bearbeiten wir noch einmal den Http-Controller

Suchen:

[code filename="app/Http/Controllers/CatalogController.php"]
        print_r($ArticleList);
[/code]

Und Ersetzen:

[code filename="app/Http/Controllers/CatalogController.php"]
        return view('catalog', [
                'ArticleList' => $ArticleList['data'],
            ]
        );
[/code]

15.) Im nächsten Teil werden Pager und Artikel-Detail fertig gestellt

 

 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.