Laravel Tutorial

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