Compare commits
5 commits
develop
...
add-seo-to
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8d24cd36a | ||
|
|
fab7138905 | ||
|
|
e912af7ecc | ||
|
|
1a0a865e83 | ||
|
|
7831ff3bee |
17 changed files with 203 additions and 78 deletions
|
|
@ -13,7 +13,6 @@ enum StaticPageType: int
|
|||
case confidentiality = 3;
|
||||
case home = 4;
|
||||
case ranges = 5;
|
||||
case range = 6;
|
||||
case klub = 7;
|
||||
case klub_register = 8;
|
||||
case history = 9;
|
||||
|
|
@ -29,7 +28,6 @@ enum StaticPageType: int
|
|||
self::confidentiality->name => 'Confidentialité',
|
||||
self::home->name => 'Accueil',
|
||||
self::ranges->name => 'Nos gammes',
|
||||
self::range->name => 'Une gamme',
|
||||
self::klub->name => 'Le Klub',
|
||||
self::klub_register->name => 'Le Klub - Inscription',
|
||||
self::history->name => 'Notre Histoire',
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ class NewsController extends Controller
|
|||
/**
|
||||
* Show a specific resource.
|
||||
*
|
||||
* @param \App\Models\News $frontNews
|
||||
* @param \App\Models\News $publishedNews
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(News $frontNews): \Illuminate\Contracts\View\View
|
||||
public function show(News $publishedNews): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('fo.pages.news.show', [
|
||||
'newsModel' => $frontNews
|
||||
'newsModel' => $publishedNews
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,30 +13,25 @@ class ProductController extends Controller
|
|||
/**
|
||||
* Show a specific resource.
|
||||
*
|
||||
* @param string $slug
|
||||
* @param Product $product
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(string $slug): \Illuminate\Contracts\View\View
|
||||
public function show(Product $product): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$productModel = Product::query()
|
||||
->with('range')
|
||||
->where('slug', $slug)
|
||||
->where('published', true)
|
||||
->firstOrFail();
|
||||
$productModels = Product::query()
|
||||
->where('slug', '!=', $slug)
|
||||
->whereNot('id', $product->id)
|
||||
->where('published', true)
|
||||
->inRandomOrder()->limit(2)->get();
|
||||
$klubBloc = KlubBloc::query()->first();
|
||||
$rangeModels = Range::query()->whereNot('id', $productModel->range->id)->limit(2)
|
||||
$rangeModels = Range::query()->whereNot('id', $product->range->id)->limit(2)
|
||||
->inRandomOrder()->get();
|
||||
|
||||
return view('fo.pages.products.show', compact(
|
||||
'productModel',
|
||||
'productModels',
|
||||
'klubBloc',
|
||||
'rangeModels'
|
||||
));
|
||||
return view('fo.pages.products.show', [
|
||||
'productModel' => $product,
|
||||
'productModels' => $productModels,
|
||||
'klubBloc' => $klubBloc,
|
||||
'rangeModels' => $rangeModels,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -27,30 +27,27 @@ class RangeController extends Controller
|
|||
/**
|
||||
* Show a specific resource.
|
||||
*
|
||||
* @param string $slug
|
||||
* @param \App\Models\Range $range
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(string $slug): \Illuminate\Contracts\View\View
|
||||
public function show(Range $range): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$rangeModel = Range::query()->where('slug', $slug)->firstOrFail();
|
||||
$rangeModels = Range::query()->where('slug', '!=', $slug)->limit(2)->inRandomOrder()->get();
|
||||
$productModels = Product::query()->where('range_id', $rangeModel->id)
|
||||
$rangeModels = Range::query()->whereNot('id', $range->id)->limit(2)->inRandomOrder()->get();
|
||||
$productModels = Product::query()->where('range_id', $range->id)
|
||||
->where('published', true)
|
||||
->orderBy('order', 'asc')
|
||||
->paginate(9);
|
||||
$staticPageModel = StaticPage::query()->where('type', StaticPageType::range)->first();
|
||||
$newsModels = News::query()
|
||||
$newsModels = News::query()
|
||||
->where('published', true)
|
||||
->orderBy('created_at', 'desc')
|
||||
->limit(6)
|
||||
->get();
|
||||
|
||||
return view('fo.pages.ranges.show', compact(
|
||||
'rangeModel',
|
||||
'rangeModels',
|
||||
'productModels',
|
||||
'staticPageModel',
|
||||
'newsModels'
|
||||
));
|
||||
return view('fo.pages.ranges.show', [
|
||||
'rangeModel' => $range,
|
||||
'rangeModels' => $rangeModels,
|
||||
'productModels' => $productModels,
|
||||
'newsModels' => $newsModels,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ class StoreRangeRequest extends FormRequest
|
|||
public function rules(): array
|
||||
{
|
||||
$rules = [
|
||||
'seo_title' => 'required|between:45,70',
|
||||
'seo_description' => 'required|between:50,160',
|
||||
'label' => 'required|string|between:3,255',
|
||||
'picture_alt' => 'required|string|between:3,255',
|
||||
'picture_title' => 'required|string|between:3,255',
|
||||
|
|
@ -71,6 +73,8 @@ class StoreRangeRequest extends FormRequest
|
|||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'seo_title' => trans('validation.custom.seo_title'),
|
||||
'seo_description' => trans('validation.custom.seo_description'),
|
||||
'label' => trans('validation.custom.label'),
|
||||
'picture_alt' => trans('validation.custom.attribute_alt'),
|
||||
'picture_title' => trans('validation.attributes.attribute_title'),
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property integer $id ID.
|
||||
* @property string $seo_title Utilisé pour la balise title de la page.
|
||||
* @property string $seo_description Utilisé pour la balise meta description
|
||||
* de la page.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ use Illuminate\Database\Eloquent\Model;
|
|||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property integer $id ID.
|
||||
* @property string $seo_title Utilisé pour la balise title de la page.
|
||||
* @property string $seo_description Utilisé pour la balise meta description
|
||||
* @property string $label Label de la gamme.
|
||||
* @property string $slug Slug à partir du label de la gamme.
|
||||
* @property string $picture Path de l'image de la gamme (579px * 579px).
|
||||
|
|
@ -46,6 +49,8 @@ class Range extends Model
|
|||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'seo_title',
|
||||
'seo_description',
|
||||
'label',
|
||||
'picture',
|
||||
'picture_alt',
|
||||
|
|
|
|||
|
|
@ -48,7 +48,21 @@ class RouteServiceProvider extends ServiceProvider
|
|||
->group(base_path('routes/web-fo.php'));
|
||||
});
|
||||
|
||||
Route::bind('frontNews', fn ($value) => News::query()->where('slug', $value)->firstOrFail());
|
||||
Route::bind('frontRange', fn ($value) => Range::query()->where('slug', $value)->firstOrFail());
|
||||
Route::bind(
|
||||
'publishedNews',
|
||||
fn ($value) => News::query()
|
||||
->where('published', true)
|
||||
->where('slug', $value)
|
||||
->firstOrFail()
|
||||
);
|
||||
Route::bind(
|
||||
'publishedProduct',
|
||||
fn ($value) => Product::query()
|
||||
->where('published', true)
|
||||
->where('slug', $value)
|
||||
->firstOrFail()
|
||||
);
|
||||
Route::model('user', User::class);
|
||||
Route::model('picto', Picto::class);
|
||||
Route::model('range', Range::class);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"diglactic/laravel-breadcrumbs": "^8.0",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"jenssegers/agent": "^2.6",
|
||||
"laravel/framework": "^10.0",
|
||||
"laravel/framework": "^10.34",
|
||||
"laravel/tinker": "^2.8",
|
||||
"laravel/ui": "^4.2",
|
||||
"ldc/ldccrmv4client": "^4.0",
|
||||
|
|
|
|||
50
composer.lock
generated
50
composer.lock
generated
|
|
@ -8277,16 +8277,16 @@
|
|||
},
|
||||
{
|
||||
"name": "composer/semver",
|
||||
"version": "3.4.0",
|
||||
"version": "3.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/composer/semver.git",
|
||||
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32"
|
||||
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32",
|
||||
"reference": "35e8d0af4486141bc745f23a29cc2091eb624a32",
|
||||
"url": "https://api.github.com/repos/composer/semver/zipball/c51258e759afdb17f1fd1fe83bc12baaef6309d6",
|
||||
"reference": "c51258e759afdb17f1fd1fe83bc12baaef6309d6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -8338,7 +8338,7 @@
|
|||
"support": {
|
||||
"irc": "ircs://irc.libera.chat:6697/composer",
|
||||
"issues": "https://github.com/composer/semver/issues",
|
||||
"source": "https://github.com/composer/semver/tree/3.4.0"
|
||||
"source": "https://github.com/composer/semver/tree/3.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
|
@ -8354,7 +8354,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-08-31T09:50:34+00:00"
|
||||
"time": "2024-07-12T11:35:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dealerdirect/phpcodesniffer-composer-installer",
|
||||
|
|
@ -10261,26 +10261,26 @@
|
|||
"ext-mbstring": "*",
|
||||
"ext-xml": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"myclabs/deep-copy": "^1.10.1",
|
||||
"phar-io/manifest": "^2.0.3",
|
||||
"phar-io/version": "^3.0.2",
|
||||
"myclabs/deep-copy": "^1.12.0",
|
||||
"phar-io/manifest": "^2.0.4",
|
||||
"phar-io/version": "^3.2.1",
|
||||
"php": ">=8.1",
|
||||
"phpunit/php-code-coverage": "^10.1.5",
|
||||
"phpunit/php-file-iterator": "^4.0",
|
||||
"phpunit/php-invoker": "^4.0",
|
||||
"phpunit/php-text-template": "^3.0",
|
||||
"phpunit/php-timer": "^6.0",
|
||||
"sebastian/cli-parser": "^2.0",
|
||||
"sebastian/code-unit": "^2.0",
|
||||
"sebastian/comparator": "^5.0",
|
||||
"sebastian/diff": "^5.0",
|
||||
"sebastian/environment": "^6.0",
|
||||
"sebastian/exporter": "^5.1",
|
||||
"sebastian/global-state": "^6.0.1",
|
||||
"sebastian/object-enumerator": "^5.0",
|
||||
"sebastian/recursion-context": "^5.0",
|
||||
"sebastian/type": "^4.0",
|
||||
"sebastian/version": "^4.0"
|
||||
"phpunit/php-code-coverage": "^10.1.15",
|
||||
"phpunit/php-file-iterator": "^4.1.0",
|
||||
"phpunit/php-invoker": "^4.0.0",
|
||||
"phpunit/php-text-template": "^3.0.1",
|
||||
"phpunit/php-timer": "^6.0.0",
|
||||
"sebastian/cli-parser": "^2.0.1",
|
||||
"sebastian/code-unit": "^2.0.0",
|
||||
"sebastian/comparator": "^5.0.1",
|
||||
"sebastian/diff": "^5.1.1",
|
||||
"sebastian/environment": "^6.1.0",
|
||||
"sebastian/exporter": "^5.1.2",
|
||||
"sebastian/global-state": "^6.0.2",
|
||||
"sebastian/object-enumerator": "^5.0.0",
|
||||
"sebastian/recursion-context": "^5.0.0",
|
||||
"sebastian/type": "^4.0.0",
|
||||
"sebastian/version": "^4.0.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-soap": "To be able to generate mocks based on WSDL files"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ class RangeFactory extends Factory
|
|||
{
|
||||
$label = fake()->text(15);
|
||||
return [
|
||||
'seo_title' => fake()->sentence(),
|
||||
'seo_description' => fake()->sentence(),
|
||||
'label' => $label,
|
||||
'slug' => Str::slug($label),
|
||||
'picture_alt' => fake()->sentence(),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
$ranges = DB::table('ranges')->get();
|
||||
Schema::table('ranges', function (Blueprint $table) {
|
||||
$table->string('seo_title')->after('id')
|
||||
->comment('Utilisé pour la balise title de la page de gamme');
|
||||
$table->string('seo_description')->after('seo_title')
|
||||
->comment('Utilisé pour la balise meta description de la page de gamme');
|
||||
});
|
||||
$ranges->each(function (object $range) {
|
||||
DB::table('ranges')->where('id', $range->id)
|
||||
->update([
|
||||
'seo_title' => $range->label,
|
||||
'seo_description' => $range->label,
|
||||
]);
|
||||
});
|
||||
// The 6th value in the StaticPageType Enum has been removed, so we need to use the value instead of the enum.
|
||||
DB::table('static_pages')->where('type', 6)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('ranges', function (Blueprint $table) {
|
||||
$table->dropColumn('seo_title');
|
||||
$table->dropColumn('seo_description');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -69,16 +69,6 @@ class StaticPageSeeder extends Seeder
|
|||
'content' => \clean(\fake()->randomHtml(2, 3)),
|
||||
]
|
||||
)->saveQuietly();
|
||||
StaticPage::query()->make(
|
||||
[
|
||||
'seo_title' => 'Seo title pour la page Une Gamme',
|
||||
'seo_description' => 'Seo description pour la page Une Gamme',
|
||||
'title' => 'Une Gamme',
|
||||
'slug' => Str::slug('Une Gamme'),
|
||||
'type' => StaticPageType::range,
|
||||
'content' => \clean(\fake()->randomHtml(2, 3)),
|
||||
]
|
||||
)->saveQuietly();
|
||||
StaticPage::query()->make(
|
||||
[
|
||||
'seo_title' => 'Seo title pour la page Actualités',
|
||||
|
|
|
|||
|
|
@ -1,4 +1,76 @@
|
|||
<div class="row">
|
||||
{{-- SEO --}}
|
||||
<div class="col-12 pb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
<legend>{{ Str::ucfirst(__('validation.custom.seo')) }}</legend>
|
||||
<div class="row mb-3">
|
||||
{{-- SEO_TITLE --}}
|
||||
<div class="col-12 col-md-6 m-md-0 mb-3">
|
||||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'rangeSeoTitle',
|
||||
'label' => __(':field :inter:model', [
|
||||
'field' => Str::ucfirst(__('validation.custom.seo_title')),
|
||||
'inter' => __('validation.custom.of_the.male'),
|
||||
'model' => __('models.classes.range'),
|
||||
]),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'seo_title',
|
||||
'required' => true,
|
||||
'model' => $rangeModel ?? null,
|
||||
'helper' => sprintf(
|
||||
'%s %s',
|
||||
__('crud.helpers.seo_title'),
|
||||
__('validation.between.string', [
|
||||
'attribute' => __(':field :inter:model', [
|
||||
'field' => __('validation.custom.seo_title'),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => __('models.classes.range'),
|
||||
]),
|
||||
'min' => 45,
|
||||
'max' => 70,
|
||||
])),
|
||||
'placeholder' => __(':field :inter:model', [
|
||||
'field' => Str::ucfirst(__('validation.custom.seo_title')),
|
||||
'inter' => __('validation.custom.of_the.male'),
|
||||
'model' => __('models.classes.range'),
|
||||
]),
|
||||
])
|
||||
</div>
|
||||
{{-- SEO_DESCRIPTION --}}
|
||||
<div class="col-12 col-md-6 m-md-0 mb-3">
|
||||
@include('bo.partials.inputs.varchar-multiline', [
|
||||
'id' => 'rangeSeoDescription',
|
||||
'label' => __(':field :inter:model', [
|
||||
'field' => Str::ucfirst(__('validation.custom.seo_description')),
|
||||
'inter' => __('validation.custom.of_the.male'),
|
||||
'model' => __('models.classes.range'),
|
||||
]),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'seo_description',
|
||||
'required' => true,
|
||||
'model' => $rangeModel ?? null,
|
||||
'helper' => sprintf(
|
||||
'%s %s',
|
||||
__('crud.helpers.seo_description'),
|
||||
__('validation.between.string', [
|
||||
'attribute' => __(':field :inter:model', [
|
||||
'field' => __('validation.custom.seo_description'),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => __('models.classes.range'),
|
||||
]),
|
||||
'min' => 50,
|
||||
'max' => 160,
|
||||
])),
|
||||
'placeholder' => __(':field :inter:model', [
|
||||
'field' => Str::ucfirst(__('validation.custom.seo_description')),
|
||||
'inter' => __('validation.custom.of_the.male'),
|
||||
'model' => __('models.classes.range'),
|
||||
]),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
{{-- LABEL --}}
|
||||
<div class="col-12 col-md-6 mb-3">
|
||||
<fieldset class="h-100 border p-3">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
@extends('fo.layout')
|
||||
|
||||
@section('title', __($staticPageModel->seo_title))
|
||||
@section('description', __($staticPageModel->seo_description))
|
||||
@section('title', __($rangeModel->seo_title))
|
||||
@section('description', __($rangeModel->seo_description))
|
||||
@section('breadcrumb',
|
||||
request()->route()->getName())
|
||||
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@
|
|||
}
|
||||
window.__SYSTEM._routes.fo = {
|
||||
ranges: {
|
||||
show: "{{ route('fo.ranges.show', ['slug' => 'SLUG']) }}"
|
||||
show: "{{ route('fo.ranges.show', ['frontRange' => 'SLUG']) }}"
|
||||
},
|
||||
products: {
|
||||
filtered: "{{ route('fo.products.filtered') }}",
|
||||
show: "{{ route('fo.products.show', ['slug' => 'SLUG']) }}"
|
||||
show: "{{ route('fo.products.show', ['publishedProduct' => 'SLUG']) }}"
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -58,15 +58,15 @@ Route::middleware(['throttle:credentials'])->name('fo.')->group(function () {
|
|||
|
||||
// * NEWS
|
||||
Route::get('/actualites', [NewsController::class, 'index'])->name('news.index');
|
||||
Route::get('/actualites/{frontNews:slug}', [NewsController::class, 'show'])->name('news.show');
|
||||
Route::get('/actualites/{publishedNews:slug}', [NewsController::class, 'show'])->name('news.show');
|
||||
|
||||
// * RANGES
|
||||
Route::get('/gammes', [RangeController::class, 'index'])->name('ranges.index');
|
||||
Route::get('/gamme/{slug}', [RangeController::class, 'show'])->name('ranges.show');
|
||||
Route::get('/gamme/{frontRange:slug}', [RangeController::class, 'show'])->name('ranges.show');
|
||||
|
||||
// * PRODUCTS
|
||||
Route::get('/produit/filtered', [ProductController::class, 'productsFiltered'])->name('products.filtered');
|
||||
Route::get('/produit/{slug}', [ProductController::class, 'show'])->name('products.show');
|
||||
Route::get('/produit/{publishedProduct:slug}', [ProductController::class, 'show'])->name('products.show');
|
||||
|
||||
// * COMMITMENTS
|
||||
Route::get('/nos-engagements', [CommitmentController::class, 'show'])->name('commitments.show');
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue