LARAVEL to jeden z wielu frameworków, który może w znacznym stopniu ułatwić pracę programisty aplikacji lub strony internetowej dzięki temu, że posiada implementację rozwiązań wielu typowych problemów związanych z typowym środowiskiem internetowym.
Do pracy będzie potrzebne kilka elementów: serwer WWW obsługujący technologię PHP, serwer bazy danych MySQL, silnik COMPOSER, edytor podświetlający składnię i ułatwiający nawigację pomiędzy plikami, dostęp do internetu.
Proponuję pobranie i instalację:
Korzystając z wiersza poleceń utwórz projekt strony.
cd c:\xampp\htdocs
composer create-project --prefer-dist laravel/laravel laravel.cms
W celu skonfigurowania środowiska konieczne będzie utworzenie bazy danych. W tym celu można użyć dostępnego w pakiecie XAMPP narzędzia PhpMyAdmin. Warto również utworzyć nowego użytkownika i przypisać do niego utworzoną bazę danych.
CREATE DATABASE cms
DEFAULT CHARACTER SET utf8
COLLATE utf8_polish_ci;
CREATE USER 'laravel-user'@'%'
IDENTIFIED VIA mysql_native_password
USING 'laravel-password';
GRANT USAGE ON *.* TO 'laravel-user'@'%' REQUIRE NONE;
GRANT ALL PRIVILEGES ON `cms`.* TO 'laravel-user'@'%';
Po dodaniu bazy trzeba skonfigurować ją we frameworku:
Projekt jest gotowy do pierwszego uruchomienia. Można do tego wykorzystać przygotowany wcześniej serwer Apache lub wbudowany miniserwer:
cd c:\xampp\htdocs\laravel.cms
php artisan serve
W wyniku otrzymamy domyślną stronę projektu Laravel.
http://127.0.0.1:8000/
Polecenie artisan ma wiele innych ciekawych zastosowań. Warto się z nimi pobieżnie zapoznać:
php artisan list
Jeżeli chcemy wygenerować wirtualną domenę dla projektu możemy to zrobić dodając VirtualHost do serwera Apache.
<VirtualHost *:80>
ServerName stronka.pl
ServerAlias www.stronka.pl
ServerAdmin stronka@poczta.com
DocumentRoot /var/www/html/stronka/public
#DocumentRoot c:/xampp/htdocs/stronka/public
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Domena musi również zostać dodana do pliku z lokalnymi nazwami hostów -
$ sudo echo 127.0.0.1 stronka.pl >> /etc/hosts
$ sudo echo 127.0.0.1 www.stronka.pl >> /etc/hosts
$ sudo service apache2 restart
cd \xampp\htdocs\laravel.cms
php artisan make:controller PagesController -resource
public function index() {
echo "To jest INDEX() w pliku ", __FILE__;
}
Co i kiedy się uruchamia? google.pl/search?q=laravel+controller
public function index() {
return view('pages.index');
}
<!DOCTYPE html>
<html lang="pl">
<head>
<title>Tytuł strony</title>
<meta charset="UTF-8"/>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css"/>
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<div class="content">
@yield('content')
</div>
</div>
</body>
</html>
@extends('layout')
@section('content')
treść strony pages/index
@endsection
php artisan make:auth
http://127.0.0.1/projekt/public/login
php artisan make:migration pages
public function up() {
Schema::create('pages', function(Blueprint $table) {
$table->increments('id');
$table->string('title')->unique();
$table->text('content');
$table->timestamps();
});
}
public function down() {
Schema::drop('pages');
}
php artisan make:seeder UsersTableSeeder
php artisan make:model Pages
php artisan make:seeder PagesTableSeeder
public function index() {
# //use App\Pages; //na początku pliku
# $pages = Pages::all();
# $pages = \App\Pages::all(); //nie wymaga użycia "use..."
$pages = \App\Pages::paginate(10);
return view('pages.index', compact('pages'));
}
<table>
<tr>
<th>ID</th>
<th>TITLE</th>
<th>OPTIONS</th>
</tr>
@foreach ($pages as $page)
<tr>
<td>{{ $page->id }}</td>
<td>{{ $page->title }}</td>
<td>
<a class="btn btn-info" href="#">Edit</a>
<a class="btn btn-danger" href="#">Delete</a>
</td>
</tr>
@endforeach
</table>
{{ $pages->links() }}
public function run() {
$this->call(UsersTableSeeder::class);
}
use App\User;
public function run() {
$user = new User();
$user->name = 'user';
$user->email = 'user@mail.com';
$user->password = bcrypt('haslo');
$user->save();
}
use App\Pages;
public function run() {
$faker = Faker\Factory::create();
for ($i = 0; $i < 10; $i++) {
$pages = new Pages();
$pages->title = 'page_'.$i.' '.$faker->company();
$page->content = $faker->text(200);
$pages->save();
}
}
rem php artisan migrate:rollback
php artisan migrate
php artisan db:seed
PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes")
use Illuminate\Support\Facades\Schema;
public function boot() {
Schema::defaultStringLength(191);
}
php artisan make:model Roles -m
php artisan make:seed RolesTableSeeder
public function up() {
Schema::create('roles', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
}
public function run() {
$role = new \App\Roles();
$role->name = 'Admin';
$role->save();
$role = new \App\Roles();
$role->name = 'Moderator';
$role->save();
$role = new \App\Roles();
$role->name = 'User';
$role->save();
}
php artisan migrate
php artisan db:seed --class=RolesTableSeeder
php artisan make:model RolesHasUsers -m
public function up() {
Schema::create('roles_has_users', function(Blueprint $table) {
$table->increments('id');
$table->integer('users_id')->unsigned();
$table->integer('roles_id')->unsigned();
$table->timestamps();
});
Schema::table('roles_has_users', function(Blueprint $table) {
$table->foreign('users_id')->references('id')->on('users');
});
Schema::table('roles_has_users', function(Blueprint $table) {
$table->foreign('roles_id')->references('id')->on('roles');
});
}
php artisan migrate
public function roles() {//ta sama nazwa funkcji, co nazwa tabeli
return $this->belongsToMany(Roles::class, 'roles_has_users', 'users_id', 'roles_id')->withTimestamps();
}
use App\Roles;
public function run() {
...
$user->roles()->attach(1);
...
$role = Roles::where('name', 'Admin')->first();
$user->roles()->attach($role);
...
}
public function run() {
$this->call(RolesTableSeeder::class);//przed UsersTableSeeder, bo są zależne
$this->call(UsersTableSeeder::class);
$this->call(PagesTableSeeder::class);
}
php artisan migrate:refresh
php artisan db:seed
php artisan make:middleware CheckRoles
$protected $routeMiddleware = [
...
'roles' => \App\Http\Middleware\CheckRoles::class
];
#Route::resource('pages', 'PagesController');
Route::group([
'middleware' => 'roles',
'roles' => 'Admin',
//'roles' => ['Admin', 'Moderator'],
], function() {
Route::resource('pages', 'PagesController');
});
public function handle($request, Closure $next) {
echo 'xxx MiddleWare CheckRoles się uruchomił';
return $next($request);
}
public function __construct() {
//$this->middleware('auth');
}
public function handle($request, Closure $next) {
if ($request->user() === null) {
return redirect('/login');
}
$actions = $request->route()->getAction();
# zwraca przykładowo: array(
# 'middleware' => array('web','roles'),
# 'roles' => array('Admin', 'Moderator'),
# 'as' => 'pages.index',
# 'uses' => 'App\Http\Controllers\PagesController@index',
# 'controller' => 'App\Http\Controllers\PagesController@index',
# 'namespace' => 'App\Http\Controllers',
# 'prefix' => null,
# 'where' => array(),
# )
if (!isset($actions['roles']) ||
$request->user()->hasAnyRole($actions['roles'])) {
return $next($request);
}
return redirect('/login');
}
# public function hasRole($role) {
# return $this->roles()->where('name', $role)->first();
# }
public function hasAnyRole($roles) {
$roles = (array) $roles;
foreach ($roles as $role) {
if ($this->roles()->where('name', $role)->first()) {
return true;
}
}
return false;
}
Logout (testy na innych userach)
composer require barryvdh/laravel-debugbar
Barryvdh\Debugbar\ServiceProvider::class,//dodajemy na końcu listy
...
'Debugbar' => Barryvdh\Debugbar\Facade::class,//dodajemy na końcu pliku
...
#Route::resource('pages', 'PagesController');
Route::group([
'middleware' => 'roles',
'roles' => 'Admin',
//'roles' => ['Admin', 'Moderator'],
], function() {
//Route::resource('pages', 'PagesController');
Route::get('pages', [
'uses' => 'PagesController@index',
'as' => 'pages.index',
]);
Route::get('pages/create', [
'uses' => 'PagesController@create',
'as' => 'pages.create',
]);
Route::post('pages/store', [
'uses' => 'PagesController@store',
'as' => 'pages.store',
]);
});
composer require "laravelcollective/html":"^5.3.0"
Collective\Html\HtmlServiceProvider::class,//dodajemy na końcu listy
...
'Form' => Collective\Html\FormFacade::class,//dodajemy na końcu pliku
'Html' => Collective\Html\HtmlFacade::class,
...
Dokumentacja Laravel Collective
public function create() {
return view('pages.create');
}
public function store(Request $request) {
//@todo
return view('pages.create');
}
@extends('layout')
# @section('content')
# <form>
# <input name="title"...> //nazwa pola zgodna z nazwą kolumny w bazie danych
# </form>
# @endsection
@section('content')
{!! Form::open(['route' => 'pages.store']) !!}
@if ($errors->any())
<ul class="alert alert-danger">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
@endif
<div class="form-group">
{!! Form::label('title', 'Tytuł:') !!}
{!! Form::text('title', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('content', 'Treść:') !!}
{!! Form::textarea('content', null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::submit('Zapisz', ['class' => 'btn btn-primary']) !!}
{!! link_to(URL::previous(), 'Powrót', ['class' => 'btn btn-default']) !!}
</div>
{!! Form::close() !!}
@endsection
public function store(Request $request) {
$title = $request->input('title');
$content = $request->input('content');
return view('pages.create');
}
php artisan make:request PagesRequest
public function authorize() {
# return false;
return true;
}
public function rules() {
return [
'title' => 'required|max:255',
'content' => 'required',
];
}
//odblokować po przetestowaniu walidacji bez metody messages()
# public function messages() {
# return [
# 'title.required' => 'TYTUŁ jest wymagany',
# 'content.required' => 'TREŚĆ jest wymagana',
# ];
}
use App\Http\Request\PagesRequest;
/*
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param PagesRequest $request
* @return \Illuminate\Http\Response
*/
public function store(PagesRequest Request $request) {
# $title = $request->input('title');
# $content = $request->input('content');
# return view('pages.create');
Pages::create($request->all());
return redirect()->route('pages.index');
}
...
public function update(PagesRequest Request $request, Pages $page) {
$page->update($request->all());
return redirect()->route('pages.index');
}
class Pages extends Model {
//tylko wskazane pola formularz będą tworzyły rekord w Pages::create($request->all())
protected $fillable = [ 'title', 'content' ];
}
public function index() {
# $pages = Pages->paginate(10);
$pages = Pages::orderBy('id', 'DESC')->paginate(10);
return view('pages.index', compact('pages'));
}
...
@section('content')
<a class="btn btn-primary" href="{{route('pages.create')}}">Dodaj stronę</a>
...
...
Route::get('pages/edit/{page}', [
'uses' => 'PagesController@edit',
'as' => 'pages.edit',
]);
Route::put('pages/{page}', [
'uses' => 'PagesController@update',
'as' => 'pages.update',
]);
...
/**
* Show the form for editing the specified resource.
*
* param int $id
* @param \App\Pages $page
* @return \Illuminate\Http\Response
*/
public function edit(Pages $page $id) {
return view('pages.edit', compact('page'));
}
...
{!! Form::model($page, ['route' => ['pages.update', $page], 'method' => 'PUT']) !!}
@if ($errors->any())
<ul class="alert alert-danger">
@foreach ($errors->all() as $error)
{{ $error }}
@endforeach
</ul>
@endif
<div class="form-group">
{!! Form::label('title', 'Tytuł:') !!}
{!! Form::text('title', $page->title null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::label('content', 'Treść:') !!}
{!! Form::textarea('content', $page->content null, ['class' => 'form-control']) !!}
</div>
<div class="form-group">
{!! Form::submit('Zapisz', ['class' => 'btn btn-primary']) !!}
{!! link_to(URL::previous(), 'Powrót', ['class' => 'btn btn-default']) !!}
</div>
{!! Form::close() !!}
...
<a class="btn btn-danger" href="#">Delete</a>
{!! Form::model($page, ['route' => ['pages.delete', $page], 'method' => 'DELETE']) !!}
<button class="btn btn-danger">Delete</button>
{!! Form::close() !!}